import { Slide } from '@netless/slide'; import { delay } from './utils'; export interface PoolItem { key: string; slide: Slide; } export class SlidePool { private pool: PoolItem[] = []; private maxActiveSize: number = 2; private renderingQueue: string[] = []; private renderingQueueCallback: (() => void) | undefined; constructor(maxActiveSize?: number) { if (maxActiveSize) { this.setMaxActiveSize(maxActiveSize); } } private async freeze(poolItem: PoolItem): Promise { return new Promise((resolve, _reject) => { if (!poolItem.slide.view) { resolve(false); } else { poolItem.slide.frozen(() => { resolve(true); }); } }); } private async unfreeze(poolItem: PoolItem): Promise { return new Promise((resolve, _reject) => { if (poolItem.slide.view) { resolve(false); } else { poolItem.slide.release(() => { resolve(true); }); } }); } private async checkPool() { for (let i = 0; i < this.pool.length; i ++) { const poolItem = this.pool[i]; if (i < this.maxActiveSize) { await this.unfreeze(poolItem); } else { await this.freeze(poolItem); } } } onRenderEnd(appId: string, isFocus: boolean) { const index = this.renderingQueue.findIndex(item => item === appId); if (index > -1) { this.renderingQueue.splice(index, 1); } if (isFocus) { this.renderingQueueCallback = () => { const poolItem = this.pool.find(item => item.key === appId); if (poolItem) { this.active(appId, poolItem.slide); } }; } if (this.renderingQueue.length === 0 && this.renderingQueueCallback) { this.renderingQueueCallback(); } } setMaxActiveSize(maxActiveSize: number) { this.maxActiveSize = maxActiveSize > 8 ? 8 : maxActiveSize; if (maxActiveSize > 8) { console.warn('maxActiveSize should not be greater than 8'); } } async waitUntilReady(appId: string) { if (this.renderingQueue.length < this.maxActiveSize) { this.renderingQueue.push(appId); return; } else { await delay(200); await this.waitUntilReady(appId); } } async active(key: string, slide: Slide) { const index = this.pool.findIndex(item => item.key === key); if (index < 0) { this.pool.unshift({ key, slide }); } else { this.pool.splice(index, 1); this.pool.unshift({ key, slide }); } await this.checkPool(); } remove(key: string) { const index = this.pool.findIndex(item => item.key === key); if (index >= 0) { this.pool.splice(index, 1); } } } export const slidePool = new SlidePool();