wip #7533
This commit is contained in:
		
							parent
							
								
									c92744c3d3
								
							
						
					
					
						commit
						ae2267220b
					
				
					 23 changed files with 69 additions and 386 deletions
				
			
		|  | @ -174,6 +174,7 @@ | |||
| 		"markdown-it-anchor": "7.1.0", | ||||
| 		"matter-js": "0.17.1", | ||||
| 		"mfm-js": "0.16.4", | ||||
| 		"misskey-js": "0.0.2", | ||||
| 		"mocha": "8.4.0", | ||||
| 		"moji": "0.5.1", | ||||
| 		"ms": "2.1.3", | ||||
|  |  | |||
|  | @ -139,7 +139,7 @@ export default defineComponent({ | |||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		this.connection = os.stream.useSharedConnection('drive'); | ||||
| 		this.connection = os.stream.useChannel('drive'); | ||||
| 
 | ||||
| 		this.connection.on('fileCreated', this.onStreamDriveFileCreated); | ||||
| 		this.connection.on('fileUpdated', this.onStreamDriveFileUpdated); | ||||
|  | @ -301,7 +301,7 @@ export default defineComponent({ | |||
| 				} | ||||
| 			}).then(({ canceled, result: url }) => { | ||||
| 				if (canceled) return; | ||||
| 				os.api('drive/files/upload_from_url', { | ||||
| 				os.api('drive/files/upload-from-url', { | ||||
| 					url: url, | ||||
| 					folderId: this.folder ? this.folder.id : undefined | ||||
| 				}); | ||||
|  |  | |||
|  | @ -71,7 +71,7 @@ export default defineComponent({ | |||
| 	}, | ||||
| 
 | ||||
| 	mounted() { | ||||
| 		this.connection = os.stream.useSharedConnection('main'); | ||||
| 		this.connection = os.stream.useChannel('main'); | ||||
| 
 | ||||
| 		this.connection.on('follow', this.onFollowChange); | ||||
| 		this.connection.on('unfollow', this.onFollowChange); | ||||
|  |  | |||
|  | @ -109,7 +109,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 			this.readObserver.observe(this.$el); | ||||
| 
 | ||||
| 			this.connection = os.stream.useSharedConnection('main'); | ||||
| 			this.connection = os.stream.useChannel('main'); | ||||
| 			this.connection.on('readAllNotifications', () => this.readObserver.unobserve(this.$el)); | ||||
| 		} | ||||
| 	}, | ||||
|  |  | |||
|  | @ -87,7 +87,7 @@ export default defineComponent({ | |||
| 	}, | ||||
| 
 | ||||
| 	mounted() { | ||||
| 		this.connection = os.stream.useSharedConnection('main'); | ||||
| 		this.connection = os.stream.useChannel('main'); | ||||
| 		this.connection.on('notification', this.onNotification); | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -92,33 +92,33 @@ export default defineComponent({ | |||
| 			this.query = { | ||||
| 				antennaId: this.antenna | ||||
| 			}; | ||||
| 			this.connection = os.stream.connectToChannel('antenna', { | ||||
| 			this.connection = os.stream.useChannel('antenna', { | ||||
| 				antennaId: this.antenna | ||||
| 			}); | ||||
| 			this.connection.on('note', prepend); | ||||
| 		} else if (this.src == 'home') { | ||||
| 			endpoint = 'notes/timeline'; | ||||
| 			this.connection = os.stream.useSharedConnection('homeTimeline'); | ||||
| 			this.connection = os.stream.useChannel('homeTimeline'); | ||||
| 			this.connection.on('note', prepend); | ||||
| 
 | ||||
| 			this.connection2 = os.stream.useSharedConnection('main'); | ||||
| 			this.connection2 = os.stream.useChannel('main'); | ||||
| 			this.connection2.on('follow', onChangeFollowing); | ||||
| 			this.connection2.on('unfollow', onChangeFollowing); | ||||
| 		} else if (this.src == 'local') { | ||||
| 			endpoint = 'notes/local-timeline'; | ||||
| 			this.connection = os.stream.useSharedConnection('localTimeline'); | ||||
| 			this.connection = os.stream.useChannel('localTimeline'); | ||||
| 			this.connection.on('note', prepend); | ||||
| 		} else if (this.src == 'social') { | ||||
| 			endpoint = 'notes/hybrid-timeline'; | ||||
| 			this.connection = os.stream.useSharedConnection('hybridTimeline'); | ||||
| 			this.connection = os.stream.useChannel('hybridTimeline'); | ||||
| 			this.connection.on('note', prepend); | ||||
| 		} else if (this.src == 'global') { | ||||
| 			endpoint = 'notes/global-timeline'; | ||||
| 			this.connection = os.stream.useSharedConnection('globalTimeline'); | ||||
| 			this.connection = os.stream.useChannel('globalTimeline'); | ||||
| 			this.connection.on('note', prepend); | ||||
| 		} else if (this.src == 'mentions') { | ||||
| 			endpoint = 'notes/mentions'; | ||||
| 			this.connection = os.stream.useSharedConnection('main'); | ||||
| 			this.connection = os.stream.useChannel('main'); | ||||
| 			this.connection.on('mention', prepend); | ||||
| 		} else if (this.src == 'directs') { | ||||
| 			endpoint = 'notes/mentions'; | ||||
|  | @ -130,14 +130,14 @@ export default defineComponent({ | |||
| 					prepend(note); | ||||
| 				} | ||||
| 			}; | ||||
| 			this.connection = os.stream.useSharedConnection('main'); | ||||
| 			this.connection = os.stream.useChannel('main'); | ||||
| 			this.connection.on('mention', onNote); | ||||
| 		} else if (this.src == 'list') { | ||||
| 			endpoint = 'notes/user-list-timeline'; | ||||
| 			this.query = { | ||||
| 				listId: this.list | ||||
| 			}; | ||||
| 			this.connection = os.stream.connectToChannel('userList', { | ||||
| 			this.connection = os.stream.useChannel('userList', { | ||||
| 				listId: this.list | ||||
| 			}); | ||||
| 			this.connection.on('note', prepend); | ||||
|  | @ -148,7 +148,7 @@ export default defineComponent({ | |||
| 			this.query = { | ||||
| 				channelId: this.channel | ||||
| 			}; | ||||
| 			this.connection = os.stream.connectToChannel('channel', { | ||||
| 			this.connection = os.stream.useChannel('channel', { | ||||
| 				channelId: this.channel | ||||
| 			}); | ||||
| 			this.connection.on('note', prepend); | ||||
|  |  | |||
|  | @ -163,8 +163,6 @@ fetchInstance().then(() => { | |||
| 	initializeSw(); | ||||
| }); | ||||
| 
 | ||||
| stream.init($i); | ||||
| 
 | ||||
| const app = createApp(await ( | ||||
| 	window.location.search === '?zen' ? import('@client/ui/zen.vue') : | ||||
| 	!$i                               ? import('@client/ui/visitor.vue') : | ||||
|  | @ -296,7 +294,7 @@ if ($i) { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	const main = stream.useSharedConnection('main', 'System'); | ||||
| 	const main = stream.useChannel('main', 'System'); | ||||
| 
 | ||||
| 	// 自分の情報が更新されたとき
 | ||||
| 	main.on('meUpdated', i => { | ||||
|  | @ -358,10 +356,6 @@ if ($i) { | |||
| 		sound.play('channel'); | ||||
| 	}); | ||||
| 
 | ||||
| 	main.on('readAllAnnouncements', () => { | ||||
| 		updateAccount({ hasUnreadAnnouncement: false }); | ||||
| 	}); | ||||
| 
 | ||||
| 	// トークンが再生成されたとき
 | ||||
| 	// このままではMisskeyが利用できないので強制的にサインアウトさせる
 | ||||
| 	main.on('myTokenRegenerated', () => { | ||||
|  |  | |||
|  | @ -1,26 +1,14 @@ | |||
| import { computed, reactive } from 'vue'; | ||||
| import * as Misskey from 'misskey-js'; | ||||
| import { api } from './os'; | ||||
| 
 | ||||
| // TODO: 他のタブと永続化されたstateを同期
 | ||||
| 
 | ||||
| export type Instance = { | ||||
| 	emojis: { | ||||
| 		category: string; | ||||
| 	}[]; | ||||
| 	ads: { | ||||
| 		id: string; | ||||
| 		ratio: number; | ||||
| 		place: string; | ||||
| 		url: string; | ||||
| 		imageUrl: string; | ||||
| 	}[]; | ||||
| }; | ||||
| 
 | ||||
| const data = localStorage.getItem('instance'); | ||||
| 
 | ||||
| // TODO: instanceをリアクティブにするかは再考の余地あり
 | ||||
| 
 | ||||
| export const instance: Instance = reactive(data ? JSON.parse(data) : { | ||||
| export const instance: Misskey.entities.InstanceMetadata = reactive(data ? JSON.parse(data) : { | ||||
| 	// TODO: set default values
 | ||||
| }); | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,16 +3,16 @@ | |||
| import { Component, defineAsyncComponent, markRaw, reactive, Ref, ref } from 'vue'; | ||||
| import { EventEmitter } from 'eventemitter3'; | ||||
| import insertTextAtCursor from 'insert-text-at-cursor'; | ||||
| import * as Misskey from 'misskey-js'; | ||||
| import * as Sentry from '@sentry/browser'; | ||||
| import Stream from '@client/scripts/stream'; | ||||
| import { apiUrl, debug } from '@client/config'; | ||||
| import { apiUrl, debug, url } from '@client/config'; | ||||
| import MkPostFormDialog from '@client/components/post-form-dialog.vue'; | ||||
| import MkWaitingDialog from '@client/components/waiting-dialog.vue'; | ||||
| import { resolve } from '@client/router'; | ||||
| import { $i } from '@client/account'; | ||||
| import { defaultStore } from '@client/store'; | ||||
| 
 | ||||
| export const stream = markRaw(new Stream()); | ||||
| export const stream = markRaw(new Misskey.Stream(url, $i)); | ||||
| 
 | ||||
| export const pendingApiRequestsCount = ref(0); | ||||
| let apiRequestsCount = 0; // for debug
 | ||||
|  | @ -20,7 +20,11 @@ export const apiRequests = ref([]); // for debug | |||
| 
 | ||||
| export const windows = new Map(); | ||||
| 
 | ||||
| export function api(endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) { | ||||
| const apiClient = new Misskey.api.APIClient({ | ||||
| 	origin: url, | ||||
| }); | ||||
| 
 | ||||
| export const api = ((endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) => { | ||||
| 	pendingApiRequestsCount.value++; | ||||
| 
 | ||||
| 	const onFinally = () => { | ||||
|  | @ -90,17 +94,15 @@ export function api(endpoint: string, data: Record<string, any> = {}, token?: st | |||
| 	promise.then(onFinally, onFinally); | ||||
| 
 | ||||
| 	return promise; | ||||
| } | ||||
| }) as typeof apiClient.request; | ||||
| 
 | ||||
| export function apiWithDialog( | ||||
| export const apiWithDialog = (( | ||||
| 	endpoint: string, | ||||
| 	data: Record<string, any> = {}, | ||||
| 	token?: string | null | undefined, | ||||
| 	onSuccess?: (res: any) => void, | ||||
| 	onFailure?: (e: Error) => void, | ||||
| ) { | ||||
| ) => { | ||||
| 	const promise = api(endpoint, data, token); | ||||
| 	promiseDialog(promise, onSuccess, onFailure ? onFailure : (e) => { | ||||
| 	promiseDialog(promise, null, (e) => { | ||||
| 		dialog({ | ||||
| 			type: 'error', | ||||
| 			text: e.message + '\n' + (e as any).id, | ||||
|  | @ -108,7 +110,7 @@ export function apiWithDialog( | |||
| 	}); | ||||
| 
 | ||||
| 	return promise; | ||||
| } | ||||
| }) as typeof api; | ||||
| 
 | ||||
| export function promiseDialog<T extends Promise<any>>( | ||||
| 	promise: T, | ||||
|  |  | |||
|  | @ -90,7 +90,7 @@ export default defineComponent({ | |||
| 			stats: null, | ||||
| 			serverInfo: null, | ||||
| 			connection: null, | ||||
| 			queueConnection: os.stream.useSharedConnection('queueStats'), | ||||
| 			queueConnection: os.stream.useChannel('queueStats'), | ||||
| 			memUsage: 0, | ||||
| 			chartCpuMem: null, | ||||
| 			chartNet: null, | ||||
|  | @ -121,7 +121,7 @@ export default defineComponent({ | |||
| 		os.api('admin/server-info', {}).then(res => { | ||||
| 			this.serverInfo = res; | ||||
| 
 | ||||
| 			this.connection = os.stream.useSharedConnection('serverStats'); | ||||
| 			this.connection = os.stream.useChannel('serverStats'); | ||||
| 			this.connection.on('stats', this.onStats); | ||||
| 			this.connection.on('statsLog', this.onStatsLog); | ||||
| 			this.connection.send('requestLog', { | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ export default defineComponent({ | |||
| 				title: this.$ts.jobQueue, | ||||
| 				icon: 'fas fa-clipboard-list', | ||||
| 			}, | ||||
| 			connection: os.stream.useSharedConnection('queueStats'), | ||||
| 			connection: os.stream.useChannel('queueStats'), | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -63,7 +63,7 @@ export default defineComponent({ | |||
| 	}, | ||||
| 
 | ||||
| 	mounted() { | ||||
| 		this.connection = os.stream.useSharedConnection('messagingIndex'); | ||||
| 		this.connection = os.stream.useChannel('messagingIndex'); | ||||
| 
 | ||||
| 		this.connection.on('message', this.onMessage); | ||||
| 		this.connection.on('read', this.onRead); | ||||
|  |  | |||
|  | @ -141,7 +141,7 @@ const Component = defineComponent({ | |||
| 				this.group = group; | ||||
| 			} | ||||
| 
 | ||||
| 			this.connection = os.stream.connectToChannel('messaging', { | ||||
| 			this.connection = os.stream.useChannel('messaging', { | ||||
| 				otherparty: this.user ? this.user.id : undefined, | ||||
| 				group: this.group ? this.group.id : undefined, | ||||
| 			}); | ||||
|  |  | |||
|  | @ -61,7 +61,7 @@ export default defineComponent({ | |||
| 				if (this.connection) { | ||||
| 					this.connection.dispose(); | ||||
| 				} | ||||
| 				this.connection = os.stream.connectToChannel('gamesReversiGame', { | ||||
| 				this.connection = os.stream.useChannel('gamesReversiGame', { | ||||
| 					gameId: this.game.id | ||||
| 				}); | ||||
| 				this.connection.on('started', this.onStarted); | ||||
|  |  | |||
|  | @ -92,7 +92,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	mounted() { | ||||
| 		if (this.$i) { | ||||
| 			this.connection = os.stream.useSharedConnection('gamesReversi'); | ||||
| 			this.connection = os.stream.useChannel('gamesReversi'); | ||||
| 
 | ||||
| 			this.connection.on('invited', this.onInvited); | ||||
| 
 | ||||
|  |  | |||
|  | @ -47,7 +47,7 @@ export function selectFile(src: any, label: string | null, multiple = false) { | |||
| 
 | ||||
| 				const marker = Math.random().toString(); // TODO: UUIDとか使う
 | ||||
| 
 | ||||
| 				const connection = os.stream.useSharedConnection('main'); | ||||
| 				const connection = os.stream.useChannel('main'); | ||||
| 				connection.on('urlUploadFinished', data => { | ||||
| 					if (data.marker === marker) { | ||||
| 						res(multiple ? [data.file] : data.file); | ||||
|  | @ -55,7 +55,7 @@ export function selectFile(src: any, label: string | null, multiple = false) { | |||
| 					} | ||||
| 				}); | ||||
| 
 | ||||
| 				os.api('drive/files/upload_from_url', { | ||||
| 				os.api('drive/files/upload-from-url', { | ||||
| 					url: url, | ||||
| 					marker | ||||
| 				}); | ||||
|  |  | |||
|  | @ -1,312 +0,0 @@ | |||
| import autobind from 'autobind-decorator'; | ||||
| import { EventEmitter } from 'eventemitter3'; | ||||
| import ReconnectingWebsocket from 'reconnecting-websocket'; | ||||
| import { markRaw } from 'vue'; | ||||
| import { debug, wsUrl } from '@client/config'; | ||||
| import { query as urlQuery } from '../../prelude/url'; | ||||
| 
 | ||||
| /** | ||||
|  * Misskey stream connection | ||||
|  */ | ||||
| export default class Stream extends EventEmitter { | ||||
| 	private stream: ReconnectingWebsocket; | ||||
| 	public state: 'initializing' | 'reconnecting' | 'connected' = 'initializing'; | ||||
| 	private sharedConnectionPools: Pool[] = []; | ||||
| 	private sharedConnections: SharedConnection[] = []; | ||||
| 	private nonSharedConnections: NonSharedConnection[] = []; | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public init(user): void { | ||||
| 		const query = urlQuery({ | ||||
| 			i: user?.token, | ||||
| 			_t: Date.now(), | ||||
| 		}); | ||||
| 
 | ||||
| 		this.stream = new ReconnectingWebsocket(`${wsUrl}?${query}`, '', { minReconnectionDelay: 1 }); // https://github.com/pladaria/reconnecting-websocket/issues/91
 | ||||
| 		this.stream.addEventListener('open', this.onOpen); | ||||
| 		this.stream.addEventListener('close', this.onClose); | ||||
| 		this.stream.addEventListener('message', this.onMessage); | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public useSharedConnection(channel: string, name?: string): SharedConnection { | ||||
| 		let pool = this.sharedConnectionPools.find(p => p.channel === channel); | ||||
| 
 | ||||
| 		if (pool == null) { | ||||
| 			pool = new Pool(this, channel); | ||||
| 			this.sharedConnectionPools.push(pool); | ||||
| 		} | ||||
| 
 | ||||
| 		const connection = markRaw(new SharedConnection(this, channel, pool, name)); | ||||
| 		this.sharedConnections.push(connection); | ||||
| 		return connection; | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public removeSharedConnection(connection: SharedConnection) { | ||||
| 		this.sharedConnections = this.sharedConnections.filter(c => c !== connection); | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public removeSharedConnectionPool(pool: Pool) { | ||||
| 		this.sharedConnectionPools = this.sharedConnectionPools.filter(p => p !== pool); | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public connectToChannel(channel: string, params?: any): NonSharedConnection { | ||||
| 		const connection = markRaw(new NonSharedConnection(this, channel, params)); | ||||
| 		this.nonSharedConnections.push(connection); | ||||
| 		return connection; | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public disconnectToChannel(connection: NonSharedConnection) { | ||||
| 		this.nonSharedConnections = this.nonSharedConnections.filter(c => c !== connection); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Callback of when open connection | ||||
| 	 */ | ||||
| 	@autobind | ||||
| 	private onOpen() { | ||||
| 		const isReconnect = this.state === 'reconnecting'; | ||||
| 
 | ||||
| 		this.state = 'connected'; | ||||
| 		this.emit('_connected_'); | ||||
| 
 | ||||
| 		// チャンネル再接続
 | ||||
| 		if (isReconnect) { | ||||
| 			for (const p of this.sharedConnectionPools) | ||||
| 				p.connect(); | ||||
| 			for (const c of this.nonSharedConnections) | ||||
| 				c.connect(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Callback of when close connection | ||||
| 	 */ | ||||
| 	@autobind | ||||
| 	private onClose() { | ||||
| 		if (this.state === 'connected') { | ||||
| 			this.state = 'reconnecting'; | ||||
| 			this.emit('_disconnected_'); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Callback of when received a message from connection | ||||
| 	 */ | ||||
| 	@autobind | ||||
| 	private onMessage(message) { | ||||
| 		const { type, body } = JSON.parse(message.data); | ||||
| 
 | ||||
| 		if (type === 'channel') { | ||||
| 			const id = body.id; | ||||
| 
 | ||||
| 			let connections: Connection[]; | ||||
| 
 | ||||
| 			connections = this.sharedConnections.filter(c => c.id === id); | ||||
| 
 | ||||
| 			if (connections.length === 0) { | ||||
| 				connections = [this.nonSharedConnections.find(c => c.id === id)]; | ||||
| 			} | ||||
| 
 | ||||
| 			for (const c of connections.filter(c => c != null)) { | ||||
| 				c.emit(body.type, Object.freeze(body.body)); | ||||
| 				if (debug) c.inCount++; | ||||
| 			} | ||||
| 		} else { | ||||
| 			this.emit(type, Object.freeze(body)); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Send a message to connection | ||||
| 	 */ | ||||
| 	@autobind | ||||
| 	public send(typeOrPayload, payload?) { | ||||
| 		const data = payload === undefined ? typeOrPayload : { | ||||
| 			type: typeOrPayload, | ||||
| 			body: payload | ||||
| 		}; | ||||
| 
 | ||||
| 		this.stream.send(JSON.stringify(data)); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Close this connection | ||||
| 	 */ | ||||
| 	@autobind | ||||
| 	public close() { | ||||
| 		this.stream.removeEventListener('open', this.onOpen); | ||||
| 		this.stream.removeEventListener('message', this.onMessage); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| let idCounter = 0; | ||||
| 
 | ||||
| class Pool { | ||||
| 	public channel: string; | ||||
| 	public id: string; | ||||
| 	protected stream: Stream; | ||||
| 	public users = 0; | ||||
| 	private disposeTimerId: any; | ||||
| 	private isConnected = false; | ||||
| 
 | ||||
| 	constructor(stream: Stream, channel: string) { | ||||
| 		this.channel = channel; | ||||
| 		this.stream = stream; | ||||
| 
 | ||||
| 		this.id = (++idCounter).toString(); | ||||
| 
 | ||||
| 		this.stream.on('_disconnected_', this.onStreamDisconnected); | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	private onStreamDisconnected() { | ||||
| 		this.isConnected = false; | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public inc() { | ||||
| 		if (this.users === 0 && !this.isConnected) { | ||||
| 			this.connect(); | ||||
| 		} | ||||
| 
 | ||||
| 		this.users++; | ||||
| 
 | ||||
| 		// タイマー解除
 | ||||
| 		if (this.disposeTimerId) { | ||||
| 			clearTimeout(this.disposeTimerId); | ||||
| 			this.disposeTimerId = null; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public dec() { | ||||
| 		this.users--; | ||||
| 
 | ||||
| 		// そのコネクションの利用者が誰もいなくなったら
 | ||||
| 		if (this.users === 0) { | ||||
| 			// また直ぐに再利用される可能性があるので、一定時間待ち、
 | ||||
| 			// 新たな利用者が現れなければコネクションを切断する
 | ||||
| 			this.disposeTimerId = setTimeout(() => { | ||||
| 				this.disconnect(); | ||||
| 			}, 3000); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public connect() { | ||||
| 		if (this.isConnected) return; | ||||
| 		this.isConnected = true; | ||||
| 		this.stream.send('connect', { | ||||
| 			channel: this.channel, | ||||
| 			id: this.id | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	private disconnect() { | ||||
| 		this.stream.off('_disconnected_', this.onStreamDisconnected); | ||||
| 		this.stream.send('disconnect', { id: this.id }); | ||||
| 		this.stream.removeSharedConnectionPool(this); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| abstract class Connection extends EventEmitter { | ||||
| 	public channel: string; | ||||
| 	protected stream: Stream; | ||||
| 	public abstract id: string; | ||||
| 
 | ||||
| 	public name?: string; // for debug
 | ||||
| 	public inCount: number = 0; // for debug
 | ||||
| 	public outCount: number = 0; // for debug
 | ||||
| 
 | ||||
| 	constructor(stream: Stream, channel: string, name?: string) { | ||||
| 		super(); | ||||
| 
 | ||||
| 		this.stream = stream; | ||||
| 		this.channel = channel; | ||||
| 		this.name = name; | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public send(id: string, typeOrPayload, payload?) { | ||||
| 		const type = payload === undefined ? typeOrPayload.type : typeOrPayload; | ||||
| 		const body = payload === undefined ? typeOrPayload.body : payload; | ||||
| 
 | ||||
| 		this.stream.send('ch', { | ||||
| 			id: id, | ||||
| 			type: type, | ||||
| 			body: body | ||||
| 		}); | ||||
| 
 | ||||
| 		if (debug) this.outCount++; | ||||
| 	} | ||||
| 
 | ||||
| 	public abstract dispose(): void; | ||||
| } | ||||
| 
 | ||||
| class SharedConnection extends Connection { | ||||
| 	private pool: Pool; | ||||
| 
 | ||||
| 	public get id(): string { | ||||
| 		return this.pool.id; | ||||
| 	} | ||||
| 
 | ||||
| 	constructor(stream: Stream, channel: string, pool: Pool, name?: string) { | ||||
| 		super(stream, channel, name); | ||||
| 
 | ||||
| 		this.pool = pool; | ||||
| 		this.pool.inc(); | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public send(typeOrPayload, payload?) { | ||||
| 		super.send(this.pool.id, typeOrPayload, payload); | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public dispose() { | ||||
| 		this.pool.dec(); | ||||
| 		this.removeAllListeners(); | ||||
| 		this.stream.removeSharedConnection(this); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| class NonSharedConnection extends Connection { | ||||
| 	public id: string; | ||||
| 	protected params: any; | ||||
| 
 | ||||
| 	constructor(stream: Stream, channel: string, params?: any) { | ||||
| 		super(stream, channel); | ||||
| 
 | ||||
| 		this.params = params; | ||||
| 		this.id = (++idCounter).toString(); | ||||
| 
 | ||||
| 		this.connect(); | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public connect() { | ||||
| 		this.stream.send('connect', { | ||||
| 			channel: this.channel, | ||||
| 			id: this.id, | ||||
| 			params: this.params | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public send(typeOrPayload, payload?) { | ||||
| 		super.send(this.id, typeOrPayload, payload); | ||||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public dispose() { | ||||
| 		this.removeAllListeners(); | ||||
| 		this.stream.send('disconnect', { id: this.id }); | ||||
| 		this.stream.disconnectToChannel(this); | ||||
| 	} | ||||
| } | ||||
|  | @ -43,7 +43,7 @@ export default defineComponent({ | |||
| 		}; | ||||
| 
 | ||||
| 		if ($i) { | ||||
| 			const connection = stream.useSharedConnection('main', 'UI'); | ||||
| 			const connection = stream.useChannel('main', 'UI'); | ||||
| 			connection.on('notification', onNotification); | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -121,33 +121,33 @@ export default defineComponent({ | |||
| 			this.query = { | ||||
| 				antennaId: this.antenna | ||||
| 			}; | ||||
| 			this.connection = os.stream.connectToChannel('antenna', { | ||||
| 			this.connection = os.stream.useChannel('antenna', { | ||||
| 				antennaId: this.antenna | ||||
| 			}); | ||||
| 			this.connection.on('note', prepend); | ||||
| 		} else if (this.src == 'home') { | ||||
| 			endpoint = 'notes/timeline'; | ||||
| 			this.connection = os.stream.useSharedConnection('homeTimeline'); | ||||
| 			this.connection = os.stream.useChannel('homeTimeline'); | ||||
| 			this.connection.on('note', prepend); | ||||
| 
 | ||||
| 			this.connection2 = os.stream.useSharedConnection('main'); | ||||
| 			this.connection2 = os.stream.useChannel('main'); | ||||
| 			this.connection2.on('follow', onChangeFollowing); | ||||
| 			this.connection2.on('unfollow', onChangeFollowing); | ||||
| 		} else if (this.src == 'local') { | ||||
| 			endpoint = 'notes/local-timeline'; | ||||
| 			this.connection = os.stream.useSharedConnection('localTimeline'); | ||||
| 			this.connection = os.stream.useChannel('localTimeline'); | ||||
| 			this.connection.on('note', prepend); | ||||
| 		} else if (this.src == 'social') { | ||||
| 			endpoint = 'notes/hybrid-timeline'; | ||||
| 			this.connection = os.stream.useSharedConnection('hybridTimeline'); | ||||
| 			this.connection = os.stream.useChannel('hybridTimeline'); | ||||
| 			this.connection.on('note', prepend); | ||||
| 		} else if (this.src == 'global') { | ||||
| 			endpoint = 'notes/global-timeline'; | ||||
| 			this.connection = os.stream.useSharedConnection('globalTimeline'); | ||||
| 			this.connection = os.stream.useChannel('globalTimeline'); | ||||
| 			this.connection.on('note', prepend); | ||||
| 		} else if (this.src == 'mentions') { | ||||
| 			endpoint = 'notes/mentions'; | ||||
| 			this.connection = os.stream.useSharedConnection('main'); | ||||
| 			this.connection = os.stream.useChannel('main'); | ||||
| 			this.connection.on('mention', prepend); | ||||
| 		} else if (this.src == 'directs') { | ||||
| 			endpoint = 'notes/mentions'; | ||||
|  | @ -159,14 +159,14 @@ export default defineComponent({ | |||
| 					prepend(note); | ||||
| 				} | ||||
| 			}; | ||||
| 			this.connection = os.stream.useSharedConnection('main'); | ||||
| 			this.connection = os.stream.useChannel('main'); | ||||
| 			this.connection.on('mention', onNote); | ||||
| 		} else if (this.src == 'list') { | ||||
| 			endpoint = 'notes/user-list-timeline'; | ||||
| 			this.query = { | ||||
| 				listId: this.list | ||||
| 			}; | ||||
| 			this.connection = os.stream.connectToChannel('userList', { | ||||
| 			this.connection = os.stream.useChannel('userList', { | ||||
| 				listId: this.list | ||||
| 			}); | ||||
| 			this.connection.on('note', prepend); | ||||
|  | @ -178,7 +178,7 @@ export default defineComponent({ | |||
| 			this.query = { | ||||
| 				channelId: this.channel | ||||
| 			}; | ||||
| 			this.connection = os.stream.connectToChannel('channel', { | ||||
| 			this.connection = os.stream.useChannel('channel', { | ||||
| 				channelId: this.channel | ||||
| 			}); | ||||
| 			this.connection.on('note', prepend); | ||||
|  |  | |||
|  | @ -65,7 +65,7 @@ export default defineComponent({ | |||
| 	extends: widget, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			connection: os.stream.useSharedConnection('queueStats'), | ||||
| 			connection: os.stream.useChannel('queueStats'), | ||||
| 			inbox: { | ||||
| 				activeSincePrevTick: 0, | ||||
| 				active: 0, | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ export default defineComponent({ | |||
| 		}; | ||||
| 	}, | ||||
| 	mounted() { | ||||
| 		this.connection = os.stream.useSharedConnection('main'); | ||||
| 		this.connection = os.stream.useChannel('main'); | ||||
| 
 | ||||
| 		this.connection.on('driveFileCreated', this.onDriveFileCreated); | ||||
| 
 | ||||
|  |  | |||
|  | @ -63,7 +63,7 @@ export default defineComponent({ | |||
| 		os.api('server-info', {}).then(res => { | ||||
| 			this.meta = res; | ||||
| 		}); | ||||
| 		this.connection = os.stream.useSharedConnection('serverStats'); | ||||
| 		this.connection = os.stream.useChannel('serverStats'); | ||||
| 	}, | ||||
| 	unmounted() { | ||||
| 		this.connection.dispose(); | ||||
|  |  | |||
							
								
								
									
										18
									
								
								yarn.lock
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								yarn.lock
									
										
									
									
									
								
							|  | @ -1290,7 +1290,7 @@ | |||
|     "@vue/compiler-dom" "3.0.11" | ||||
|     "@vue/shared" "3.0.11" | ||||
| 
 | ||||
| "@vue/reactivity@3.0.11": | ||||
| "@vue/reactivity@3.0.11", "@vue/reactivity@^3.0.11": | ||||
|   version "3.0.11" | ||||
|   resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.0.11.tgz#07b588349fd05626b17f3500cbef7d4bdb4dbd0b" | ||||
|   integrity sha512-SKM3YKxtXHBPMf7yufXeBhCZ4XZDKP9/iXeQSC8bBO3ivBuzAi4aZi0bNoeE2IF2iGfP/AHEt1OU4ARj4ao/Xw== | ||||
|  | @ -1899,7 +1899,7 @@ atob@^2.1.2: | |||
|   resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" | ||||
|   integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== | ||||
| 
 | ||||
| autobind-decorator@2.4.0: | ||||
| autobind-decorator@2.4.0, autobind-decorator@^2.4.0: | ||||
|   version "2.4.0" | ||||
|   resolved "https://registry.yarnpkg.com/autobind-decorator/-/autobind-decorator-2.4.0.tgz#ea9e1c98708cf3b5b356f7cf9f10f265ff18239c" | ||||
|   integrity sha512-OGYhWUO72V6DafbF8PM8rm3EPbfuyMZcJhtm5/n26IDwO18pohE4eNazLoCGhPiXOCD0gEGmrbU3849QvM8bbw== | ||||
|  | @ -4203,7 +4203,7 @@ event-target-shim@^5.0.0: | |||
|   resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" | ||||
|   integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== | ||||
| 
 | ||||
| eventemitter3@4.0.7: | ||||
| eventemitter3@4.0.7, eventemitter3@^4.0.7: | ||||
|   version "4.0.7" | ||||
|   resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" | ||||
|   integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== | ||||
|  | @ -6977,6 +6977,16 @@ minizlib@^2.0.0, minizlib@^2.1.1: | |||
|     minipass "^3.0.0" | ||||
|     yallist "^4.0.0" | ||||
| 
 | ||||
| misskey-js@0.0.2: | ||||
|   version "0.0.2" | ||||
|   resolved "https://registry.yarnpkg.com/misskey-js/-/misskey-js-0.0.2.tgz#233d62e5a326a00dd72f36d63436e6584c8076f2" | ||||
|   integrity sha512-gsq3E9lUepNapK4i/3mmqjobQV6gYlgO1O1rQt401ot3LCYlcaLhlUrwBOFtI+ALMGKgwRgkLlDQhcWgAfHHuQ== | ||||
|   dependencies: | ||||
|     "@vue/reactivity" "^3.0.11" | ||||
|     autobind-decorator "^2.4.0" | ||||
|     eventemitter3 "^4.0.7" | ||||
|     reconnecting-websocket "^4.4.0" | ||||
| 
 | ||||
| mixin-deep@^1.2.0: | ||||
|   version "1.3.2" | ||||
|   resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" | ||||
|  | @ -9072,7 +9082,7 @@ rechoir@^0.7.0: | |||
|   dependencies: | ||||
|     resolve "^1.9.0" | ||||
| 
 | ||||
| reconnecting-websocket@4.4.0: | ||||
| reconnecting-websocket@4.4.0, reconnecting-websocket@^4.4.0: | ||||
|   version "4.4.0" | ||||
|   resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783" | ||||
|   integrity sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng== | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue