diff --git a/libraries/Enums/types/webrtc.ts b/libraries/Enums/types/webrtc.ts index 11aad4aad2..278bea2f95 100644 --- a/libraries/Enums/types/webrtc.ts +++ b/libraries/Enums/types/webrtc.ts @@ -5,4 +5,4 @@ export enum WebRTCEnum { HEADPHONES = 'headphones', } -export type WebRTC = keyof typeof WebRTCEnum +export type WebRTCKinds = keyof typeof WebRTCEnum diff --git a/libraries/Iridium/IridiumManager.ts b/libraries/Iridium/IridiumManager.ts index f2b81753dd..f3ae372237 100644 --- a/libraries/Iridium/IridiumManager.ts +++ b/libraries/Iridium/IridiumManager.ts @@ -49,17 +49,9 @@ export class IridiumManager extends Emitter { * @param param0 Textile Configuration that includes id, password and SolanaWallet instance * @returns a promise that resolves when the initialization completes */ - async init({ pass, wallet }: { pass: string; wallet: Account }) { + async start({ pass, wallet }: { pass: string; wallet: Account }) { this.connector?.on('stopping', async () => { - await this.friends.stop?.() - await this.users.stop?.() - // await this.profile.stop?.() - // await this.groups.stop?.() - // await this.chat.stop?.() - // await this.files.stop?.() - // await this.webRTC.stop?.() - // await this.settings.stop?.() - // await this.notifications.stop?.() + await this.stop() }) logger.info('iridium/manager', 'init()') @@ -67,6 +59,18 @@ export class IridiumManager extends Emitter { return this.initFromEntropy(seed) } + async stop() { + await this.friends.stop?.() + await this.users.stop?.() + await this.profile.stop?.() + await this.groups.stop?.() + await this.chat.stop?.() + await this.files.stop?.() + await this.webRTC.stop?.() + await this.settings.stop?.() + await this.notifications.stop?.() + } + get id(): string { if (!this.connector) { throw new Error('Iridium not initialized') @@ -132,7 +136,7 @@ export class IridiumManager extends Emitter { this.profile.on('changed', this.onProfileChange.bind(this)) logger.info('iridium/manager', 'initializing profile') - await this.profile.init() + await this.profile.start() } async onProfileChange() { @@ -174,32 +178,32 @@ export class IridiumManager extends Emitter { if (this.ready) return logger.info('iridium/manager', 'initializing users') - await this.users.init() + await this.users.start() logger.info('iridium/friends', 'initializing friends') - this.friends.init() + this.friends.start() logger.info('iridium/manager', 'initializing chat') - this.chat.init() + this.chat.start() logger.info('iridium/manager', 'ready') this.ready = true this.emit('ready', {}) logger.info('iridium/manager', 'initializing groups') - this.groups.init() + this.groups.start() logger.info('iridium/manager', 'initializing files') - this.files.init() + this.files.start() logger.info('iridium/manager', 'initializing settings') - this.settings.init() + this.settings.start() logger.info('iridium/manager', 'initializing webRTC') - this.webRTC.init() + this.webRTC.start() logger.info('iridium/manager', 'notification settings') - this.notifications.init() + this.notifications.start() logger.info( 'iridium/manager', diff --git a/libraries/Iridium/NotificationManager.ts b/libraries/Iridium/NotificationManager.ts index 5f3bfeee77..7845e2e73f 100644 --- a/libraries/Iridium/NotificationManager.ts +++ b/libraries/Iridium/NotificationManager.ts @@ -22,12 +22,14 @@ export default class NotificationManager extends Emitter { notifications: [], } - async init() { + async start() { await this.fetch() this.ready = true this.emit('ready', {}) } + async stop() {} + async fetch() { logger.info('iridium/notifications/fetch', 'fetching') const fetched = await iridium.connector?.get<{ diff --git a/libraries/Iridium/chat/ChatManager.ts b/libraries/Iridium/chat/ChatManager.ts index 6da520c093..60e27109f4 100644 --- a/libraries/Iridium/chat/ChatManager.ts +++ b/libraries/Iridium/chat/ChatManager.ts @@ -65,7 +65,7 @@ export default class ChatManager extends Emitter { typing: {}, } - async init() { + async start() { const fetched = await this.get() this.state.conversations = { ...this.state.conversations, @@ -100,6 +100,8 @@ export default class ChatManager extends Emitter { this.emit('ready', {}) } + async stop() {} + private async onConversationAnnounce( message: IridiumPubsubMessage< IridiumDecodedPayload diff --git a/libraries/Iridium/files/FilesManager.ts b/libraries/Iridium/files/FilesManager.ts index 52882d7929..16d7bdabc4 100644 --- a/libraries/Iridium/files/FilesManager.ts +++ b/libraries/Iridium/files/FilesManager.ts @@ -25,7 +25,7 @@ import { DIRECTORY_TYPE } from '~/libraries/Files/types/directory' export default class FilesManager extends Emitter { public state: { items: IridiumItem[] } = { items: [] } - async init() { + async start() { if (!iridium.connector) { throw new Error('cannot initialize files, no iridium connector') } @@ -38,6 +38,8 @@ export default class FilesManager extends Emitter { this.emit('ready', {}) } + async stop() {} + async fetch() { const res = await iridium.connector?.get<{ items: IridiumItem[] }>('/files') if (!res?.items) { diff --git a/libraries/Iridium/friends/FriendsManager.ts b/libraries/Iridium/friends/FriendsManager.ts index 930626de75..ce6a5895f0 100644 --- a/libraries/Iridium/friends/FriendsManager.ts +++ b/libraries/Iridium/friends/FriendsManager.ts @@ -47,7 +47,7 @@ export default class FriendsManager extends Emitter { private loggerTag = 'iridium/friends' - async init() { + async start() { if (!iridium.connector) { throw new Error('cannot initialize friends, no iridium connector') } diff --git a/libraries/Iridium/groups/GroupManager.ts b/libraries/Iridium/groups/GroupManager.ts index c77ec18ff3..2f9da13369 100644 --- a/libraries/Iridium/groups/GroupManager.ts +++ b/libraries/Iridium/groups/GroupManager.ts @@ -38,7 +38,7 @@ export default class GroupManager extends Emitter { private loggerTag = 'iridium/groups' - async init() { + async start() { if (!iridium.connector) { throw new Error('cannot initialize groups, no iridium connector') } @@ -51,6 +51,8 @@ export default class GroupManager extends Emitter { await this.fetch() } + async stop() {} + private async fetch() { this.state = (await iridium.connector?.get('/groups')) || {} } diff --git a/libraries/Iridium/profile/ProfileManager.ts b/libraries/Iridium/profile/ProfileManager.ts index 2d402ec4b7..a84d7a20f5 100644 --- a/libraries/Iridium/profile/ProfileManager.ts +++ b/libraries/Iridium/profile/ProfileManager.ts @@ -7,7 +7,7 @@ export default class IridiumProfile extends Emitter { public state?: User public ready?: boolean = false - async init() { + async start() { if (!iridium) { throw new Error('cannot initialize profile, no iridium connector') } @@ -22,6 +22,8 @@ export default class IridiumProfile extends Emitter { }) } + async stop() {} + private async fetch() { this.state = await this.get() await this.setUser() @@ -75,11 +77,11 @@ export default class IridiumProfile extends Emitter { async updateUser(details: Partial) { logger.info('iridium/profile', 'updating user', { details }) - for (const [key, value] of Object.entries(details)) { - this.state[key] = value - } - - await this.set('/', { ...this.state, ...(details as User) }) + this.state = { + ...this.state, + ...details, + } as User + await this.set('/', this.state) if (!this.state || !iridium.id) return // tell our peers via user announce await iridium.users.send({ diff --git a/libraries/Iridium/settings/SettingsManager.ts b/libraries/Iridium/settings/SettingsManager.ts index eb7c02a36d..5de60eea91 100644 --- a/libraries/Iridium/settings/SettingsManager.ts +++ b/libraries/Iridium/settings/SettingsManager.ts @@ -39,10 +39,12 @@ export default class SettingsManager extends Emitter { this.state = initialState } - async init() { + async start() { await this.fetch() } + async stop() {} + private async fetch() { const fetched = await this.get() if (!fetched) { diff --git a/libraries/Iridium/users/UsersManager.ts b/libraries/Iridium/users/UsersManager.ts index 7000cb7f5f..151f591496 100644 --- a/libraries/Iridium/users/UsersManager.ts +++ b/libraries/Iridium/users/UsersManager.ts @@ -45,7 +45,7 @@ export default class UsersManager extends Emitter { return Object.values(this.state) } - async init() { + async start() { if (!iridium.connector) { throw new Error('cannot initialize users, no iridium connector') } diff --git a/libraries/Iridium/webrtc/WebRTCManager.ts b/libraries/Iridium/webrtc/WebRTCManager.ts index fb66ad1022..b6d63e4a04 100644 --- a/libraries/Iridium/webrtc/WebRTCManager.ts +++ b/libraries/Iridium/webrtc/WebRTCManager.ts @@ -79,7 +79,7 @@ export default class WebRTCManager extends Emitter { return this.state.streamConstraints } - async init() { + async start() { if (!iridium.connector || !iridium.connector.p2p.primaryNodeID) { throw new Error('not connected to primary node') } @@ -99,7 +99,7 @@ export default class WebRTCManager extends Emitter { this.wire.on('wire:message', this.onMessage.bind(this)) // Initialize the Wire - await this.wire.init() + await this.wire.start() setInterval(() => { if (this.state.activeCall) { @@ -108,6 +108,12 @@ export default class WebRTCManager extends Emitter { }, 1000) } + async stop() { + await Promise.all( + Object.values(this.state.calls).map(async (call) => call.destroy()), + ) + } + private async onMessage({ type, message, @@ -438,14 +444,25 @@ export default class WebRTCManager extends Emitter { callId?: string did: string }) => { - // It's not related the active call, so we don't reset the state - if (this.state.activeCall?.callId !== callId) return + const incomingCallId = this.state.incomingCall?.callId + if (incomingCallId && incomingCallId === callId) { + const incomingCall = this.state.calls[incomingCallId] + if (incomingCall) { + incomingCall.destroy() + } + this.state.incomingCall = null + } - this.state.incomingCall = null + // It's not related the active call, so we don't reset the state + const activeCallId = this.state.activeCall?.callId + if (!activeCallId || activeCallId !== callId) return + const activeCall = this.state.calls[activeCallId] + activeCall?.destroy() this.state.activeCall = null this.state.callStartedAt = 0 } call.on('HANG_UP', onCallHangup) + call.on('REMOTE_HANG_UP', onCallHangup) const onCallTrack = async ({ track, @@ -591,9 +608,12 @@ export default class WebRTCManager extends Emitter { callId?: string did: string }) => { - // Reset the state only if the event is related to the active call - if (callId === this.state.activeCall?.callId) { + if (!callId) return + if (callId === this.state.incomingCall?.callId) { this.state.incomingCall = null + } + + if (callId === this.state.activeCall?.callId) { this.state.activeCall = null this.state.callStartedAt = 0 } @@ -760,10 +780,10 @@ export default class WebRTCManager extends Emitter { } public async mute({ - kind = 'audio', + kind = WebRTCEnum.AUDIO, did = iridium.id, }: { - kind: string + kind: WebRTCEnum did?: string }) { if (!this.state.activeCall) return @@ -776,7 +796,7 @@ export default class WebRTCManager extends Emitter { kind, did = iridium.id, }: { - kind: string + kind: WebRTCEnum did?: string }) { if (!this.state.activeCall) return diff --git a/libraries/Iridium/webrtc/types.ts b/libraries/Iridium/webrtc/types.ts index 02fd146a98..a2251fcc84 100644 --- a/libraries/Iridium/webrtc/types.ts +++ b/libraries/Iridium/webrtc/types.ts @@ -3,7 +3,7 @@ import { WebRTCEnum } from '~/libraries/Enums/enums' import { Call } from '~/libraries/WebRTC/Call' export type PeerMutedState = { - [key in WebRTCEnum]: boolean + [key: string]: boolean } export type StreamMutedState = { [key: string]: PeerMutedState diff --git a/libraries/WebRTC/Call.ts b/libraries/WebRTC/Call.ts index 1e80851333..cb40f5666a 100644 --- a/libraries/WebRTC/Call.ts +++ b/libraries/WebRTC/Call.ts @@ -1051,7 +1051,7 @@ export class Call extends Emitter { */ protected _onError(peer: CallPeer, error: Error) { // FOR DEBUG - console.error(`${error} CODE: ${error.code}`) + logger.error('webrtc/call', 'error', error) this.emit('ERROR', { did: peer.id, error }) } @@ -1201,6 +1201,12 @@ export class Call extends Emitter { // It's related to another call if (callId !== this.callId) return + // reset incoming call + this.emit('REMOTE_HANG_UP', { + did, + callId, + }) + this.peerDialingDisabled[did] = true this.isCallee[did] = false this.isCaller[did] = false diff --git a/libraries/WebRTC/Wire.ts b/libraries/WebRTC/Wire.ts index eff0e2e507..2de96405e4 100644 --- a/libraries/WebRTC/Wire.ts +++ b/libraries/WebRTC/Wire.ts @@ -41,7 +41,7 @@ export class Wire extends Emitter { [did: string]: ReturnType } = {} - async init() { + async start() { this._bus = new IridiumBus('/webrtc/announce') this._bus.on('message', this.onMessage.bind(this)) @@ -50,6 +50,8 @@ export class Wire extends Emitter { await this.setupAnnounce() } + async stop() {} + onMessage({ type, message, @@ -304,7 +306,11 @@ export class Wire extends Emitter { } }) - logger.debug(this.loggerTag, 'Sending message to', { online, offline }) + logger.debug(this.loggerTag, 'Sending message to', { + online, + offline, + message, + }) if (online.length && iridium.connector) { const encodedMessage = await encoding.encodePayload( diff --git a/libraries/WebRTC/types.ts b/libraries/WebRTC/types.ts index 81d61cba7b..b58d13ba58 100644 --- a/libraries/WebRTC/types.ts +++ b/libraries/WebRTC/types.ts @@ -63,6 +63,7 @@ export interface CallEventListeners { CONNECTED: (data: { did: string; callId?: string }) => void HANG_UP: (data: { did: string; callId?: string }) => void ERROR: (data: { did: string; error: Error; callId?: string }) => void + REMOTE_HANG_UP: (data: { did: string; callId?: string }) => void REMOTE_TRACK_RECEIVED: (data: { did: string callId?: string