parent
4129dce95a
commit
c614e6f5d7
38 changed files with 358 additions and 216 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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', {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
20
src/web/app/common/scripts/streaming/home-stream-manager.ts
Normal file
20
src/web/app/common/scripts/streaming/home-stream-manager.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
73
src/web/app/common/scripts/streaming/stream-manager.ts
Normal file
73
src/web/app/common/scripts/streaming/stream-manager.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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 => {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue