#925, #926, and refactoring

This commit is contained in:
syuilo 2017-11-17 01:24:44 +09:00
parent 4129dce95a
commit c614e6f5d7
38 changed files with 358 additions and 216 deletions

View file

@ -55,7 +55,7 @@
</style> </style>
<script> <script>
import Progress from '../../common/scripts/loading'; 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('i');
this.mixin('api'); this.mixin('api');

View file

@ -2,7 +2,7 @@ import { EventEmitter } from 'eventemitter3';
import * as riot from 'riot'; import * as riot from 'riot';
import signout from './scripts/signout'; import signout from './scripts/signout';
import Progress from './scripts/loading'; 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 CONFIG from './scripts/config';
import api from './scripts/api'; 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() { constructor() {
super(); super();
@ -67,21 +67,27 @@ export default class MiOS extends EventEmitter {
body: JSON.stringify({ body: JSON.stringify({
i: token i: token
}) })
}).then(res => { // When success })
// When success
.then(res => {
// When failed to authenticate user // When failed to authenticate user
if (res.status !== 200) { if (res.status !== 200) {
return signout(); return signout();
} }
// Parse response
res.json().then(i => { res.json().then(i => {
me = i; me = i;
me.token = token; me.token = token;
done(); done();
}); });
}, () => { // When failure })
// When failure
.catch(() => {
// Render the error screen // Render the error screen
document.body.innerHTML = '<mk-error />'; document.body.innerHTML = '<mk-error />';
riot.mount('*'); riot.mount('*');
Progress.done(); Progress.done();
}); });
@ -104,6 +110,7 @@ export default class MiOS extends EventEmitter {
// ローカルストレージにキャッシュ // ローカルストレージにキャッシュ
localStorage.setItem('me', JSON.stringify(me)); localStorage.setItem('me', JSON.stringify(me));
// 自分の情報が更新されたとき
me.on('updated', () => { me.on('updated', () => {
// キャッシュ更新 // キャッシュ更新
localStorage.setItem('me', JSON.stringify(me)); localStorage.setItem('me', JSON.stringify(me));
@ -112,8 +119,10 @@ export default class MiOS extends EventEmitter {
this.i = me; this.i = me;
// Init home stream connection // Init home stream manager
this.stream = this.i ? new Connection(this.i) : null; this.stream = this.isSignedin
? new HomeStreamManager(this.i)
: null;
// Finish init // Finish init
callback(); callback();

View file

@ -1,10 +1,10 @@
import * as riot from 'riot'; import * as riot from 'riot';
import MiOS from './mios'; import MiOS from './mios';
import ServerStreamManager from './scripts/server-stream-manager'; import ServerStreamManager from './scripts/streaming/server-stream-manager';
import RequestsStreamManager from './scripts/requests-stream-manager'; import RequestsStreamManager from './scripts/streaming/requests-stream-manager';
import MessagingIndexStreamManager from './scripts/messaging-index-stream-manager'; import MessagingIndexStreamManager from './scripts/streaming/messaging-index-stream-manager';
import DriveStreamManager from './scripts/drive-stream-manager'; import DriveStreamManager from './scripts/streaming/drive-stream-manager';
export default (mios: MiOS) => { export default (mios: MiOS) => {
(riot as any).mixin('os', { (riot as any).mixin('os', {

View file

@ -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;
}
}
}

View file

@ -3,12 +3,10 @@ import Stream from './stream';
/** /**
* Channel stream connection * Channel stream connection
*/ */
class Connection extends Stream { export default class Connection extends Stream {
constructor(channelId) { constructor(channelId) {
super('channel', { super('channel', {
channel: channelId channel: channelId
}); });
} }
} }
export default Connection;

View file

@ -3,12 +3,10 @@ import Stream from './stream';
/** /**
* Drive stream connection * Drive stream connection
*/ */
class Connection extends Stream { export default class Connection extends Stream {
constructor(me) { constructor(me) {
super('drive', { super('drive', {
i: me.token i: me.token
}); });
} }
} }
export default Connection;

View file

@ -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;
}
}

View file

@ -1,10 +1,10 @@
import Stream from './stream'; import Stream from './stream';
import signout from './signout'; import signout from '../signout';
/** /**
* Home stream connection * Home stream connection
*/ */
class Connection extends Stream { export default class Connection extends Stream {
constructor(me) { constructor(me) {
super('', { super('', {
i: me.token i: me.token
@ -15,13 +15,14 @@ class Connection extends Stream {
this.send({ type: 'alive' }); this.send({ type: 'alive' });
}, 1000 * 60); }, 1000 * 60);
// 自分の情報が更新されたとき
(this as any).on('i_updated', me.update); (this as any).on('i_updated', me.update);
// トークンが再生成されたとき
// このままではAPIが利用できないので強制的にサインアウトさせる
(this as any).on('my_token_regenerated', () => { (this as any).on('my_token_regenerated', () => {
alert('%i18n:common.my-token-regenerated%'); alert('%i18n:common.my-token-regenerated%');
signout(); signout();
}); });
} }
} }
export default Connection;

View file

@ -3,12 +3,10 @@ import Stream from './stream';
/** /**
* Messaging index stream connection * Messaging index stream connection
*/ */
class Connection extends Stream { export default class Connection extends Stream {
constructor(me) { constructor(me) {
super('messaging-index', { super('messaging-index', {
i: me.token i: me.token
}); });
} }
} }
export default Connection;

View file

@ -3,7 +3,7 @@ import Stream from './stream';
/** /**
* Messaging stream connection * Messaging stream connection
*/ */
class Connection extends Stream { export default class Connection extends Stream {
constructor(me, otherparty) { constructor(me, otherparty) {
super('messaging', { super('messaging', {
i: me.token, i: me.token,
@ -17,5 +17,3 @@ class Connection extends Stream {
}); });
} }
} }
export default Connection;

View file

@ -3,10 +3,8 @@ import Stream from './stream';
/** /**
* Requests stream connection * Requests stream connection
*/ */
class Connection extends Stream { export default class Connection extends Stream {
constructor() { constructor() {
super('requests'); super('requests');
} }
} }
export default Connection;

View file

@ -3,10 +3,8 @@ import Stream from './stream';
/** /**
* Server stream connection * Server stream connection
*/ */
class Connection extends Stream { export default class Connection extends Stream {
constructor() { constructor() {
super('server'); super('server');
} }
} }
export default Connection;

View file

@ -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;
}
}
}

View file

@ -1,25 +1,25 @@
import { EventEmitter } from 'eventemitter3';
import * as ReconnectingWebsocket from 'reconnecting-websocket'; import * as ReconnectingWebsocket from 'reconnecting-websocket';
import * as riot from 'riot'; import CONFIG from '../config';
import CONFIG from './config';
/** /**
* Misskey stream connection * Misskey stream connection
*/ */
class Connection { export default class Connection extends EventEmitter {
private state: string; private state: string;
private buffer: any[]; private buffer: any[];
private socket: ReconnectingWebsocket; private socket: ReconnectingWebsocket;
constructor(endpoint, params?) { constructor(endpoint, params?) {
// BIND ----------------------------------- super();
//#region BIND
this.onOpen = this.onOpen.bind(this); this.onOpen = this.onOpen.bind(this);
this.onClose = this.onClose.bind(this); this.onClose = this.onClose.bind(this);
this.onMessage = this.onMessage.bind(this); this.onMessage = this.onMessage.bind(this);
this.send = this.send.bind(this); this.send = this.send.bind(this);
this.close = this.close.bind(this); this.close = this.close.bind(this);
// ---------------------------------------- //#endregion
riot.observable(this);
this.state = 'initializing'; this.state = 'initializing';
this.buffer = []; this.buffer = [];
@ -42,7 +42,7 @@ class Connection {
*/ */
private onOpen() { private onOpen() {
this.state = 'connected'; this.state = 'connected';
(this as any).trigger('_connected_'); this.emit('_connected_');
// バッファーを処理 // バッファーを処理
const _buffer = [].concat(this.buffer); // Shallow copy const _buffer = [].concat(this.buffer); // Shallow copy
@ -57,7 +57,7 @@ class Connection {
*/ */
private onClose() { private onClose() {
this.state = 'reconnecting'; this.state = 'reconnecting';
(this as any).trigger('_closed_'); this.emit('_closed_');
} }
/** /**
@ -66,7 +66,7 @@ class Connection {
private onMessage(message) { private onMessage(message) {
try { try {
const msg = JSON.parse(message.data); 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) { } catch (e) {
// noop // noop
} }
@ -93,5 +93,3 @@ class Connection {
this.socket.removeEventListener('message', this.onMessage); this.socket.removeEventListener('message', this.onMessage);
} }
} }
export default Connection;

View file

@ -162,7 +162,7 @@
</style> </style>
<script> <script>
import MessagingStreamConnection from '../../scripts/messaging-stream'; import MessagingStreamConnection from '../../scripts/streaming/messaging-stream';
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');

View file

@ -50,7 +50,10 @@
<script> <script>
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.history = []; this.history = [];
this.fetching = true; this.fetching = true;
@ -63,11 +66,12 @@
}); });
}); });
this.stream.on('signin', this.onSignin); this.connection.on('signin', this.onSignin);
}); });
this.on('unmount', () => { this.on('unmount', () => {
this.stream.off('signin', this.onSignin); this.connection.off('signin', this.onSignin);
this.stream.dispose(this.connectionId);
}); });
this.onSignin = signin => { this.onSignin = signin => {

View file

@ -1,13 +1,13 @@
<mk-stream-indicator> <mk-stream-indicator>
<p if={ stream.state == 'initializing' }> <p if={ connection.state == 'initializing' }>
<i class="fa fa-spinner fa-spin"></i> <i class="fa fa-spinner fa-spin"></i>
<span>%i18n:common.tags.mk-stream-indicator.connecting%<mk-ellipsis/></span> <span>%i18n:common.tags.mk-stream-indicator.connecting%<mk-ellipsis/></span>
</p> </p>
<p if={ stream.state == 'reconnecting' }> <p if={ connection.state == 'reconnecting' }>
<i class="fa fa-spinner fa-spin"></i> <i class="fa fa-spinner fa-spin"></i>
<span>%i18n:common.tags.mk-stream-indicator.reconnecting%<mk-ellipsis/></span> <span>%i18n:common.tags.mk-stream-indicator.reconnecting%<mk-ellipsis/></span>
</p> </p>
<p if={ stream.state == 'connected' }> <p if={ connection.state == 'connected' }>
<i class="fa fa-check"></i> <i class="fa fa-check"></i>
<span>%i18n:common.tags.mk-stream-indicator.connected%</span> <span>%i18n:common.tags.mk-stream-indicator.connected%</span>
</p> </p>
@ -38,34 +38,41 @@
import anime from 'animejs'; import anime from 'animejs';
this.mixin('i'); this.mixin('i');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.on('before-mount', () => { this.on('before-mount', () => {
if (this.stream.state == 'connected') { if (this.connection.state == 'connected') {
this.root.style.opacity = 0; this.root.style.opacity = 0;
} }
});
this.stream.on('_connected_', () => { this.connection.on('_connected_', () => {
this.update(); this.update();
setTimeout(() => { setTimeout(() => {
anime({
targets: this.root,
opacity: 0,
easing: 'linear',
duration: 200
});
}, 1000);
});
this.connection.on('_closed_', () => {
this.update();
anime({ anime({
targets: this.root, targets: this.root,
opacity: 0, opacity: 1,
easing: 'linear', easing: 'linear',
duration: 200 duration: 100
}); });
}, 1000); });
}); });
this.stream.on('_closed_', () => { this.on('unmount', () => {
this.update(); this.stream.dispose(this.connectionId);
anime({
targets: this.root,
opacity: 1,
easing: 'linear',
duration: 100
});
}); });
</script> </script>
</mk-stream-indicator> </mk-stream-indicator>

View file

@ -13,6 +13,7 @@ import route from './router';
import fuckAdBlock from './scripts/fuck-ad-block'; import fuckAdBlock from './scripts/fuck-ad-block';
import getPostSummary from '../../../common/get-post-summary'; import getPostSummary from '../../../common/get-post-summary';
import MiOS from '../common/mios'; import MiOS from '../common/mios';
import HomeStreamManager from '../common/scripts/streaming/home-stream-manager';
/** /**
* init * init
@ -41,52 +42,62 @@ init(async (mios: MiOS) => {
route(mios); route(mios);
}); });
function registerNotifications(stream) { function registerNotifications(stream: HomeStreamManager) {
if (stream == null) return; if (stream == null) return;
stream.on('drive_file_created', file => { if (stream.hasConnection) {
const n = new Notification('ファイルがアップロードされました', { attach(stream.borrow());
body: file.name, }
icon: file.url + '?thumbnail&size=64'
}); stream.on('connected', connection => {
setTimeout(n.close.bind(n), 5000); attach(connection);
}); });
stream.on('mention', post => { function attach(connection) {
const n = new Notification(`${post.user.name}さんから:`, { connection.on('drive_file_created', file => {
body: getPostSummary(post), const n = new Notification('ファイルがアップロードされました', {
icon: post.user.avatar_url + '?thumbnail&size=64' body: file.name,
}); icon: file.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
}); });
}; setTimeout(n.close.bind(n), 5000);
setTimeout(n.close.bind(n), 7000); });
});
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);
});
}
} }

View file

@ -74,7 +74,10 @@
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.user = null; this.user = null;
this.userPromise = isPromise(this.opts.user) this.userPromise = isPromise(this.opts.user)
@ -89,14 +92,15 @@
init: false, init: false,
user: user user: user
}); });
this.stream.on('follow', this.onStreamFollow); this.connection.on('follow', this.onStreamFollow);
this.stream.on('unfollow', this.onStreamUnfollow); this.connection.on('unfollow', this.onStreamUnfollow);
}); });
}); });
this.on('unmount', () => { this.on('unmount', () => {
this.stream.off('follow', this.onStreamFollow); this.connection.off('follow', this.onStreamFollow);
this.stream.off('unfollow', this.onStreamUnfollow); this.connection.off('unfollow', this.onStreamUnfollow);
this.stream.dispose(this.connectionId);
}); });
this.onStreamFollow = user => { this.onStreamFollow = user => {

View file

@ -71,7 +71,10 @@
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.user = null; this.user = null;
this.userPromise = isPromise(this.opts.user) this.userPromise = isPromise(this.opts.user)
@ -86,14 +89,15 @@
init: false, init: false,
user: user user: user
}); });
this.stream.on('follow', this.onStreamFollow); this.connection.on('follow', this.onStreamFollow);
this.stream.on('unfollow', this.onStreamUnfollow); this.connection.on('unfollow', this.onStreamUnfollow);
}); });
}); });
this.on('unmount', () => { this.on('unmount', () => {
this.stream.off('follow', this.onStreamFollow); this.connection.off('follow', this.onStreamFollow);
this.stream.off('unfollow', this.onStreamUnfollow); this.connection.off('unfollow', this.onStreamUnfollow);
this.stream.dispose(this.connectionId);
}); });
this.onStreamFollow = user => { this.onStreamFollow = user => {

View file

@ -138,7 +138,7 @@
</style> </style>
<script> <script>
import ChannelStream from '../../../common/scripts/channel-stream'; import ChannelStream from '../../../common/scripts/streaming/channel-stream';
this.mixin('api'); this.mixin('api');

View file

@ -75,13 +75,16 @@
}; };
this.mixin('widget'); this.mixin('widget');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.images = []; this.images = [];
this.initializing = true; this.initializing = true;
this.on('mount', () => { this.on('mount', () => {
this.stream.on('drive_file_created', this.onStreamDriveFileCreated); this.connection.on('drive_file_created', this.onStreamDriveFileCreated);
this.api('drive/stream', { this.api('drive/stream', {
type: 'image/*', type: 'image/*',
@ -95,7 +98,8 @@
}); });
this.on('unmount', () => { 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 => { this.onStreamDriveFileCreated = file => {

View file

@ -40,7 +40,10 @@
<script> <script>
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.isLoading = true; this.isLoading = true;
this.isEmpty = false; this.isEmpty = false;
@ -48,9 +51,9 @@
this.noFollowing = this.I.following_count == 0; this.noFollowing = this.I.following_count == 0;
this.on('mount', () => { this.on('mount', () => {
this.stream.on('post', this.onStreamPost); this.connection.on('post', this.onStreamPost);
this.stream.on('follow', this.onStreamFollow); this.connection.on('follow', this.onStreamFollow);
this.stream.on('unfollow', this.onStreamUnfollow); this.connection.on('unfollow', this.onStreamUnfollow);
document.addEventListener('keydown', this.onDocumentKeydown); document.addEventListener('keydown', this.onDocumentKeydown);
window.addEventListener('scroll', this.onScroll); window.addEventListener('scroll', this.onScroll);
@ -59,9 +62,10 @@
}); });
this.on('unmount', () => { this.on('unmount', () => {
this.stream.off('post', this.onStreamPost); this.connection.off('post', this.onStreamPost);
this.stream.off('follow', this.onStreamFollow); this.connection.off('follow', this.onStreamFollow);
this.stream.off('unfollow', this.onStreamUnfollow); this.connection.off('unfollow', this.onStreamUnfollow);
this.stream.dispose(this.connectionId);
document.removeEventListener('keydown', this.onDocumentKeydown); document.removeEventListener('keydown', this.onDocumentKeydown);
window.removeEventListener('scroll', this.onScroll); window.removeEventListener('scroll', this.onScroll);

View file

@ -212,9 +212,12 @@
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');
this.mixin('stream');
this.mixin('user-preview'); this.mixin('user-preview');
this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.notifications = []; this.notifications = [];
this.loading = true; this.loading = true;
@ -235,11 +238,12 @@
}); });
}); });
this.stream.on('notification', this.onNotification); this.connection.on('notification', this.onNotification);
}); });
this.on('unmount', () => { this.on('unmount', () => {
this.stream.off('notification', this.onNotification); this.connection.off('notification', this.onNotification);
this.stream.dispose(this.connectionId);
}); });
this.on('update', () => { this.on('update', () => {
@ -253,7 +257,7 @@
this.onNotification = notification => { this.onNotification = notification => {
// TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない
this.stream.send({ this.connection.send({
type: 'read_notification', type: 'read_notification',
id: notification.id id: notification.id
}); });

View file

@ -12,10 +12,12 @@
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.unreadCount = 0; this.unreadCount = 0;
this.page = this.opts.mode || 'timeline'; this.page = this.opts.mode || 'timeline';
this.on('mount', () => { this.on('mount', () => {
@ -24,12 +26,14 @@
}); });
document.title = 'Misskey'; document.title = 'Misskey';
Progress.start(); Progress.start();
this.stream.on('post', this.onStreamPost);
this.connection.on('post', this.onStreamPost);
document.addEventListener('visibilitychange', this.windowOnVisibilitychange, false); document.addEventListener('visibilitychange', this.windowOnVisibilitychange, false);
}); });
this.on('unmount', () => { 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); document.removeEventListener('visibilitychange', this.windowOnVisibilitychange);
}); });

View file

@ -430,9 +430,12 @@
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');
this.mixin('stream');
this.mixin('user-preview'); this.mixin('user-preview');
this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.isDetailOpened = false; this.isDetailOpened = false;
this.set = post => { this.set = post => {
@ -468,21 +471,21 @@
this.capture = withHandler => { this.capture = withHandler => {
if (this.SIGNIN) { if (this.SIGNIN) {
this.stream.send({ this.connection.send({
type: 'capture', type: 'capture',
id: this.post.id 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 => { this.decapture = withHandler => {
if (this.SIGNIN) { if (this.SIGNIN) {
this.stream.send({ this.connection.send({
type: 'decapture', type: 'decapture',
id: this.post.id 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); this.capture(true);
if (this.SIGNIN) { if (this.SIGNIN) {
this.stream.on('_connected_', this.onStreamConnected); this.connection.on('_connected_', this.onStreamConnected);
} }
if (this.p.text) { if (this.p.text) {
@ -515,7 +518,8 @@
this.on('unmount', () => { this.on('unmount', () => {
this.decapture(true); this.decapture(true);
this.stream.off('_connected_', this.onStreamConnected); this.connection.off('_connected_', this.onStreamConnected);
this.stream.dispose(this.connectionId);
}); });
this.reply = () => { this.reply = () => {

View file

@ -423,14 +423,17 @@
<script> <script>
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.page = this.opts.page; this.page = this.opts.page;
this.on('mount', () => { this.on('mount', () => {
if (this.SIGNIN) { if (this.SIGNIN) {
this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages); this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages);
this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage); this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage);
// Fetch count of unread messaging messages // Fetch count of unread messaging messages
this.api('messaging/unread').then(res => { this.api('messaging/unread').then(res => {
@ -445,8 +448,9 @@
this.on('unmount', () => { this.on('unmount', () => {
if (this.SIGNIN) { if (this.SIGNIN) {
this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages); this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages);
this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage); this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage);
this.stream.dispose(this.connectionId);
} }
}); });

View file

@ -52,7 +52,10 @@
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.user = null; this.user = null;
this.userPromise = isPromise(this.opts.user) this.userPromise = isPromise(this.opts.user)
@ -67,14 +70,15 @@
init: false, init: false,
user: user user: user
}); });
this.stream.on('follow', this.onStreamFollow); this.connection.on('follow', this.onStreamFollow);
this.stream.on('unfollow', this.onStreamUnfollow); this.connection.on('unfollow', this.onStreamUnfollow);
}); });
}); });
this.on('unmount', () => { this.on('unmount', () => {
this.stream.off('follow', this.onStreamFollow); this.connection.off('follow', this.onStreamFollow);
this.stream.off('unfollow', this.onStreamUnfollow); this.connection.off('unfollow', this.onStreamUnfollow);
this.stream.dispose(this.connectionId);
}); });
this.onStreamFollow = user => { this.onStreamFollow = user => {

View file

@ -12,7 +12,10 @@
<script> <script>
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.noFollowing = this.I.following_count == 0; this.noFollowing = this.I.following_count == 0;
@ -30,15 +33,16 @@
}; };
this.on('mount', () => { this.on('mount', () => {
this.stream.on('post', this.onStreamPost); this.connection.on('post', this.onStreamPost);
this.stream.on('follow', this.onStreamFollow); this.connection.on('follow', this.onStreamFollow);
this.stream.on('unfollow', this.onStreamUnfollow); this.connection.on('unfollow', this.onStreamUnfollow);
}); });
this.on('unmount', () => { this.on('unmount', () => {
this.stream.off('post', this.onStreamPost); this.connection.off('post', this.onStreamPost);
this.stream.off('follow', this.onStreamFollow); this.connection.off('follow', this.onStreamFollow);
this.stream.off('unfollow', this.onStreamUnfollow); this.connection.off('unfollow', this.onStreamUnfollow);
this.stream.dispose(this.connectionId);
}); });
this.more = () => { this.more = () => {

View file

@ -82,7 +82,10 @@
this.getPostSummary = getPostSummary; this.getPostSummary = getPostSummary;
this.mixin('api'); this.mixin('api');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.notifications = []; this.notifications = [];
this.loading = true; this.loading = true;
@ -106,11 +109,12 @@
this.trigger('fetched'); this.trigger('fetched');
}); });
this.stream.on('notification', this.onNotification); this.connection.on('notification', this.onNotification);
}); });
this.on('unmount', () => { this.on('unmount', () => {
this.stream.off('notification', this.onNotification); this.connection.off('notification', this.onNotification);
this.stream.dispose(this.connectionId);
}); });
this.on('update', () => { this.on('update', () => {
@ -124,7 +128,7 @@
this.onNotification = notification => { this.onNotification = notification => {
// TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない
this.stream.send({ this.connection.send({
type: 'read_notification', type: 'read_notification',
id: notification.id id: notification.id
}); });

View file

@ -13,7 +13,10 @@
import openPostForm from '../../scripts/open-post-form'; import openPostForm from '../../scripts/open-post-form';
this.mixin('i'); this.mixin('i');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.unreadCount = 0; this.unreadCount = 0;
@ -28,7 +31,7 @@
Progress.start(); Progress.start();
this.stream.on('post', this.onStreamPost); this.connection.on('post', this.onStreamPost);
document.addEventListener('visibilitychange', this.onVisibilitychange, false); document.addEventListener('visibilitychange', this.onVisibilitychange, false);
this.refs.ui.refs.home.on('loaded', () => { this.refs.ui.refs.home.on('loaded', () => {
@ -37,7 +40,8 @@
}); });
this.on('unmount', () => { 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); document.removeEventListener('visibilitychange', this.onVisibilitychange);
}); });

View file

@ -473,7 +473,10 @@
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.set = post => { this.set = post => {
this.post = post; this.post = post;
@ -508,21 +511,21 @@
this.capture = withHandler => { this.capture = withHandler => {
if (this.SIGNIN) { if (this.SIGNIN) {
this.stream.send({ this.connection.send({
type: 'capture', type: 'capture',
id: this.post.id 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 => { this.decapture = withHandler => {
if (this.SIGNIN) { if (this.SIGNIN) {
this.stream.send({ this.connection.send({
type: 'decapture', type: 'decapture',
id: this.post.id 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); this.capture(true);
if (this.SIGNIN) { if (this.SIGNIN) {
this.stream.on('_connected_', this.onStreamConnected); this.connection.on('_connected_', this.onStreamConnected);
} }
if (this.p.text) { if (this.p.text) {
@ -555,7 +558,8 @@
this.on('unmount', () => { this.on('unmount', () => {
this.decapture(true); this.decapture(true);
this.stream.off('_connected_', this.onStreamConnected); this.connection.off('_connected_', this.onStreamConnected);
this.stream.dispose(this.connectionId);
}); });
this.reply = () => { this.reply = () => {

View file

@ -12,16 +12,20 @@
</style> </style>
<script> <script>
this.mixin('i'); this.mixin('i');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.isDrawerOpening = false; this.isDrawerOpening = false;
this.on('mount', () => { this.on('mount', () => {
this.stream.on('notification', this.onStreamNotification); this.connection.on('notification', this.onStreamNotification);
}); });
this.on('unmount', () => { this.on('unmount', () => {
this.stream.off('notification', this.onStreamNotification); this.connection.off('notification', this.onStreamNotification);
this.stream.dispose(this.connectionId);
}); });
this.toggleDrawer = () => { this.toggleDrawer = () => {
@ -31,7 +35,7 @@
this.onStreamNotification = notification => { this.onStreamNotification = notification => {
// TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない
this.stream.send({ this.connection.send({
type: 'read_notification', type: 'read_notification',
id: notification.id id: notification.id
}); });
@ -145,15 +149,18 @@
import ui from '../scripts/ui-event'; import ui from '../scripts/ui-event';
this.mixin('api'); this.mixin('api');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.func = null; this.func = null;
this.funcIcon = null; this.funcIcon = null;
this.on('mount', () => { this.on('mount', () => {
this.stream.on('read_all_notifications', this.onReadAllNotifications); this.connection.on('read_all_notifications', this.onReadAllNotifications);
this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages); this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages);
this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage); this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage);
// Fetch count of unread notifications // Fetch count of unread notifications
this.api('notifications/get_unread_count').then(res => { this.api('notifications/get_unread_count').then(res => {
@ -175,9 +182,10 @@
}); });
this.on('unmount', () => { this.on('unmount', () => {
this.stream.off('read_all_notifications', this.onReadAllNotifications); this.connection.off('read_all_notifications', this.onReadAllNotifications);
this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages); this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages);
this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage); this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage);
this.stream.dispose(this.connectionId);
ui.off('title', this.setTitle); ui.off('title', this.setTitle);
ui.off('func', this.setFunc); ui.off('func', this.setFunc);
@ -348,12 +356,15 @@
this.mixin('i'); this.mixin('i');
this.mixin('page'); this.mixin('page');
this.mixin('api'); this.mixin('api');
this.mixin('stream'); this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.on('mount', () => { this.on('mount', () => {
this.stream.on('read_all_notifications', this.onReadAllNotifications); this.connection.on('read_all_notifications', this.onReadAllNotifications);
this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages); this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages);
this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage); this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage);
// Fetch count of unread notifications // Fetch count of unread notifications
this.api('notifications/get_unread_count').then(res => { this.api('notifications/get_unread_count').then(res => {
@ -375,9 +386,10 @@
}); });
this.on('unmount', () => { this.on('unmount', () => {
this.stream.off('read_all_notifications', this.onReadAllNotifications); this.connection.off('read_all_notifications', this.onReadAllNotifications);
this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages); this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages);
this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage); this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage);
this.stream.dispose(this.connectionId);
}); });
this.onReadAllNotifications = () => { this.onReadAllNotifications = () => {

View file

@ -51,7 +51,7 @@
color #546567 color #546567
</style> </style>
<script> <script>
import Connection from '../../common/scripts/server-stream'; import Connection from '../../common/scripts/streaming/server-stream';
this.mixin('api'); this.mixin('api');