mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-21 17:26:29 -05:00
feat: submit own style index on realtime user state set
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
b538c2c2a3
commit
24b7514e25
8 changed files with 157 additions and 91 deletions
|
@ -77,28 +77,34 @@ describe('realtime user status adapter', () => {
|
||||||
|
|
||||||
const expectedMessage1: Message<MessageType.REALTIME_USER_STATE_SET> = {
|
const expectedMessage1: Message<MessageType.REALTIME_USER_STATE_SET> = {
|
||||||
type: MessageType.REALTIME_USER_STATE_SET,
|
type: MessageType.REALTIME_USER_STATE_SET,
|
||||||
payload: [
|
payload: {
|
||||||
{
|
ownUser: {
|
||||||
active: true,
|
styleIndex: 0,
|
||||||
cursor: {
|
displayName: username1,
|
||||||
from: 0,
|
|
||||||
to: 0,
|
|
||||||
},
|
|
||||||
styleIndex: 1,
|
|
||||||
username: username2,
|
|
||||||
displayName: username2,
|
|
||||||
},
|
},
|
||||||
{
|
users: [
|
||||||
active: true,
|
{
|
||||||
cursor: {
|
active: true,
|
||||||
from: 0,
|
cursor: {
|
||||||
to: 0,
|
from: 0,
|
||||||
|
to: 0,
|
||||||
|
},
|
||||||
|
styleIndex: 1,
|
||||||
|
username: username2,
|
||||||
|
displayName: username2,
|
||||||
},
|
},
|
||||||
styleIndex: 2,
|
{
|
||||||
username: username3,
|
active: true,
|
||||||
displayName: username3,
|
cursor: {
|
||||||
},
|
from: 0,
|
||||||
],
|
to: 0,
|
||||||
|
},
|
||||||
|
styleIndex: 2,
|
||||||
|
username: username3,
|
||||||
|
displayName: username3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
expect(sendMessage1Spy).toHaveBeenNthCalledWith(1, expectedMessage1);
|
expect(sendMessage1Spy).toHaveBeenNthCalledWith(1, expectedMessage1);
|
||||||
expect(sendMessage2Spy).toHaveBeenCalledTimes(0);
|
expect(sendMessage2Spy).toHaveBeenCalledTimes(0);
|
||||||
|
@ -125,54 +131,66 @@ describe('realtime user status adapter', () => {
|
||||||
|
|
||||||
const expectedMessage2: Message<MessageType.REALTIME_USER_STATE_SET> = {
|
const expectedMessage2: Message<MessageType.REALTIME_USER_STATE_SET> = {
|
||||||
type: MessageType.REALTIME_USER_STATE_SET,
|
type: MessageType.REALTIME_USER_STATE_SET,
|
||||||
payload: [
|
payload: {
|
||||||
{
|
ownUser: {
|
||||||
active: true,
|
styleIndex: 1,
|
||||||
cursor: {
|
displayName: username2,
|
||||||
from: newFrom,
|
|
||||||
to: newTo,
|
|
||||||
},
|
|
||||||
styleIndex: 0,
|
|
||||||
username: username1,
|
|
||||||
displayName: username1,
|
|
||||||
},
|
},
|
||||||
{
|
users: [
|
||||||
active: true,
|
{
|
||||||
cursor: {
|
active: true,
|
||||||
from: 0,
|
cursor: {
|
||||||
to: 0,
|
from: newFrom,
|
||||||
|
to: newTo,
|
||||||
|
},
|
||||||
|
styleIndex: 0,
|
||||||
|
username: username1,
|
||||||
|
displayName: username1,
|
||||||
},
|
},
|
||||||
styleIndex: 2,
|
{
|
||||||
username: username3,
|
active: true,
|
||||||
displayName: username3,
|
cursor: {
|
||||||
},
|
from: 0,
|
||||||
],
|
to: 0,
|
||||||
|
},
|
||||||
|
styleIndex: 2,
|
||||||
|
username: username3,
|
||||||
|
displayName: username3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const expectedMessage3: Message<MessageType.REALTIME_USER_STATE_SET> = {
|
const expectedMessage3: Message<MessageType.REALTIME_USER_STATE_SET> = {
|
||||||
type: MessageType.REALTIME_USER_STATE_SET,
|
type: MessageType.REALTIME_USER_STATE_SET,
|
||||||
payload: [
|
payload: {
|
||||||
{
|
ownUser: {
|
||||||
active: true,
|
styleIndex: 2,
|
||||||
cursor: {
|
displayName: username3,
|
||||||
from: newFrom,
|
|
||||||
to: newTo,
|
|
||||||
},
|
|
||||||
styleIndex: 0,
|
|
||||||
username: username1,
|
|
||||||
displayName: username1,
|
|
||||||
},
|
},
|
||||||
{
|
users: [
|
||||||
active: true,
|
{
|
||||||
cursor: {
|
active: true,
|
||||||
from: 0,
|
cursor: {
|
||||||
to: 0,
|
from: newFrom,
|
||||||
|
to: newTo,
|
||||||
|
},
|
||||||
|
styleIndex: 0,
|
||||||
|
username: username1,
|
||||||
|
displayName: username1,
|
||||||
},
|
},
|
||||||
styleIndex: 1,
|
{
|
||||||
username: username2,
|
active: true,
|
||||||
displayName: username2,
|
cursor: {
|
||||||
},
|
from: 0,
|
||||||
],
|
to: 0,
|
||||||
|
},
|
||||||
|
styleIndex: 1,
|
||||||
|
username: username2,
|
||||||
|
displayName: username2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(sendMessage1Spy).toHaveBeenCalledTimes(0);
|
expect(sendMessage1Spy).toHaveBeenCalledTimes(0);
|
||||||
|
@ -191,34 +209,46 @@ describe('realtime user status adapter', () => {
|
||||||
|
|
||||||
const expectedMessage1: Message<MessageType.REALTIME_USER_STATE_SET> = {
|
const expectedMessage1: Message<MessageType.REALTIME_USER_STATE_SET> = {
|
||||||
type: MessageType.REALTIME_USER_STATE_SET,
|
type: MessageType.REALTIME_USER_STATE_SET,
|
||||||
payload: [
|
payload: {
|
||||||
{
|
ownUser: {
|
||||||
active: true,
|
styleIndex: 0,
|
||||||
cursor: {
|
displayName: username1,
|
||||||
from: 0,
|
|
||||||
to: 0,
|
|
||||||
},
|
|
||||||
styleIndex: 2,
|
|
||||||
username: username3,
|
|
||||||
displayName: username3,
|
|
||||||
},
|
},
|
||||||
],
|
users: [
|
||||||
|
{
|
||||||
|
active: true,
|
||||||
|
cursor: {
|
||||||
|
from: 0,
|
||||||
|
to: 0,
|
||||||
|
},
|
||||||
|
styleIndex: 2,
|
||||||
|
username: username3,
|
||||||
|
displayName: username3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const expectedMessage3: Message<MessageType.REALTIME_USER_STATE_SET> = {
|
const expectedMessage3: Message<MessageType.REALTIME_USER_STATE_SET> = {
|
||||||
type: MessageType.REALTIME_USER_STATE_SET,
|
type: MessageType.REALTIME_USER_STATE_SET,
|
||||||
payload: [
|
payload: {
|
||||||
{
|
ownUser: {
|
||||||
active: true,
|
styleIndex: 2,
|
||||||
cursor: {
|
displayName: username3,
|
||||||
from: 0,
|
|
||||||
to: 0,
|
|
||||||
},
|
|
||||||
styleIndex: 0,
|
|
||||||
username: username1,
|
|
||||||
displayName: username1,
|
|
||||||
},
|
},
|
||||||
],
|
users: [
|
||||||
|
{
|
||||||
|
active: true,
|
||||||
|
cursor: {
|
||||||
|
from: 0,
|
||||||
|
to: 0,
|
||||||
|
},
|
||||||
|
styleIndex: 0,
|
||||||
|
username: username1,
|
||||||
|
displayName: username1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(sendMessage1Spy).toHaveBeenNthCalledWith(1, expectedMessage1);
|
expect(sendMessage1Spy).toHaveBeenNthCalledWith(1, expectedMessage1);
|
||||||
|
|
|
@ -94,13 +94,21 @@ export class RealtimeUserStatusAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private sendCompleteStateToClient(client: RealtimeConnection): void {
|
private sendCompleteStateToClient(client: RealtimeConnection): void {
|
||||||
const payload = this.collectAllConnectionsExcept(client).map(
|
const realtimeUsers = this.collectAllConnectionsExcept(client).map(
|
||||||
(client) => client.getRealtimeUserStateAdapter().realtimeUser,
|
(client) => client.getRealtimeUserStateAdapter().realtimeUser,
|
||||||
);
|
);
|
||||||
|
|
||||||
client.getTransporter().sendMessage({
|
client.getTransporter().sendMessage({
|
||||||
type: MessageType.REALTIME_USER_STATE_SET,
|
type: MessageType.REALTIME_USER_STATE_SET,
|
||||||
payload,
|
payload: {
|
||||||
|
users: realtimeUsers,
|
||||||
|
ownUser: {
|
||||||
|
displayName:
|
||||||
|
client.getRealtimeUserStateAdapter().realtimeUser.displayName,
|
||||||
|
styleIndex:
|
||||||
|
client.getRealtimeUserStateAdapter().realtimeUser.styleIndex,
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,13 @@ export enum MessageType {
|
||||||
export interface MessagePayloads {
|
export interface MessagePayloads {
|
||||||
[MessageType.NOTE_CONTENT_STATE_REQUEST]: number[]
|
[MessageType.NOTE_CONTENT_STATE_REQUEST]: number[]
|
||||||
[MessageType.NOTE_CONTENT_UPDATE]: number[]
|
[MessageType.NOTE_CONTENT_UPDATE]: number[]
|
||||||
[MessageType.REALTIME_USER_STATE_SET]: RealtimeUser[]
|
[MessageType.REALTIME_USER_STATE_SET]: {
|
||||||
|
users: RealtimeUser[]
|
||||||
|
ownUser: {
|
||||||
|
displayName: string
|
||||||
|
styleIndex: number
|
||||||
|
}
|
||||||
|
}
|
||||||
[MessageType.REALTIME_USER_SINGLE_UPDATE]: RemoteCursor
|
[MessageType.REALTIME_USER_SINGLE_UPDATE]: RemoteCursor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ export class ReceiveRemoteCursorViewPlugin implements PluginValue {
|
||||||
this.listener = messageTransporter.on(
|
this.listener = messageTransporter.on(
|
||||||
MessageType.REALTIME_USER_STATE_SET,
|
MessageType.REALTIME_USER_STATE_SET,
|
||||||
({ payload }) => {
|
({ payload }) => {
|
||||||
const cursors: RemoteCursor[] = payload.map((user) => ({
|
const cursors: RemoteCursor[] = payload.users.map((user) => ({
|
||||||
from: user.cursor.from,
|
from: user.cursor.from,
|
||||||
to: user.cursor.to,
|
to: user.cursor.to,
|
||||||
displayName: user.displayName,
|
displayName: user.displayName,
|
||||||
|
|
|
@ -21,7 +21,12 @@ export const useReceiveRealtimeUsers = (messageTransporter: MessageTransporter):
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const listener = messageTransporter.on(
|
const listener = messageTransporter.on(
|
||||||
MessageType.REALTIME_USER_STATE_SET,
|
MessageType.REALTIME_USER_STATE_SET,
|
||||||
(payload) => setRealtimeUsers(payload.payload),
|
(message) =>
|
||||||
|
setRealtimeUsers(
|
||||||
|
message.payload.users,
|
||||||
|
message.payload.ownUser.styleIndex,
|
||||||
|
message.payload.ownUser.displayName
|
||||||
|
),
|
||||||
{ objectify: true }
|
{ objectify: true }
|
||||||
) as Listener
|
) as Listener
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,14 @@ import type { RealtimeUser } from '@hedgedoc/commons'
|
||||||
/**
|
/**
|
||||||
* Dispatches an event to add a user
|
* Dispatches an event to add a user
|
||||||
*/
|
*/
|
||||||
export const setRealtimeUsers = (users: RealtimeUser[]): void => {
|
export const setRealtimeUsers = (users: RealtimeUser[], ownStyleIndex: number, ownDisplayName: string): void => {
|
||||||
const action: SetRealtimeUsersAction = {
|
const action: SetRealtimeUsersAction = {
|
||||||
type: RealtimeStatusActionType.SET_REALTIME_USERS,
|
type: RealtimeStatusActionType.SET_REALTIME_USERS,
|
||||||
users
|
users,
|
||||||
|
ownUser: {
|
||||||
|
styleIndex: ownStyleIndex,
|
||||||
|
displayName: ownDisplayName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
store.dispatch(action)
|
store.dispatch(action)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,11 @@ import type { Reducer } from 'redux'
|
||||||
const initialState: RealtimeStatus = {
|
const initialState: RealtimeStatus = {
|
||||||
isSynced: false,
|
isSynced: false,
|
||||||
isConnected: false,
|
isConnected: false,
|
||||||
onlineUsers: []
|
onlineUsers: [],
|
||||||
|
ownUser: {
|
||||||
|
displayName: '',
|
||||||
|
styleIndex: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +32,8 @@ export const RealtimeStatusReducer: Reducer<RealtimeStatus, RealtimeStatusAction
|
||||||
case RealtimeStatusActionType.SET_REALTIME_USERS:
|
case RealtimeStatusActionType.SET_REALTIME_USERS:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
onlineUsers: action.users
|
onlineUsers: action.users,
|
||||||
|
ownUser: action.ownUser
|
||||||
}
|
}
|
||||||
case RealtimeStatusActionType.SET_REALTIME_CONNECTION_STATUS:
|
case RealtimeStatusActionType.SET_REALTIME_CONNECTION_STATUS:
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -16,6 +16,10 @@ export enum RealtimeStatusActionType {
|
||||||
export interface SetRealtimeUsersAction extends Action<RealtimeStatusActionType> {
|
export interface SetRealtimeUsersAction extends Action<RealtimeStatusActionType> {
|
||||||
type: RealtimeStatusActionType.SET_REALTIME_USERS
|
type: RealtimeStatusActionType.SET_REALTIME_USERS
|
||||||
users: RealtimeUser[]
|
users: RealtimeUser[]
|
||||||
|
ownUser: {
|
||||||
|
styleIndex: number
|
||||||
|
displayName: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SetRealtimeConnectionStatusAction extends Action<RealtimeStatusActionType> {
|
export interface SetRealtimeConnectionStatusAction extends Action<RealtimeStatusActionType> {
|
||||||
|
@ -36,6 +40,10 @@ export interface RealtimeStatus {
|
||||||
onlineUsers: RealtimeUser[]
|
onlineUsers: RealtimeUser[]
|
||||||
isConnected: boolean
|
isConnected: boolean
|
||||||
isSynced: boolean
|
isSynced: boolean
|
||||||
|
ownUser: {
|
||||||
|
displayName: string
|
||||||
|
styleIndex: number
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RealtimeStatusActions =
|
export type RealtimeStatusActions =
|
||||||
|
|
Loading…
Reference in a new issue