From 1189420867466d5ea5ee496ea0c1dcf9a6b3fbc5 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Thu, 7 Nov 2024 13:40:20 +0000 Subject: [PATCH] refactor: misc formating and code review changes, comment tidyup --- demo/src/App.tsx | 20 ++++++++++++++++++-- demo/src/containers/Chat/Chat.tsx | 7 ++----- src/core/discontinuity.ts | 2 +- src/core/messages.ts | 5 ++--- src/core/occupancy.ts | 3 +-- src/core/presence.ts | 6 +++--- src/core/room-lifecycle-manager.ts | 2 +- src/core/room-reactions.ts | 3 +-- src/core/room.ts | 1 - src/core/rooms.ts | 5 +++-- src/core/typing.ts | 6 +++--- src/react/helper/room-promise.ts | 5 ++--- 12 files changed, 37 insertions(+), 28 deletions(-) diff --git a/demo/src/App.tsx b/demo/src/App.tsx index 8ef6c724..76aea3f4 100644 --- a/demo/src/App.tsx +++ b/demo/src/App.tsx @@ -1,4 +1,4 @@ -import { FC, useState } from 'react'; +import { FC, useEffect, useState } from 'react'; import { Chat } from './containers/Chat'; import { OccupancyComponent } from './components/OccupancyComponent'; import { UserPresenceComponent } from './components/UserPresenceComponent'; @@ -28,10 +28,26 @@ const App: FC = () => { const updateRoomId = (newRoomId: string) => { const params = new URLSearchParams(window.location.search); params.set('room', newRoomId); - history.replaceState(null, '', '?' + params.toString()); + history.pushState(null, '', '?' + params.toString()); setRoomId(newRoomId); }; + // Add a useEffect that handles the popstate event to update the roomId when + // the user navigates back and forth in the browser history. + useEffect(() => { + const handlePopState = () => { + const params = new URLSearchParams(window.location.search); + const newRoomId = params.get('room') || 'abcd'; + setRoomId(newRoomId); + }; + + window.addEventListener('popstate', handlePopState); + + return () => { + window.removeEventListener('popstate', handlePopState); + }; + }, []); + return ( voi chatClient.logger.error('Error fetching initial messages', error); }); } - } + }; - const { - send: sendMessage, - getPreviousMessages, - } = useMessages({ + const { send: sendMessage, getPreviousMessages } = useMessages({ listener: (message: MessageEventPayload) => { setMessages((prevMessage) => [...prevMessage, message.message]); }, diff --git a/src/core/discontinuity.ts b/src/core/discontinuity.ts index da6dde58..995ec563 100644 --- a/src/core/discontinuity.ts +++ b/src/core/discontinuity.ts @@ -7,7 +7,7 @@ import EventEmitter from './utils/event-emitter.js'; */ export interface HandlesDiscontinuity { /** - * A promise of the channel that this object is associated with. The promise + * A channel that this object is associated with. The promise * is resolved when the feature has finished initializing. */ get channel(): Ably.RealtimeChannel; diff --git a/src/core/messages.ts b/src/core/messages.ts index 2fa33e1e..dc524f95 100644 --- a/src/core/messages.ts +++ b/src/core/messages.ts @@ -191,7 +191,7 @@ export interface Messages extends EmitsDiscontinuities { /** * Get the underlying Ably realtime channel used for the messages in this chat room. * - * @returns A promise of the realtime channel. + * @returns The realtime channel. */ get channel(): Ably.RealtimeChannel; } @@ -223,7 +223,6 @@ export class DefaultMessages * @param chatApi An instance of the ChatApi. * @param clientId The client ID of the user. * @param logger An instance of the Logger. - * @param initAfter A promise that is awaited before creating any channels. */ constructor(roomId: string, realtime: Ably.Realtime, chatApi: ChatApi, clientId: string, logger: Logger) { super(); @@ -238,7 +237,7 @@ export class DefaultMessages } /** - * Creates the realtime channel for messages. Called after initAfter is resolved. + * Creates the realtime channel for messages. */ private _makeChannel(roomId: string, realtime: Ably.Realtime): Ably.RealtimeChannel { const channel = getChannel(messagesChannelName(roomId), realtime); diff --git a/src/core/occupancy.ts b/src/core/occupancy.ts index 0ce8eb4f..b6f29227 100644 --- a/src/core/occupancy.ts +++ b/src/core/occupancy.ts @@ -109,7 +109,6 @@ export class DefaultOccupancy * @param realtime An instance of the Ably Realtime client. * @param chatApi An instance of the ChatApi. * @param logger An instance of the Logger. - * @param initAfter A promise that is awaited before creating any channels. */ constructor(roomId: string, realtime: Ably.Realtime, chatApi: ChatApi, logger: Logger) { super(); @@ -121,7 +120,7 @@ export class DefaultOccupancy } /** - * Creates the realtime channel for occupancy. Called after initAfter is resolved. + * Creates the realtime channel for occupancy. */ private _makeChannel(roomId: string, realtime: Ably.Realtime): Ably.RealtimeChannel { const channel = getChannel(messagesChannelName(roomId), realtime, { params: { occupancy: 'metrics' } }); diff --git a/src/core/presence.ts b/src/core/presence.ts index a7f097d7..512554b3 100644 --- a/src/core/presence.ts +++ b/src/core/presence.ts @@ -178,7 +178,7 @@ export interface Presence extends EmitsDiscontinuities { /** * Get the underlying Ably realtime channel used for presence in this chat room. - * @returns A promise of the realtime channel. + * @returns The realtime channel. */ get channel(): Ably.RealtimeChannel; } @@ -203,7 +203,6 @@ export class DefaultPresence * @param clientId The client ID, attached to presences messages as an identifier of the sender. * A channel can have multiple connections using the same clientId. * @param logger An instance of the Logger. - * @param initAfter A promise that is awaited before creating any channels. */ constructor(roomId: string, roomOptions: RoomOptions, realtime: Ably.Realtime, clientId: string, logger: Logger) { super(); @@ -214,7 +213,7 @@ export class DefaultPresence } /** - * Creates the realtime channel for presence. Called after initAfter is resolved. + * Creates the realtime channel for presence. */ private _makeChannel(roomId: string, roomOptions: RoomOptions, realtime: Ably.Realtime): Ably.RealtimeChannel { // Set our channel modes based on the room options @@ -249,6 +248,7 @@ export class DefaultPresence * @inheritDoc */ async get(params?: Ably.RealtimePresenceParams): Promise { + this._logger.trace('Presence.get()', { params }); const userOnPresence = await this._channel.presence.get(params); // ably-js never emits the 'absent' event, so we can safely ignore it here. diff --git a/src/core/room-lifecycle-manager.ts b/src/core/room-lifecycle-manager.ts index eec22dab..29c04753 100644 --- a/src/core/room-lifecycle-manager.ts +++ b/src/core/room-lifecycle-manager.ts @@ -111,7 +111,7 @@ export class RoomLifecycleManager { /** * Constructs a new `RoomLifecycleManager` instance. - * @param status The status to update. + * @param lifecycle The room lifecycle that manages status. * @param contributors The features that contribute to the room status. * @param logger An instance of the Logger. * @param transientDetachTimeout The number of milliseconds to consider a detach to be "transient" diff --git a/src/core/room-reactions.ts b/src/core/room-reactions.ts index 8a9fd60f..76722b2c 100644 --- a/src/core/room-reactions.ts +++ b/src/core/room-reactions.ts @@ -146,7 +146,6 @@ export class DefaultRoomReactions * @param realtime An instance of the Ably Realtime client. * @param clientId The client ID of the user. * @param logger An instance of the Logger. - * @param initAfter A promise that is awaited before creating any channels. */ constructor(roomId: string, realtime: Ably.Realtime, clientId: string, logger: Logger) { super(); @@ -157,7 +156,7 @@ export class DefaultRoomReactions } /** - * Creates the realtime channel for room reactions. Called after initAfter is resolved. + * Creates the realtime channel for room reactions. */ private _makeChannel(roomId: string, realtime: Ably.Realtime): Ably.RealtimeChannel { const channel = getChannel(`${roomId}::$chat::$reactions`, realtime); diff --git a/src/core/room.ts b/src/core/room.ts index 6145a8ce..2c9aa8f0 100644 --- a/src/core/room.ts +++ b/src/core/room.ts @@ -148,7 +148,6 @@ export class DefaultRoom implements Room { * @param realtime An instance of the Ably Realtime client. * @param chatApi An instance of the ChatApi. * @param logger An instance of the Logger. - * @param initAfter The room will wait for this promise to finish before initializing */ constructor( roomId: string, diff --git a/src/core/rooms.ts b/src/core/rooms.ts index 2936b8f0..0695f308 100644 --- a/src/core/rooms.ts +++ b/src/core/rooms.ts @@ -29,7 +29,7 @@ export interface Rooms { * @param roomId The ID of the room. * @param options The options for the room. * @throws {@link ErrorInfo} if a room with the same ID but different options already exists. - * @returns Room A new or existing Room object. + * @returns Room A promise to a new or existing Room object. */ get(roomId: string, options: RoomOptions): Promise; @@ -201,7 +201,8 @@ export class DefaultRooms implements Rooms { // If the room doesn't currently exist if (!existing) { - // existing the room is being released, forward the releasing promise + // There's no existing room, but there is a release in progress, so forward that releasing promise + // to the caller so they can watch that. if (releasing) { this._logger.debug('Rooms.release(); waiting for previous release call', { roomId, diff --git a/src/core/typing.ts b/src/core/typing.ts index b6d3a82b..92078b2a 100644 --- a/src/core/typing.ts +++ b/src/core/typing.ts @@ -136,7 +136,6 @@ export class DefaultTyping * @param realtime An instance of the Ably Realtime client. * @param clientId The client ID of the user. * @param logger An instance of the Logger. - * @param initAfter A promise that is awaited before creating any channels. */ constructor(roomId: string, options: TypingOptions, realtime: Ably.Realtime, clientId: string, logger: Logger) { super(); @@ -149,7 +148,7 @@ export class DefaultTyping } /** - * Creates the realtime channel for typing indicators. Called after initAfter is resolved. + * Creates the realtime channel for typing indicators. */ private _makeChannel(roomId: string, realtime: Ably.Realtime): Ably.RealtimeChannel { const channel = getChannel(`${roomId}::$chat::$typingIndicators`, realtime); @@ -164,6 +163,7 @@ export class DefaultTyping * @inheritDoc */ get(): Promise> { + this._logger.trace(`DefaultTyping.get();`); return this._channel.presence.get().then((members) => new Set(members.map((m) => m.clientId))); } @@ -200,7 +200,7 @@ export class DefaultTyping // Start typing and emit typingStarted event this._startTypingTimer(); - return this._channel.presence.enterClient(this._clientId).then(); + return this._channel.presence.enterClient(this._clientId); } /** diff --git a/src/react/helper/room-promise.ts b/src/react/helper/room-promise.ts index 5fdba499..2014b3ba 100644 --- a/src/react/helper/room-promise.ts +++ b/src/react/helper/room-promise.ts @@ -68,9 +68,8 @@ class DefaultRoomPromise implements RoomPromise { } /** - * Wait for the room promise to resolve, then execute the onResolve callback, if the component - * has not been unmounted. If the component has not been unmounted, then use the returned - * unmount function to clean up any resources later. + * Wait for the room promise to resolve, then execute the onResolve callback, storing its response as an unmount function. + * If the component is unmounted before the promise resolves,then this will do nothing. * * @param promise The promise that resolves to a Room instance. * @returns A promise that we simply resolve when its done.