diff --git a/packages/status-js/src/client/client.ts b/packages/status-js/src/client/client.ts index 375e28b6..bdb8afa2 100644 --- a/packages/status-js/src/client/client.ts +++ b/packages/status-js/src/client/client.ts @@ -53,6 +53,7 @@ class Client { */ #wakuDisconnectionTimer: ReturnType connected: boolean + #connectionCallbacks: Set<(connected: boolean) => void> public activityCenter: ActivityCenter public community: Community @@ -68,6 +69,7 @@ class Client { * Waku should be connected and protocols awaited at this point, thus connected. */ this.connected = true + this.#connectionCallbacks = new Set() this.waku = waku this.wakuMessages = new Set() this.#wakuDisconnectionTimer = setInterval(async () => { @@ -76,6 +78,12 @@ class Client { for (const connection of this.waku.libp2p.connectionManager.getConnections()) { try { await this.waku.libp2p.ping(connection.remoteAddr) + + if (!this.connected) { + this.connected = true + + this.emitConnection(this.connected) + } } catch { connectionsToClose.push(connection.close()) } @@ -89,6 +97,8 @@ class Client { */ this.waku.libp2p.connectionManager.addEventListener('peer:connect', () => { this.connected = true // reconnect + + this.emitConnection(this.connected) }) /** * >This event will **only** be triggered when the last connection is closed. @@ -96,6 +106,13 @@ class Client { */ waku.libp2p.connectionManager.addEventListener('peer:disconnect', () => { this.connected = false + + this.emitConnection(this.connected) + }) + window.addEventListener('offline', () => { + this.connected = false + + this.emitConnection(this.connected) }) // Storage @@ -177,6 +194,18 @@ class Client { await this.waku.stop() } + public onConnection = (callback: (connected: boolean) => void) => { + this.#connectionCallbacks.add(callback) + + return () => { + this.#connectionCallbacks.delete(callback) + } + } + + private emitConnection = (connected: boolean) => { + this.#connectionCallbacks.forEach(callback => callback(connected)) + } + get account() { return this.#account } @@ -201,10 +230,10 @@ class Client { this.account = undefined } - public onAccountChange(listener: (account?: Account) => void) { - this.#accountCallbacks.add(listener) + public onAccountChange(callback: (account?: Account) => void) { + this.#accountCallbacks.add(callback) return () => { - this.#accountCallbacks.delete(listener) + this.#accountCallbacks.delete(callback) } } diff --git a/packages/status-react/src/protocol/provider.tsx b/packages/status-react/src/protocol/provider.tsx index 59b62055..b315059e 100644 --- a/packages/status-react/src/protocol/provider.tsx +++ b/packages/status-react/src/protocol/provider.tsx @@ -23,6 +23,7 @@ export type Action = | { type: 'UPDATE_COMMUNITY'; community: Community['description'] } | { type: 'SET_ACCOUNT'; account: Account | undefined } | { type: 'FAIL' } + | { type: 'CONNECT'; connected: boolean } interface Props { options: ClientOptions @@ -50,6 +51,9 @@ const reducer = (state: State, action: Action): State => { case 'FAIL': { return { ...state, failed: true, loading: false } } + case 'CONNECT': { + return { ...state, loading: !action.connected } + } } } @@ -88,6 +92,9 @@ export const ProtocolProvider = (props: Props) => { useEffect(() => { if (client) { const unsubscribe = [ + client.onConnection(connected => { + dispatch({ type: 'CONNECT', connected }) + }), client.onAccountChange(account => { dispatch({ type: 'SET_ACCOUNT', account }) }),