diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2021-02-21 13:38:29 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2021-02-21 13:38:29 +0900 |
| commit | 3d68a0988bb40567e71a23cbe809d9eff4e1a2c0 (patch) | |
| tree | dbecada3558bfaeef7ae72a44c0e643f678f252a /src/server/api/stream/channels | |
| parent | Merge branch 'develop' (diff) | |
| parent | 12.71.0 (diff) | |
| download | misskey-3d68a0988bb40567e71a23cbe809d9eff4e1a2c0.tar.gz misskey-3d68a0988bb40567e71a23cbe809d9eff4e1a2c0.tar.bz2 misskey-3d68a0988bb40567e71a23cbe809d9eff4e1a2c0.zip | |
Merge branch 'develop'
Diffstat (limited to 'src/server/api/stream/channels')
| -rw-r--r-- | src/server/api/stream/channels/channel.ts | 39 | ||||
| -rw-r--r-- | src/server/api/stream/channels/games/reversi-game.ts | 2 | ||||
| -rw-r--r-- | src/server/api/stream/channels/messaging.ts | 47 |
3 files changed, 83 insertions, 5 deletions
diff --git a/src/server/api/stream/channels/channel.ts b/src/server/api/stream/channels/channel.ts index c24b3db937..aa570d1ef4 100644 --- a/src/server/api/stream/channels/channel.ts +++ b/src/server/api/stream/channels/channel.ts @@ -1,14 +1,17 @@ import autobind from 'autobind-decorator'; import Channel from '../channel'; -import { Notes } from '../../../../models'; +import { Notes, Users } from '../../../../models'; import { isMutedUserRelated } from '../../../../misc/is-muted-user-related'; import { PackedNote } from '../../../../models/repositories/note'; +import { User } from '../../../../models/entities/user'; export default class extends Channel { public readonly chName = 'channel'; public static shouldShare = false; public static requireCredential = false; private channelId: string; + private typers: Record<User['id'], Date> = {}; + private emitTypersIntervalId: ReturnType<typeof setInterval>; @autobind public async init(params: any) { @@ -16,6 +19,8 @@ export default class extends Channel { // Subscribe stream this.subscriber.on('notesStream', this.onNote); + this.subscriber.on(`channelStream:${this.channelId}`, this.onEvent); + this.emitTypersIntervalId = setInterval(this.emitTypers, 5000); } @autobind @@ -42,8 +47,40 @@ export default class extends Channel { } @autobind + private onEvent(data: any) { + if (data.type === 'typing') { + const id = data.body; + const begin = this.typers[id] == null; + this.typers[id] = new Date(); + if (begin) { + this.emitTypers(); + } + } + } + + @autobind + private async emitTypers() { + const now = new Date(); + + // Remove not typing users + for (const [userId, date] of Object.entries(this.typers)) { + if (now.getTime() - date.getTime() > 5000) delete this.typers[userId]; + } + + const users = await Users.packMany(Object.keys(this.typers), null, { detail: false }); + + this.send({ + type: 'typers', + body: users, + }); + } + + @autobind public dispose() { // Unsubscribe events this.subscriber.off('notesStream', this.onNote); + this.subscriber.off(`channelStream:${this.channelId}`, this.onEvent); + + clearInterval(this.emitTypersIntervalId); } } diff --git a/src/server/api/stream/channels/games/reversi-game.ts b/src/server/api/stream/channels/games/reversi-game.ts index ea62ab1e88..e1c2116ac6 100644 --- a/src/server/api/stream/channels/games/reversi-game.ts +++ b/src/server/api/stream/channels/games/reversi-game.ts @@ -15,7 +15,7 @@ export default class extends Channel { private gameId: ReversiGame['id'] | null = null; private watchers: Record<User['id'], Date> = {}; - private emitWatchersIntervalId: any; + private emitWatchersIntervalId: ReturnType<typeof setInterval>; @autobind public async init(params: any) { diff --git a/src/server/api/stream/channels/messaging.ts b/src/server/api/stream/channels/messaging.ts index 8456871e6a..4c41dc820b 100644 --- a/src/server/api/stream/channels/messaging.ts +++ b/src/server/api/stream/channels/messaging.ts @@ -12,6 +12,9 @@ export default class extends Channel { private otherpartyId: string | null; private otherparty?: User; private groupId: string | null; + private subCh: string; + private typers: Record<User['id'], Date> = {}; + private emitTypersIntervalId: ReturnType<typeof setInterval>; @autobind public async init(params: any) { @@ -31,14 +34,28 @@ export default class extends Channel { } } - const subCh = this.otherpartyId + this.emitTypersIntervalId = setInterval(this.emitTypers, 5000); + + this.subCh = this.otherpartyId ? `messagingStream:${this.user!.id}-${this.otherpartyId}` : `messagingStream:${this.groupId}`; // Subscribe messaging stream - this.subscriber.on(subCh, data => { + this.subscriber.on(this.subCh, this.onEvent); + } + + @autobind + private onEvent(data: any) { + if (data.type === 'typing') { + const id = data.body; + const begin = this.typers[id] == null; + this.typers[id] = new Date(); + if (begin) { + this.emitTypers(); + } + } else { this.send(data); - }); + } } @autobind @@ -60,4 +77,28 @@ export default class extends Channel { break; } } + + @autobind + private async emitTypers() { + const now = new Date(); + + // Remove not typing users + for (const [userId, date] of Object.entries(this.typers)) { + if (now.getTime() - date.getTime() > 5000) delete this.typers[userId]; + } + + const users = await Users.packMany(Object.keys(this.typers), null, { detail: false }); + + this.send({ + type: 'typers', + body: users, + }); + } + + @autobind + public dispose() { + this.subscriber.off(this.subCh, this.onEvent); + + clearInterval(this.emitTypersIntervalId); + } } |