diff --git a/backend/src/realtime/realtime-note/realtime-user-status-adapter.spec.ts b/backend/src/realtime/realtime-note/realtime-user-status-adapter.spec.ts index 634e0476b..7ebe9884f 100644 --- a/backend/src/realtime/realtime-note/realtime-user-status-adapter.spec.ts +++ b/backend/src/realtime/realtime-note/realtime-user-status-adapter.spec.ts @@ -77,28 +77,34 @@ describe('realtime user status adapter', () => { const expectedMessage1: Message = { type: MessageType.REALTIME_USER_STATE_SET, - payload: [ - { - active: true, - cursor: { - from: 0, - to: 0, - }, - styleIndex: 1, - username: username2, - displayName: username2, + payload: { + ownUser: { + styleIndex: 0, + displayName: username1, }, - { - active: true, - cursor: { - from: 0, - to: 0, + users: [ + { + active: true, + cursor: { + from: 0, + to: 0, + }, + styleIndex: 1, + username: username2, + displayName: username2, }, - styleIndex: 2, - username: username3, - displayName: username3, - }, - ], + { + active: true, + cursor: { + from: 0, + to: 0, + }, + styleIndex: 2, + username: username3, + displayName: username3, + }, + ], + }, }; expect(sendMessage1Spy).toHaveBeenNthCalledWith(1, expectedMessage1); expect(sendMessage2Spy).toHaveBeenCalledTimes(0); @@ -125,54 +131,66 @@ describe('realtime user status adapter', () => { const expectedMessage2: Message = { type: MessageType.REALTIME_USER_STATE_SET, - payload: [ - { - active: true, - cursor: { - from: newFrom, - to: newTo, - }, - styleIndex: 0, - username: username1, - displayName: username1, + payload: { + ownUser: { + styleIndex: 1, + displayName: username2, }, - { - active: true, - cursor: { - from: 0, - to: 0, + users: [ + { + active: true, + cursor: { + from: newFrom, + to: newTo, + }, + styleIndex: 0, + username: username1, + displayName: username1, }, - styleIndex: 2, - username: username3, - displayName: username3, - }, - ], + { + active: true, + cursor: { + from: 0, + to: 0, + }, + styleIndex: 2, + username: username3, + displayName: username3, + }, + ], + }, }; const expectedMessage3: Message = { type: MessageType.REALTIME_USER_STATE_SET, - payload: [ - { - active: true, - cursor: { - from: newFrom, - to: newTo, - }, - styleIndex: 0, - username: username1, - displayName: username1, + payload: { + ownUser: { + styleIndex: 2, + displayName: username3, }, - { - active: true, - cursor: { - from: 0, - to: 0, + users: [ + { + active: true, + cursor: { + from: newFrom, + to: newTo, + }, + styleIndex: 0, + username: username1, + displayName: username1, }, - styleIndex: 1, - username: username2, - displayName: username2, - }, - ], + { + active: true, + cursor: { + from: 0, + to: 0, + }, + styleIndex: 1, + username: username2, + displayName: username2, + }, + ], + }, }; expect(sendMessage1Spy).toHaveBeenCalledTimes(0); @@ -191,34 +209,46 @@ describe('realtime user status adapter', () => { const expectedMessage1: Message = { type: MessageType.REALTIME_USER_STATE_SET, - payload: [ - { - active: true, - cursor: { - from: 0, - to: 0, - }, - styleIndex: 2, - username: username3, - displayName: username3, + payload: { + ownUser: { + styleIndex: 0, + displayName: username1, }, - ], + users: [ + { + active: true, + cursor: { + from: 0, + to: 0, + }, + styleIndex: 2, + username: username3, + displayName: username3, + }, + ], + }, }; const expectedMessage3: Message = { type: MessageType.REALTIME_USER_STATE_SET, - payload: [ - { - active: true, - cursor: { - from: 0, - to: 0, - }, - styleIndex: 0, - username: username1, - displayName: username1, + payload: { + ownUser: { + styleIndex: 2, + displayName: username3, }, - ], + users: [ + { + active: true, + cursor: { + from: 0, + to: 0, + }, + styleIndex: 0, + username: username1, + displayName: username1, + }, + ], + }, }; expect(sendMessage1Spy).toHaveBeenNthCalledWith(1, expectedMessage1); diff --git a/backend/src/realtime/realtime-note/realtime-user-status-adapter.ts b/backend/src/realtime/realtime-note/realtime-user-status-adapter.ts index 12ab29d53..7ee3e2522 100644 --- a/backend/src/realtime/realtime-note/realtime-user-status-adapter.ts +++ b/backend/src/realtime/realtime-note/realtime-user-status-adapter.ts @@ -94,13 +94,21 @@ export class RealtimeUserStatusAdapter { } private sendCompleteStateToClient(client: RealtimeConnection): void { - const payload = this.collectAllConnectionsExcept(client).map( + const realtimeUsers = this.collectAllConnectionsExcept(client).map( (client) => client.getRealtimeUserStateAdapter().realtimeUser, ); client.getTransporter().sendMessage({ type: MessageType.REALTIME_USER_STATE_SET, - payload, + payload: { + users: realtimeUsers, + ownUser: { + displayName: + client.getRealtimeUserStateAdapter().realtimeUser.displayName, + styleIndex: + client.getRealtimeUserStateAdapter().realtimeUser.styleIndex, + }, + }, }); } diff --git a/commons/src/message-transporters/message.ts b/commons/src/message-transporters/message.ts index 5ddfe1a03..dfb2e410c 100644 --- a/commons/src/message-transporters/message.ts +++ b/commons/src/message-transporters/message.ts @@ -22,7 +22,13 @@ export enum MessageType { export interface MessagePayloads { [MessageType.NOTE_CONTENT_STATE_REQUEST]: 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 } diff --git a/frontend/src/components/editor-page/editor-pane/codemirror-extensions/remote-cursors/receive-remote-cursor-view-plugin.ts b/frontend/src/components/editor-page/editor-pane/codemirror-extensions/remote-cursors/receive-remote-cursor-view-plugin.ts index 5c61e1ecf..7656b4e4e 100644 --- a/frontend/src/components/editor-page/editor-pane/codemirror-extensions/remote-cursors/receive-remote-cursor-view-plugin.ts +++ b/frontend/src/components/editor-page/editor-pane/codemirror-extensions/remote-cursors/receive-remote-cursor-view-plugin.ts @@ -20,7 +20,7 @@ export class ReceiveRemoteCursorViewPlugin implements PluginValue { this.listener = messageTransporter.on( MessageType.REALTIME_USER_STATE_SET, ({ payload }) => { - const cursors: RemoteCursor[] = payload.map((user) => ({ + const cursors: RemoteCursor[] = payload.users.map((user) => ({ from: user.cursor.from, to: user.cursor.to, displayName: user.displayName, diff --git a/frontend/src/components/editor-page/editor-pane/hooks/yjs/use-receive-realtime-users.ts b/frontend/src/components/editor-page/editor-pane/hooks/yjs/use-receive-realtime-users.ts index e409e3947..a8d44b3d3 100644 --- a/frontend/src/components/editor-page/editor-pane/hooks/yjs/use-receive-realtime-users.ts +++ b/frontend/src/components/editor-page/editor-pane/hooks/yjs/use-receive-realtime-users.ts @@ -21,7 +21,12 @@ export const useReceiveRealtimeUsers = (messageTransporter: MessageTransporter): useEffect(() => { const listener = messageTransporter.on( MessageType.REALTIME_USER_STATE_SET, - (payload) => setRealtimeUsers(payload.payload), + (message) => + setRealtimeUsers( + message.payload.users, + message.payload.ownUser.styleIndex, + message.payload.ownUser.displayName + ), { objectify: true } ) as Listener diff --git a/frontend/src/redux/realtime/methods.ts b/frontend/src/redux/realtime/methods.ts index 39011435f..8e8d0997d 100644 --- a/frontend/src/redux/realtime/methods.ts +++ b/frontend/src/redux/realtime/methods.ts @@ -11,10 +11,14 @@ import type { RealtimeUser } from '@hedgedoc/commons' /** * 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 = { type: RealtimeStatusActionType.SET_REALTIME_USERS, - users + users, + ownUser: { + styleIndex: ownStyleIndex, + displayName: ownDisplayName + } } store.dispatch(action) } diff --git a/frontend/src/redux/realtime/reducers.ts b/frontend/src/redux/realtime/reducers.ts index 50655c6d6..8f3cfcc5f 100644 --- a/frontend/src/redux/realtime/reducers.ts +++ b/frontend/src/redux/realtime/reducers.ts @@ -10,7 +10,11 @@ import type { Reducer } from 'redux' const initialState: RealtimeStatus = { isSynced: false, isConnected: false, - onlineUsers: [] + onlineUsers: [], + ownUser: { + displayName: '', + styleIndex: 0 + } } /** @@ -28,7 +32,8 @@ export const RealtimeStatusReducer: Reducer { type: RealtimeStatusActionType.SET_REALTIME_USERS users: RealtimeUser[] + ownUser: { + styleIndex: number + displayName: string + } } export interface SetRealtimeConnectionStatusAction extends Action { @@ -36,6 +40,10 @@ export interface RealtimeStatus { onlineUsers: RealtimeUser[] isConnected: boolean isSynced: boolean + ownUser: { + displayName: string + styleIndex: number + } } export type RealtimeStatusActions =