チャンネルで入力中ユーザーを表示するように、Chat UIでタイムラインでは投稿フォームを上に表示するように
This commit is contained in:
parent
5f1a6b6f64
commit
25d37302a8
11 changed files with 143 additions and 41 deletions
|
@ -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
|
||||
|
@ -41,9 +46,41 @@ export default class extends Channel {
|
|||
this.send('note', note);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import { Users, Followings, Mutings, UserProfiles, ChannelFollowings } from '../
|
|||
import { ApiError } from '../error';
|
||||
import { AccessToken } from '../../../models/entities/access-token';
|
||||
import { UserProfile } from '../../../models/entities/user-profile';
|
||||
import { publishChannelStream } from '../../../services/stream';
|
||||
|
||||
/**
|
||||
* Main stream connection
|
||||
|
@ -27,10 +28,10 @@ export default class Connection {
|
|||
public subscriber: EventEmitter;
|
||||
private channels: Channel[] = [];
|
||||
private subscribingNotes: any = {};
|
||||
private followingClock: NodeJS.Timer;
|
||||
private mutingClock: NodeJS.Timer;
|
||||
private followingChannelsClock: NodeJS.Timer;
|
||||
private userProfileClock: NodeJS.Timer;
|
||||
private followingClock: ReturnType<typeof setInterval>;
|
||||
private mutingClock: ReturnType<typeof setInterval>;
|
||||
private followingChannelsClock: ReturnType<typeof setInterval>;
|
||||
private userProfileClock: ReturnType<typeof setInterval>;
|
||||
|
||||
constructor(
|
||||
wsConnection: websocket.connection,
|
||||
|
@ -93,6 +94,7 @@ export default class Connection {
|
|||
case 'disconnect': this.onChannelDisconnectRequested(body); break;
|
||||
case 'channel': this.onChannelMessageRequested(body); break;
|
||||
case 'ch': this.onChannelMessageRequested(body); break; // alias
|
||||
case 'typingOnChannel': this.typingOnChannel(body.channel); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,6 +260,13 @@ export default class Connection {
|
|||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
private typingOnChannel(channel: ChannelModel['id']) {
|
||||
if (this.user) {
|
||||
publishChannelStream(channel, 'typing', this.user.id);
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
private async updateFollowing() {
|
||||
const followings = await Followings.find({
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue