diff --git a/src/web/app/ch/tags/channel.tag b/src/web/app/ch/tags/channel.tag index 48c5c705d3..8300bd5715 100644 --- a/src/web/app/ch/tags/channel.tag +++ b/src/web/app/ch/tags/channel.tag @@ -55,7 +55,7 @@ </style> <script> import Progress from '../../common/scripts/loading'; - import ChannelStream from '../../common/scripts/channel-stream'; + import ChannelStream from '../../common/scripts/streaming/channel-stream'; this.mixin('i'); this.mixin('api'); diff --git a/src/web/app/common/mios.ts b/src/web/app/common/mios.ts index 23f6980cf4..9704e92af8 100644 --- a/src/web/app/common/mios.ts +++ b/src/web/app/common/mios.ts @@ -2,7 +2,7 @@ import { EventEmitter } from 'eventemitter3'; import * as riot from 'riot'; import signout from './scripts/signout'; import Progress from './scripts/loading'; -import Connection from './scripts/home-stream'; +import HomeStreamManager from './scripts/streaming/home-stream-manager'; import CONFIG from './scripts/config'; import api from './scripts/api'; @@ -33,9 +33,9 @@ export default class MiOS extends EventEmitter { } /** - * A connection of home stream + * A connection manager of home stream */ - public stream: Connection; + public stream: HomeStreamManager; constructor() { super(); @@ -67,21 +67,27 @@ export default class MiOS extends EventEmitter { body: JSON.stringify({ i: token }) - }).then(res => { // When success + }) + // When success + .then(res => { // When failed to authenticate user if (res.status !== 200) { return signout(); } + // Parse response res.json().then(i => { me = i; me.token = token; done(); }); - }, () => { // When failure + }) + // When failure + .catch(() => { // Render the error screen document.body.innerHTML = '<mk-error />'; riot.mount('*'); + Progress.done(); }); @@ -104,6 +110,7 @@ export default class MiOS extends EventEmitter { // ローカルストレージにキャッシュ localStorage.setItem('me', JSON.stringify(me)); + // 自分の情報が更新されたとき me.on('updated', () => { // キャッシュ更新 localStorage.setItem('me', JSON.stringify(me)); @@ -112,8 +119,10 @@ export default class MiOS extends EventEmitter { this.i = me; - // Init home stream connection - this.stream = this.i ? new Connection(this.i) : null; + // Init home stream manager + this.stream = this.isSignedin + ? new HomeStreamManager(this.i) + : null; // Finish init callback(); diff --git a/src/web/app/common/mixins.ts b/src/web/app/common/mixins.ts index 98818118f4..e9c3625937 100644 --- a/src/web/app/common/mixins.ts +++ b/src/web/app/common/mixins.ts @@ -1,10 +1,10 @@ import * as riot from 'riot'; import MiOS from './mios'; -import ServerStreamManager from './scripts/server-stream-manager'; -import RequestsStreamManager from './scripts/requests-stream-manager'; -import MessagingIndexStreamManager from './scripts/messaging-index-stream-manager'; -import DriveStreamManager from './scripts/drive-stream-manager'; +import ServerStreamManager from './scripts/streaming/server-stream-manager'; +import RequestsStreamManager from './scripts/streaming/requests-stream-manager'; +import MessagingIndexStreamManager from './scripts/streaming/messaging-index-stream-manager'; +import DriveStreamManager from './scripts/streaming/drive-stream-manager'; export default (mios: MiOS) => { (riot as any).mixin('os', { diff --git a/src/web/app/common/scripts/stream-manager.ts b/src/web/app/common/scripts/stream-manager.ts deleted file mode 100644 index 4eaf0f9a45..0000000000 --- a/src/web/app/common/scripts/stream-manager.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as uuid from 'uuid'; -import Connection from './stream'; - -export default abstract class StreamManager<T extends Connection> { - protected connection: T = null; - - /** - * コネクションを必要としているユーザー - */ - private users = []; - - public abstract getConnection(): T; - - public use() { - // ユーザーID生成 - const userId = uuid(); - - this.users.push(userId); - - return userId; - } - - public dispose(userId) { - this.users = this.users.filter(id => id != userId); - - // 誰もコネクションの利用者がいなくなったら - if (this.users.length == 0) { - // コネクションを切断する - this.connection.close(); - this.connection = null; - } - } -} diff --git a/src/web/app/common/scripts/channel-stream.ts b/src/web/app/common/scripts/streaming/channel-stream.ts similarity index 70% rename from src/web/app/common/scripts/channel-stream.ts rename to src/web/app/common/scripts/streaming/channel-stream.ts index c9c7fbbcda..434b108b9e 100644 --- a/src/web/app/common/scripts/channel-stream.ts +++ b/src/web/app/common/scripts/streaming/channel-stream.ts @@ -3,12 +3,10 @@ import Stream from './stream'; /** * Channel stream connection */ -class Connection extends Stream { +export default class Connection extends Stream { constructor(channelId) { super('channel', { channel: channelId }); } } - -export default Connection; diff --git a/src/web/app/common/scripts/drive-stream-manager.ts b/src/web/app/common/scripts/streaming/drive-stream-manager.ts similarity index 100% rename from src/web/app/common/scripts/drive-stream-manager.ts rename to src/web/app/common/scripts/streaming/drive-stream-manager.ts diff --git a/src/web/app/common/scripts/drive-stream.ts b/src/web/app/common/scripts/streaming/drive-stream.ts similarity index 67% rename from src/web/app/common/scripts/drive-stream.ts rename to src/web/app/common/scripts/streaming/drive-stream.ts index 1b33435578..0da3f12554 100644 --- a/src/web/app/common/scripts/drive-stream.ts +++ b/src/web/app/common/scripts/streaming/drive-stream.ts @@ -3,12 +3,10 @@ import Stream from './stream'; /** * Drive stream connection */ -class Connection extends Stream { +export default class Connection extends Stream { constructor(me) { super('drive', { i: me.token }); } } - -export default Connection; diff --git a/src/web/app/common/scripts/streaming/home-stream-manager.ts b/src/web/app/common/scripts/streaming/home-stream-manager.ts new file mode 100644 index 0000000000..ad1dc870eb --- /dev/null +++ b/src/web/app/common/scripts/streaming/home-stream-manager.ts @@ -0,0 +1,20 @@ +import StreamManager from './stream-manager'; +import Connection from './home-stream'; + +export default class HomeStreamManager extends StreamManager<Connection> { + private me; + + constructor(me) { + super(); + + this.me = me; + } + + public getConnection() { + if (this.connection == null) { + this.connection = new Connection(this.me); + } + + return this.connection; + } +} diff --git a/src/web/app/common/scripts/home-stream.ts b/src/web/app/common/scripts/streaming/home-stream.ts similarity index 62% rename from src/web/app/common/scripts/home-stream.ts rename to src/web/app/common/scripts/streaming/home-stream.ts index d6324eeb7b..a78f4acdbe 100644 --- a/src/web/app/common/scripts/home-stream.ts +++ b/src/web/app/common/scripts/streaming/home-stream.ts @@ -1,10 +1,10 @@ import Stream from './stream'; -import signout from './signout'; +import signout from '../signout'; /** * Home stream connection */ -class Connection extends Stream { +export default class Connection extends Stream { constructor(me) { super('', { i: me.token @@ -15,13 +15,14 @@ class Connection extends Stream { this.send({ type: 'alive' }); }, 1000 * 60); + // 自分の情報が更新されたとき (this as any).on('i_updated', me.update); + // トークンが再生成されたとき + // このままではAPIが利用できないので強制的にサインアウトさせる (this as any).on('my_token_regenerated', () => { alert('%i18n:common.my-token-regenerated%'); signout(); }); } } - -export default Connection; diff --git a/src/web/app/common/scripts/messaging-index-stream-manager.ts b/src/web/app/common/scripts/streaming/messaging-index-stream-manager.ts similarity index 100% rename from src/web/app/common/scripts/messaging-index-stream-manager.ts rename to src/web/app/common/scripts/streaming/messaging-index-stream-manager.ts diff --git a/src/web/app/common/scripts/messaging-index-stream.ts b/src/web/app/common/scripts/streaming/messaging-index-stream.ts similarity index 70% rename from src/web/app/common/scripts/messaging-index-stream.ts rename to src/web/app/common/scripts/streaming/messaging-index-stream.ts index c194e663c2..8015c840b4 100644 --- a/src/web/app/common/scripts/messaging-index-stream.ts +++ b/src/web/app/common/scripts/streaming/messaging-index-stream.ts @@ -3,12 +3,10 @@ import Stream from './stream'; /** * Messaging index stream connection */ -class Connection extends Stream { +export default class Connection extends Stream { constructor(me) { super('messaging-index', { i: me.token }); } } - -export default Connection; diff --git a/src/web/app/common/scripts/messaging-stream.ts b/src/web/app/common/scripts/streaming/messaging-stream.ts similarity index 80% rename from src/web/app/common/scripts/messaging-stream.ts rename to src/web/app/common/scripts/streaming/messaging-stream.ts index 306a733274..68dfc5ec09 100644 --- a/src/web/app/common/scripts/messaging-stream.ts +++ b/src/web/app/common/scripts/streaming/messaging-stream.ts @@ -3,7 +3,7 @@ import Stream from './stream'; /** * Messaging stream connection */ -class Connection extends Stream { +export default class Connection extends Stream { constructor(me, otherparty) { super('messaging', { i: me.token, @@ -17,5 +17,3 @@ class Connection extends Stream { }); } } - -export default Connection; diff --git a/src/web/app/common/scripts/requests-stream-manager.ts b/src/web/app/common/scripts/streaming/requests-stream-manager.ts similarity index 100% rename from src/web/app/common/scripts/requests-stream-manager.ts rename to src/web/app/common/scripts/streaming/requests-stream-manager.ts diff --git a/src/web/app/common/scripts/requests-stream.ts b/src/web/app/common/scripts/streaming/requests-stream.ts similarity index 64% rename from src/web/app/common/scripts/requests-stream.ts rename to src/web/app/common/scripts/streaming/requests-stream.ts index df342693a7..22ecea6c07 100644 --- a/src/web/app/common/scripts/requests-stream.ts +++ b/src/web/app/common/scripts/streaming/requests-stream.ts @@ -3,10 +3,8 @@ import Stream from './stream'; /** * Requests stream connection */ -class Connection extends Stream { +export default class Connection extends Stream { constructor() { super('requests'); } } - -export default Connection; diff --git a/src/web/app/common/scripts/server-stream-manager.ts b/src/web/app/common/scripts/streaming/server-stream-manager.ts similarity index 100% rename from src/web/app/common/scripts/server-stream-manager.ts rename to src/web/app/common/scripts/streaming/server-stream-manager.ts diff --git a/src/web/app/common/scripts/server-stream.ts b/src/web/app/common/scripts/streaming/server-stream.ts similarity index 63% rename from src/web/app/common/scripts/server-stream.ts rename to src/web/app/common/scripts/streaming/server-stream.ts index 938ae4bfe5..b9e0684465 100644 --- a/src/web/app/common/scripts/server-stream.ts +++ b/src/web/app/common/scripts/streaming/server-stream.ts @@ -3,10 +3,8 @@ import Stream from './stream'; /** * Server stream connection */ -class Connection extends Stream { +export default class Connection extends Stream { constructor() { super('server'); } } - -export default Connection; diff --git a/src/web/app/common/scripts/streaming/stream-manager.ts b/src/web/app/common/scripts/streaming/stream-manager.ts new file mode 100644 index 0000000000..de27235426 --- /dev/null +++ b/src/web/app/common/scripts/streaming/stream-manager.ts @@ -0,0 +1,73 @@ +import { EventEmitter } from 'eventemitter3'; +import * as uuid from 'uuid'; +import Connection from './stream'; + +/** + * ストリーム接続を管理するクラス + * 複数の場所から同じストリームを利用する際、接続をまとめたりする + */ +export default abstract class StreamManager<T extends Connection> extends EventEmitter { + protected _connection: T = null; + + /** + * コネクションを必要としているユーザー + */ + private users = []; + + protected set connection(connection: T) { + this._connection = connection; + + if (this._connection == null) { + this.emit('disconnected'); + } else { + this.emit('connected', this._connection); + } + } + + protected get connection() { + return this._connection; + } + + /** + * コネクションを持っているか否か + */ + public get hasConnection() { + return this._connection != null; + } + + /** + * コネクションを要求します + */ + public abstract getConnection(): T; + + public borrow() { + return this._connection; + } + + /** + * コネクションを要求するためのユーザーIDを発行します + */ + public use() { + // ユーザーID生成 + const userId = uuid(); + + this.users.push(userId); + + return userId; + } + + /** + * コネクションを利用し終わってもう必要ないことを通知します + * @param userId use で発行したユーザーID + */ + public dispose(userId) { + this.users = this.users.filter(id => id != userId); + + // 誰もコネクションの利用者がいなくなったら + if (this.users.length == 0) { + // コネクションを切断する + this.connection.close(); + this.connection = null; + } + } +} diff --git a/src/web/app/common/scripts/stream.ts b/src/web/app/common/scripts/streaming/stream.ts similarity index 85% rename from src/web/app/common/scripts/stream.ts rename to src/web/app/common/scripts/streaming/stream.ts index 6843394644..97ebdcdd74 100644 --- a/src/web/app/common/scripts/stream.ts +++ b/src/web/app/common/scripts/streaming/stream.ts @@ -1,25 +1,25 @@ +import { EventEmitter } from 'eventemitter3'; import * as ReconnectingWebsocket from 'reconnecting-websocket'; -import * as riot from 'riot'; -import CONFIG from './config'; +import CONFIG from '../config'; /** * Misskey stream connection */ -class Connection { +export default class Connection extends EventEmitter { private state: string; private buffer: any[]; private socket: ReconnectingWebsocket; constructor(endpoint, params?) { - // BIND ----------------------------------- + super(); + + //#region BIND this.onOpen = this.onOpen.bind(this); this.onClose = this.onClose.bind(this); this.onMessage = this.onMessage.bind(this); this.send = this.send.bind(this); this.close = this.close.bind(this); - // ---------------------------------------- - - riot.observable(this); + //#endregion this.state = 'initializing'; this.buffer = []; @@ -42,7 +42,7 @@ class Connection { */ private onOpen() { this.state = 'connected'; - (this as any).trigger('_connected_'); + this.emit('_connected_'); // バッファーを処理 const _buffer = [].concat(this.buffer); // Shallow copy @@ -57,7 +57,7 @@ class Connection { */ private onClose() { this.state = 'reconnecting'; - (this as any).trigger('_closed_'); + this.emit('_closed_'); } /** @@ -66,7 +66,7 @@ class Connection { private onMessage(message) { try { const msg = JSON.parse(message.data); - if (msg.type) (this as any).trigger(msg.type, msg.body); + if (msg.type) this.emit(msg.type, msg.body); } catch (e) { // noop } @@ -93,5 +93,3 @@ class Connection { this.socket.removeEventListener('message', this.onMessage); } } - -export default Connection; diff --git a/src/web/app/common/tags/messaging/room.tag b/src/web/app/common/tags/messaging/room.tag index b1082e26be..a930327841 100644 --- a/src/web/app/common/tags/messaging/room.tag +++ b/src/web/app/common/tags/messaging/room.tag @@ -162,7 +162,7 @@ </style> <script> - import MessagingStreamConnection from '../../scripts/messaging-stream'; + import MessagingStreamConnection from '../../scripts/streaming/messaging-stream'; this.mixin('i'); this.mixin('api'); diff --git a/src/web/app/common/tags/signin-history.tag b/src/web/app/common/tags/signin-history.tag index 9c96746249..b9bd859851 100644 --- a/src/web/app/common/tags/signin-history.tag +++ b/src/web/app/common/tags/signin-history.tag @@ -50,7 +50,10 @@ <script> this.mixin('i'); this.mixin('api'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.history = []; this.fetching = true; @@ -63,11 +66,12 @@ }); }); - this.stream.on('signin', this.onSignin); + this.connection.on('signin', this.onSignin); }); this.on('unmount', () => { - this.stream.off('signin', this.onSignin); + this.connection.off('signin', this.onSignin); + this.stream.dispose(this.connectionId); }); this.onSignin = signin => { diff --git a/src/web/app/common/tags/stream-indicator.tag b/src/web/app/common/tags/stream-indicator.tag index ea1c437035..0d74985c88 100644 --- a/src/web/app/common/tags/stream-indicator.tag +++ b/src/web/app/common/tags/stream-indicator.tag @@ -1,13 +1,13 @@ <mk-stream-indicator> - <p if={ stream.state == 'initializing' }> + <p if={ connection.state == 'initializing' }> <i class="fa fa-spinner fa-spin"></i> <span>%i18n:common.tags.mk-stream-indicator.connecting%<mk-ellipsis/></span> </p> - <p if={ stream.state == 'reconnecting' }> + <p if={ connection.state == 'reconnecting' }> <i class="fa fa-spinner fa-spin"></i> <span>%i18n:common.tags.mk-stream-indicator.reconnecting%<mk-ellipsis/></span> </p> - <p if={ stream.state == 'connected' }> + <p if={ connection.state == 'connected' }> <i class="fa fa-check"></i> <span>%i18n:common.tags.mk-stream-indicator.connected%</span> </p> @@ -38,34 +38,41 @@ import anime from 'animejs'; this.mixin('i'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.on('before-mount', () => { - if (this.stream.state == 'connected') { + if (this.connection.state == 'connected') { this.root.style.opacity = 0; } - }); - this.stream.on('_connected_', () => { - this.update(); - setTimeout(() => { + this.connection.on('_connected_', () => { + this.update(); + setTimeout(() => { + anime({ + targets: this.root, + opacity: 0, + easing: 'linear', + duration: 200 + }); + }, 1000); + }); + + this.connection.on('_closed_', () => { + this.update(); anime({ targets: this.root, - opacity: 0, + opacity: 1, easing: 'linear', - duration: 200 + duration: 100 }); - }, 1000); + }); }); - this.stream.on('_closed_', () => { - this.update(); - anime({ - targets: this.root, - opacity: 1, - easing: 'linear', - duration: 100 - }); + this.on('unmount', () => { + this.stream.dispose(this.connectionId); }); </script> </mk-stream-indicator> diff --git a/src/web/app/desktop/script.ts b/src/web/app/desktop/script.ts index b4a8d829d6..bc0fc8dfe3 100644 --- a/src/web/app/desktop/script.ts +++ b/src/web/app/desktop/script.ts @@ -13,6 +13,7 @@ import route from './router'; import fuckAdBlock from './scripts/fuck-ad-block'; import getPostSummary from '../../../common/get-post-summary'; import MiOS from '../common/mios'; +import HomeStreamManager from '../common/scripts/streaming/home-stream-manager'; /** * init @@ -41,52 +42,62 @@ init(async (mios: MiOS) => { route(mios); }); -function registerNotifications(stream) { +function registerNotifications(stream: HomeStreamManager) { if (stream == null) return; - stream.on('drive_file_created', file => { - const n = new Notification('ファイルがアップロードされました', { - body: file.name, - icon: file.url + '?thumbnail&size=64' - }); - setTimeout(n.close.bind(n), 5000); + if (stream.hasConnection) { + attach(stream.borrow()); + } + + stream.on('connected', connection => { + attach(connection); }); - stream.on('mention', post => { - const n = new Notification(`${post.user.name}さんから:`, { - body: getPostSummary(post), - icon: post.user.avatar_url + '?thumbnail&size=64' - }); - setTimeout(n.close.bind(n), 6000); - }); - - stream.on('reply', post => { - const n = new Notification(`${post.user.name}さんから返信:`, { - body: getPostSummary(post), - icon: post.user.avatar_url + '?thumbnail&size=64' - }); - setTimeout(n.close.bind(n), 6000); - }); - - stream.on('quote', post => { - const n = new Notification(`${post.user.name}さんが引用:`, { - body: getPostSummary(post), - icon: post.user.avatar_url + '?thumbnail&size=64' - }); - setTimeout(n.close.bind(n), 6000); - }); - - stream.on('unread_messaging_message', message => { - const n = new Notification(`${message.user.name}さんからメッセージ:`, { - body: message.text, // TODO: getMessagingMessageSummary(message), - icon: message.user.avatar_url + '?thumbnail&size=64' - }); - n.onclick = () => { - n.close(); - (riot as any).mount(document.body.appendChild(document.createElement('mk-messaging-room-window')), { - user: message.user + function attach(connection) { + connection.on('drive_file_created', file => { + const n = new Notification('ファイルがアップロードされました', { + body: file.name, + icon: file.url + '?thumbnail&size=64' }); - }; - setTimeout(n.close.bind(n), 7000); - }); + setTimeout(n.close.bind(n), 5000); + }); + + connection.on('mention', post => { + const n = new Notification(`${post.user.name}さんから:`, { + body: getPostSummary(post), + icon: post.user.avatar_url + '?thumbnail&size=64' + }); + setTimeout(n.close.bind(n), 6000); + }); + + connection.on('reply', post => { + const n = new Notification(`${post.user.name}さんから返信:`, { + body: getPostSummary(post), + icon: post.user.avatar_url + '?thumbnail&size=64' + }); + setTimeout(n.close.bind(n), 6000); + }); + + connection.on('quote', post => { + const n = new Notification(`${post.user.name}さんが引用:`, { + body: getPostSummary(post), + icon: post.user.avatar_url + '?thumbnail&size=64' + }); + setTimeout(n.close.bind(n), 6000); + }); + + connection.on('unread_messaging_message', message => { + const n = new Notification(`${message.user.name}さんからメッセージ:`, { + body: message.text, // TODO: getMessagingMessageSummary(message), + icon: message.user.avatar_url + '?thumbnail&size=64' + }); + n.onclick = () => { + n.close(); + (riot as any).mount(document.body.appendChild(document.createElement('mk-messaging-room-window')), { + user: message.user + }); + }; + setTimeout(n.close.bind(n), 7000); + }); + } } diff --git a/src/web/app/desktop/tags/big-follow-button.tag b/src/web/app/desktop/tags/big-follow-button.tag index 86df2d4924..8897748ae1 100644 --- a/src/web/app/desktop/tags/big-follow-button.tag +++ b/src/web/app/desktop/tags/big-follow-button.tag @@ -74,7 +74,10 @@ this.mixin('i'); this.mixin('api'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.user = null; this.userPromise = isPromise(this.opts.user) @@ -89,14 +92,15 @@ init: false, user: user }); - this.stream.on('follow', this.onStreamFollow); - this.stream.on('unfollow', this.onStreamUnfollow); + this.connection.on('follow', this.onStreamFollow); + this.connection.on('unfollow', this.onStreamUnfollow); }); }); this.on('unmount', () => { - this.stream.off('follow', this.onStreamFollow); - this.stream.off('unfollow', this.onStreamUnfollow); + this.connection.off('follow', this.onStreamFollow); + this.connection.off('unfollow', this.onStreamUnfollow); + this.stream.dispose(this.connectionId); }); this.onStreamFollow = user => { diff --git a/src/web/app/desktop/tags/follow-button.tag b/src/web/app/desktop/tags/follow-button.tag index 00ff686f69..a1cbc191d8 100644 --- a/src/web/app/desktop/tags/follow-button.tag +++ b/src/web/app/desktop/tags/follow-button.tag @@ -71,7 +71,10 @@ this.mixin('i'); this.mixin('api'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.user = null; this.userPromise = isPromise(this.opts.user) @@ -86,14 +89,15 @@ init: false, user: user }); - this.stream.on('follow', this.onStreamFollow); - this.stream.on('unfollow', this.onStreamUnfollow); + this.connection.on('follow', this.onStreamFollow); + this.connection.on('unfollow', this.onStreamUnfollow); }); }); this.on('unmount', () => { - this.stream.off('follow', this.onStreamFollow); - this.stream.off('unfollow', this.onStreamUnfollow); + this.connection.off('follow', this.onStreamFollow); + this.connection.off('unfollow', this.onStreamUnfollow); + this.stream.dispose(this.connectionId); }); this.onStreamFollow = user => { diff --git a/src/web/app/desktop/tags/home-widgets/channel.tag b/src/web/app/desktop/tags/home-widgets/channel.tag index 28c66df5c0..fc4a27e4f4 100644 --- a/src/web/app/desktop/tags/home-widgets/channel.tag +++ b/src/web/app/desktop/tags/home-widgets/channel.tag @@ -138,7 +138,7 @@ </style> <script> - import ChannelStream from '../../../common/scripts/channel-stream'; + import ChannelStream from '../../../common/scripts/streaming/channel-stream'; this.mixin('api'); diff --git a/src/web/app/desktop/tags/home-widgets/photo-stream.tag b/src/web/app/desktop/tags/home-widgets/photo-stream.tag index fa9207c48d..05658c9025 100644 --- a/src/web/app/desktop/tags/home-widgets/photo-stream.tag +++ b/src/web/app/desktop/tags/home-widgets/photo-stream.tag @@ -75,13 +75,16 @@ }; this.mixin('widget'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.images = []; this.initializing = true; this.on('mount', () => { - this.stream.on('drive_file_created', this.onStreamDriveFileCreated); + this.connection.on('drive_file_created', this.onStreamDriveFileCreated); this.api('drive/stream', { type: 'image/*', @@ -95,7 +98,8 @@ }); this.on('unmount', () => { - this.stream.off('drive_file_created', this.onStreamDriveFileCreated); + this.connection.off('drive_file_created', this.onStreamDriveFileCreated); + this.stream.dispose(this.connectionId); }); this.onStreamDriveFileCreated = file => { diff --git a/src/web/app/desktop/tags/home-widgets/timeline.tag b/src/web/app/desktop/tags/home-widgets/timeline.tag index 5b141b632d..c751069f74 100644 --- a/src/web/app/desktop/tags/home-widgets/timeline.tag +++ b/src/web/app/desktop/tags/home-widgets/timeline.tag @@ -40,7 +40,10 @@ <script> this.mixin('i'); this.mixin('api'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.isLoading = true; this.isEmpty = false; @@ -48,9 +51,9 @@ this.noFollowing = this.I.following_count == 0; this.on('mount', () => { - this.stream.on('post', this.onStreamPost); - this.stream.on('follow', this.onStreamFollow); - this.stream.on('unfollow', this.onStreamUnfollow); + this.connection.on('post', this.onStreamPost); + this.connection.on('follow', this.onStreamFollow); + this.connection.on('unfollow', this.onStreamUnfollow); document.addEventListener('keydown', this.onDocumentKeydown); window.addEventListener('scroll', this.onScroll); @@ -59,9 +62,10 @@ }); this.on('unmount', () => { - this.stream.off('post', this.onStreamPost); - this.stream.off('follow', this.onStreamFollow); - this.stream.off('unfollow', this.onStreamUnfollow); + this.connection.off('post', this.onStreamPost); + this.connection.off('follow', this.onStreamFollow); + this.connection.off('unfollow', this.onStreamUnfollow); + this.stream.dispose(this.connectionId); document.removeEventListener('keydown', this.onDocumentKeydown); window.removeEventListener('scroll', this.onScroll); diff --git a/src/web/app/desktop/tags/notifications.tag b/src/web/app/desktop/tags/notifications.tag index a4f66105a8..d7855363ea 100644 --- a/src/web/app/desktop/tags/notifications.tag +++ b/src/web/app/desktop/tags/notifications.tag @@ -212,9 +212,12 @@ this.mixin('i'); this.mixin('api'); - this.mixin('stream'); this.mixin('user-preview'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); + this.notifications = []; this.loading = true; @@ -235,11 +238,12 @@ }); }); - this.stream.on('notification', this.onNotification); + this.connection.on('notification', this.onNotification); }); this.on('unmount', () => { - this.stream.off('notification', this.onNotification); + this.connection.off('notification', this.onNotification); + this.stream.dispose(this.connectionId); }); this.on('update', () => { @@ -253,7 +257,7 @@ this.onNotification = notification => { // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない - this.stream.send({ + this.connection.send({ type: 'read_notification', id: notification.id }); diff --git a/src/web/app/desktop/tags/pages/home.tag b/src/web/app/desktop/tags/pages/home.tag index e8ba4023de..3c8f4ec570 100644 --- a/src/web/app/desktop/tags/pages/home.tag +++ b/src/web/app/desktop/tags/pages/home.tag @@ -12,10 +12,12 @@ this.mixin('i'); this.mixin('api'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.unreadCount = 0; - this.page = this.opts.mode || 'timeline'; this.on('mount', () => { @@ -24,12 +26,14 @@ }); document.title = 'Misskey'; Progress.start(); - this.stream.on('post', this.onStreamPost); + + this.connection.on('post', this.onStreamPost); document.addEventListener('visibilitychange', this.windowOnVisibilitychange, false); }); this.on('unmount', () => { - this.stream.off('post', this.onStreamPost); + this.connection.off('post', this.onStreamPost); + this.stream.dispose(this.connectionId); document.removeEventListener('visibilitychange', this.windowOnVisibilitychange); }); diff --git a/src/web/app/desktop/tags/timeline.tag b/src/web/app/desktop/tags/timeline.tag index 5e3b883b47..3e745976f3 100644 --- a/src/web/app/desktop/tags/timeline.tag +++ b/src/web/app/desktop/tags/timeline.tag @@ -430,9 +430,12 @@ this.mixin('i'); this.mixin('api'); - this.mixin('stream'); this.mixin('user-preview'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); + this.isDetailOpened = false; this.set = post => { @@ -468,21 +471,21 @@ this.capture = withHandler => { if (this.SIGNIN) { - this.stream.send({ + this.connection.send({ type: 'capture', id: this.post.id }); - if (withHandler) this.stream.on('post-updated', this.onStreamPostUpdated); + if (withHandler) this.connection.on('post-updated', this.onStreamPostUpdated); } }; this.decapture = withHandler => { if (this.SIGNIN) { - this.stream.send({ + this.connection.send({ type: 'decapture', id: this.post.id }); - if (withHandler) this.stream.off('post-updated', this.onStreamPostUpdated); + if (withHandler) this.connection.off('post-updated', this.onStreamPostUpdated); } }; @@ -490,7 +493,7 @@ this.capture(true); if (this.SIGNIN) { - this.stream.on('_connected_', this.onStreamConnected); + this.connection.on('_connected_', this.onStreamConnected); } if (this.p.text) { @@ -515,7 +518,8 @@ this.on('unmount', () => { this.decapture(true); - this.stream.off('_connected_', this.onStreamConnected); + this.connection.off('_connected_', this.onStreamConnected); + this.stream.dispose(this.connectionId); }); this.reply = () => { diff --git a/src/web/app/desktop/tags/ui.tag b/src/web/app/desktop/tags/ui.tag index 36f9cc343f..f7e1bf7463 100644 --- a/src/web/app/desktop/tags/ui.tag +++ b/src/web/app/desktop/tags/ui.tag @@ -423,14 +423,17 @@ <script> this.mixin('i'); this.mixin('api'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.page = this.opts.page; this.on('mount', () => { if (this.SIGNIN) { - this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages); - this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage); + this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages); + this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage); // Fetch count of unread messaging messages this.api('messaging/unread').then(res => { @@ -445,8 +448,9 @@ this.on('unmount', () => { if (this.SIGNIN) { - this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages); - this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage); + this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages); + this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage); + this.stream.dispose(this.connectionId); } }); diff --git a/src/web/app/mobile/tags/follow-button.tag b/src/web/app/mobile/tags/follow-button.tag index 67d580eb99..f25b2ed50e 100644 --- a/src/web/app/mobile/tags/follow-button.tag +++ b/src/web/app/mobile/tags/follow-button.tag @@ -52,7 +52,10 @@ this.mixin('i'); this.mixin('api'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.user = null; this.userPromise = isPromise(this.opts.user) @@ -67,14 +70,15 @@ init: false, user: user }); - this.stream.on('follow', this.onStreamFollow); - this.stream.on('unfollow', this.onStreamUnfollow); + this.connection.on('follow', this.onStreamFollow); + this.connection.on('unfollow', this.onStreamUnfollow); }); }); this.on('unmount', () => { - this.stream.off('follow', this.onStreamFollow); - this.stream.off('unfollow', this.onStreamUnfollow); + this.connection.off('follow', this.onStreamFollow); + this.connection.off('unfollow', this.onStreamUnfollow); + this.stream.dispose(this.connectionId); }); this.onStreamFollow = user => { diff --git a/src/web/app/mobile/tags/home-timeline.tag b/src/web/app/mobile/tags/home-timeline.tag index 051158597d..e96823fa10 100644 --- a/src/web/app/mobile/tags/home-timeline.tag +++ b/src/web/app/mobile/tags/home-timeline.tag @@ -12,7 +12,10 @@ <script> this.mixin('i'); this.mixin('api'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.noFollowing = this.I.following_count == 0; @@ -30,15 +33,16 @@ }; this.on('mount', () => { - this.stream.on('post', this.onStreamPost); - this.stream.on('follow', this.onStreamFollow); - this.stream.on('unfollow', this.onStreamUnfollow); + this.connection.on('post', this.onStreamPost); + this.connection.on('follow', this.onStreamFollow); + this.connection.on('unfollow', this.onStreamUnfollow); }); this.on('unmount', () => { - this.stream.off('post', this.onStreamPost); - this.stream.off('follow', this.onStreamFollow); - this.stream.off('unfollow', this.onStreamUnfollow); + this.connection.off('post', this.onStreamPost); + this.connection.off('follow', this.onStreamFollow); + this.connection.off('unfollow', this.onStreamUnfollow); + this.stream.dispose(this.connectionId); }); this.more = () => { diff --git a/src/web/app/mobile/tags/notifications.tag b/src/web/app/mobile/tags/notifications.tag index 2e95990314..7406fd95e2 100644 --- a/src/web/app/mobile/tags/notifications.tag +++ b/src/web/app/mobile/tags/notifications.tag @@ -82,7 +82,10 @@ this.getPostSummary = getPostSummary; this.mixin('api'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.notifications = []; this.loading = true; @@ -106,11 +109,12 @@ this.trigger('fetched'); }); - this.stream.on('notification', this.onNotification); + this.connection.on('notification', this.onNotification); }); this.on('unmount', () => { - this.stream.off('notification', this.onNotification); + this.connection.off('notification', this.onNotification); + this.stream.dispose(this.connectionId); }); this.on('update', () => { @@ -124,7 +128,7 @@ this.onNotification = notification => { // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない - this.stream.send({ + this.connection.send({ type: 'read_notification', id: notification.id }); diff --git a/src/web/app/mobile/tags/page/home.tag b/src/web/app/mobile/tags/page/home.tag index 3b0255b293..1b2a4b1e13 100644 --- a/src/web/app/mobile/tags/page/home.tag +++ b/src/web/app/mobile/tags/page/home.tag @@ -13,7 +13,10 @@ import openPostForm from '../../scripts/open-post-form'; this.mixin('i'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.unreadCount = 0; @@ -28,7 +31,7 @@ Progress.start(); - this.stream.on('post', this.onStreamPost); + this.connection.on('post', this.onStreamPost); document.addEventListener('visibilitychange', this.onVisibilitychange, false); this.refs.ui.refs.home.on('loaded', () => { @@ -37,7 +40,8 @@ }); this.on('unmount', () => { - this.stream.off('post', this.onStreamPost); + this.connection.off('post', this.onStreamPost); + this.stream.dispose(this.connectionId); document.removeEventListener('visibilitychange', this.onVisibilitychange); }); diff --git a/src/web/app/mobile/tags/timeline.tag b/src/web/app/mobile/tags/timeline.tag index 52f6f27ea8..1d6ce23598 100644 --- a/src/web/app/mobile/tags/timeline.tag +++ b/src/web/app/mobile/tags/timeline.tag @@ -473,7 +473,10 @@ this.mixin('i'); this.mixin('api'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.set = post => { this.post = post; @@ -508,21 +511,21 @@ this.capture = withHandler => { if (this.SIGNIN) { - this.stream.send({ + this.connection.send({ type: 'capture', id: this.post.id }); - if (withHandler) this.stream.on('post-updated', this.onStreamPostUpdated); + if (withHandler) this.connection.on('post-updated', this.onStreamPostUpdated); } }; this.decapture = withHandler => { if (this.SIGNIN) { - this.stream.send({ + this.connection.send({ type: 'decapture', id: this.post.id }); - if (withHandler) this.stream.off('post-updated', this.onStreamPostUpdated); + if (withHandler) this.connection.off('post-updated', this.onStreamPostUpdated); } }; @@ -530,7 +533,7 @@ this.capture(true); if (this.SIGNIN) { - this.stream.on('_connected_', this.onStreamConnected); + this.connection.on('_connected_', this.onStreamConnected); } if (this.p.text) { @@ -555,7 +558,8 @@ this.on('unmount', () => { this.decapture(true); - this.stream.off('_connected_', this.onStreamConnected); + this.connection.off('_connected_', this.onStreamConnected); + this.stream.dispose(this.connectionId); }); this.reply = () => { diff --git a/src/web/app/mobile/tags/ui.tag b/src/web/app/mobile/tags/ui.tag index b2d96f6b8b..0c969d3902 100644 --- a/src/web/app/mobile/tags/ui.tag +++ b/src/web/app/mobile/tags/ui.tag @@ -12,16 +12,20 @@ </style> <script> this.mixin('i'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.isDrawerOpening = false; this.on('mount', () => { - this.stream.on('notification', this.onStreamNotification); + this.connection.on('notification', this.onStreamNotification); }); this.on('unmount', () => { - this.stream.off('notification', this.onStreamNotification); + this.connection.off('notification', this.onStreamNotification); + this.stream.dispose(this.connectionId); }); this.toggleDrawer = () => { @@ -31,7 +35,7 @@ this.onStreamNotification = notification => { // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない - this.stream.send({ + this.connection.send({ type: 'read_notification', id: notification.id }); @@ -145,15 +149,18 @@ import ui from '../scripts/ui-event'; this.mixin('api'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.func = null; this.funcIcon = null; this.on('mount', () => { - this.stream.on('read_all_notifications', this.onReadAllNotifications); - this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages); - this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage); + this.connection.on('read_all_notifications', this.onReadAllNotifications); + this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages); + this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage); // Fetch count of unread notifications this.api('notifications/get_unread_count').then(res => { @@ -175,9 +182,10 @@ }); this.on('unmount', () => { - this.stream.off('read_all_notifications', this.onReadAllNotifications); - this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages); - this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage); + this.connection.off('read_all_notifications', this.onReadAllNotifications); + this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages); + this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage); + this.stream.dispose(this.connectionId); ui.off('title', this.setTitle); ui.off('func', this.setFunc); @@ -348,12 +356,15 @@ this.mixin('i'); this.mixin('page'); this.mixin('api'); + this.mixin('stream'); + this.connection = this.stream.getConnection(); + this.connectionId = this.stream.use(); this.on('mount', () => { - this.stream.on('read_all_notifications', this.onReadAllNotifications); - this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages); - this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage); + this.connection.on('read_all_notifications', this.onReadAllNotifications); + this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages); + this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage); // Fetch count of unread notifications this.api('notifications/get_unread_count').then(res => { @@ -375,9 +386,10 @@ }); this.on('unmount', () => { - this.stream.off('read_all_notifications', this.onReadAllNotifications); - this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages); - this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage); + this.connection.off('read_all_notifications', this.onReadAllNotifications); + this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages); + this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage); + this.stream.dispose(this.connectionId); }); this.onReadAllNotifications = () => { diff --git a/src/web/app/status/tags/index.tag b/src/web/app/status/tags/index.tag index 8e875daf39..8750942c65 100644 --- a/src/web/app/status/tags/index.tag +++ b/src/web/app/status/tags/index.tag @@ -51,7 +51,7 @@ color #546567 </style> <script> - import Connection from '../../common/scripts/server-stream'; + import Connection from '../../common/scripts/streaming/server-stream'; this.mixin('api');