@netless/forge-slide 0.1.1-alpha.1 → 0.1.1-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,110 @@
1
+ import { Slide } from '@netless/slide';
2
+ import { delay } from './utils';
3
+
4
+ export interface PoolItem {
5
+ key: string;
6
+ slide: Slide;
7
+ }
8
+
9
+ export class SlidePool {
10
+ private pool: PoolItem[] = [];
11
+ private maxActiveSize: number = 2;
12
+ private renderingQueue: string[] = [];
13
+ private renderingQueueCallback: (() => void) | undefined;
14
+
15
+ constructor(maxActiveSize?: number) {
16
+ if (maxActiveSize) {
17
+ this.setMaxActiveSize(maxActiveSize);
18
+ }
19
+ }
20
+
21
+ private async freeze(poolItem: PoolItem): Promise<boolean> {
22
+ return new Promise<boolean>((resolve, _reject) => {
23
+ if (!poolItem.slide.view) {
24
+ resolve(false);
25
+ } else {
26
+ poolItem.slide.frozen(() => {
27
+ resolve(true);
28
+ });
29
+ }
30
+ });
31
+ }
32
+
33
+ private async unfreeze(poolItem: PoolItem): Promise<boolean> {
34
+ return new Promise<boolean>((resolve, _reject) => {
35
+ if (poolItem.slide.view) {
36
+ resolve(false);
37
+ } else {
38
+ poolItem.slide.release(() => {
39
+ resolve(true);
40
+ });
41
+ }
42
+ });
43
+ }
44
+
45
+ private async checkPool() {
46
+ for (let i = 0; i < this.pool.length; i ++) {
47
+ const poolItem = this.pool[i];
48
+ if (i < this.maxActiveSize) {
49
+ await this.unfreeze(poolItem);
50
+ } else {
51
+ await this.freeze(poolItem);
52
+ }
53
+ }
54
+ }
55
+
56
+ onRenderEnd(appId: string, isFocus: boolean) {
57
+ const index = this.renderingQueue.findIndex(item => item === appId);
58
+ if (index > -1) {
59
+ this.renderingQueue.splice(index, 1);
60
+ }
61
+ if (isFocus) {
62
+ this.renderingQueueCallback = () => {
63
+ const poolItem = this.pool.find(item => item.key === appId);
64
+ if (poolItem) {
65
+ this.active(appId, poolItem.slide);
66
+ }
67
+ };
68
+ }
69
+ if (this.renderingQueue.length === 0 && this.renderingQueueCallback) {
70
+ this.renderingQueueCallback();
71
+ }
72
+ }
73
+
74
+ setMaxActiveSize(maxActiveSize: number) {
75
+ this.maxActiveSize = maxActiveSize > 8 ? 8 : maxActiveSize;
76
+ if (maxActiveSize > 8) {
77
+ console.warn('maxActiveSize should not be greater than 8');
78
+ }
79
+ }
80
+
81
+ async waitUntilReady(appId: string) {
82
+ if (this.renderingQueue.length < this.maxActiveSize) {
83
+ this.renderingQueue.push(appId);
84
+ return;
85
+ } else {
86
+ await delay(200);
87
+ await this.waitUntilReady(appId);
88
+ }
89
+ }
90
+
91
+ async active(key: string, slide: Slide) {
92
+ const index = this.pool.findIndex(item => item.key === key);
93
+ if (index < 0) {
94
+ this.pool.unshift({ key, slide });
95
+ } else {
96
+ this.pool.splice(index, 1);
97
+ this.pool.unshift({ key, slide });
98
+ }
99
+ await this.checkPool();
100
+ }
101
+
102
+ remove(key: string) {
103
+ const index = this.pool.findIndex(item => item.key === key);
104
+ if (index >= 0) {
105
+ this.pool.splice(index, 1);
106
+ }
107
+ }
108
+ }
109
+
110
+ export const slidePool = new SlidePool();
package/src/icons.ts CHANGED
@@ -5,7 +5,7 @@ const prevPage = (color: string) => `<svg xmlns="http://www.w3.org/2000/svg" wid
5
5
  <path d="M14.375 4V7H15.625V4H14.375ZM16 8.625H19V7.375H16V8.625ZM14.375 7C14.375 7.89746 15.1025 8.625 16 8.625V7.375C15.7929 7.375 15.625 7.20711 15.625 7H14.375Z" fill="${color}"/>
6
6
  <path d="M13 16H5" stroke="${color}" stroke-width="1.25" stroke-linejoin="round"/>
7
7
  <path d="M9 12L7 14L5 16L7 18L9 20" stroke="${color}" stroke-width="1.25" stroke-linejoin="round"/>
8
- </svg>`
8
+ </svg>`;
9
9
 
10
10
  const nextPage = (color: string) => `
11
11
  <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none">
@@ -14,13 +14,13 @@ const nextPage = (color: string) => `
14
14
  <path d="M14.375 4V7H15.625V4H14.375ZM16 8.625H19V7.375H16V8.625ZM14.375 7C14.375 7.89746 15.1025 8.625 16 8.625V7.375C15.7929 7.375 15.625 7.20711 15.625 7H14.375Z" fill="${color}"/>
15
15
  <path d="M11 16H19" stroke="${color}" stroke-width="1.25" stroke-linejoin="round"/>
16
16
  <path d="M15 12L17 14L19 16L17 18L15 20" stroke="${color}" stroke-width="1.25" stroke-linejoin="round"/>
17
- </svg>`
17
+ </svg>`;
18
18
  const prevStep = (color: string) => `<svg style="width:100%;height:100%;padding:2px;box-sizing:border-box;" viewBox="0 0 12.3926 16.9629"><g><rect height="16.9629" opacity="0" width="12.3926" x="0" y="0"/><path d="M0 8.47656C0 8.7207 0.0878906 8.93555 0.273438 9.12109L8.01758 16.6895C8.18359 16.8652 8.39844 16.9531 8.65234 16.9531C9.16016 16.9531 9.55078 16.5723 9.55078 16.0645C9.55078 15.8105 9.44336 15.5957 9.28711 15.4297L2.17773 8.47656L9.28711 1.52344C9.44336 1.35742 9.55078 1.13281 9.55078 0.888672C9.55078 0.380859 9.16016 0 8.65234 0C8.39844 0 8.18359 0.0878906 8.01758 0.253906L0.273438 7.83203C0.0878906 8.00781 0 8.23242 0 8.47656Z" fill="${color}"/></g></svg>`;
19
19
  const nextStep = (color: string) => `<svg style="width:100%;height:100%;padding:2px;box-sizing:border-box;" viewBox="0 0 11.6895 16.9629"><g><rect height="16.9629" opacity="0" width="11.6895" x="0" y="0"/><path d="M11.6895 8.47656C11.6895 8.23242 11.5918 8.00781 11.4062 7.83203L3.67188 0.253906C3.49609 0.0878906 3.28125 0 3.02734 0C2.5293 0 2.13867 0.380859 2.13867 0.888672C2.13867 1.13281 2.23633 1.35742 2.39258 1.52344L9.50195 8.47656L2.39258 15.4297C2.23633 15.5957 2.13867 15.8105 2.13867 16.0645C2.13867 16.5723 2.5293 16.9531 3.02734 16.9531C3.28125 16.9531 3.49609 16.8652 3.67188 16.6895L11.4062 9.12109C11.5918 8.93555 11.6895 8.7207 11.6895 8.47656Z" fill="${color}"/></g></svg>`;
20
20
  const sideBar = (color: string) => `<svg style="width:100%;height:100%;padding:2px;box-sizing:border-box;" viewBox="0 0 23.3887 17.998"><g><rect height="17.998" opacity="0" width="23.3887" x="0" y="0"/><path d="M3.06641 17.998L19.9609 17.998C22.0117 17.998 23.0273 16.9824 23.0273 14.9707L23.0273 3.04688C23.0273 1.03516 22.0117 0.0195312 19.9609 0.0195312L3.06641 0.0195312C1.02539 0.0195312 0 1.02539 0 3.04688L0 14.9707C0 16.9922 1.02539 17.998 3.06641 17.998ZM3.08594 16.4258C2.10938 16.4258 1.57227 15.9082 1.57227 14.8926L1.57227 3.125C1.57227 2.10938 2.10938 1.5918 3.08594 1.5918L19.9414 1.5918C20.9082 1.5918 21.4551 2.10938 21.4551 3.125L21.4551 14.8926C21.4551 15.9082 20.9082 16.4258 19.9414 16.4258ZM7.44141 16.7285L8.97461 16.7285L8.97461 1.29883L7.44141 1.29883ZM5.56641 5.21484C5.85938 5.21484 6.12305 4.95117 6.12305 4.66797C6.12305 4.375 5.85938 4.12109 5.56641 4.12109L3.4668 4.12109C3.17383 4.12109 2.91992 4.375 2.91992 4.66797C2.91992 4.95117 3.17383 5.21484 3.4668 5.21484ZM5.56641 7.74414C5.85938 7.74414 6.12305 7.48047 6.12305 7.1875C6.12305 6.89453 5.85938 6.65039 5.56641 6.65039L3.4668 6.65039C3.17383 6.65039 2.91992 6.89453 2.91992 7.1875C2.91992 7.48047 3.17383 7.74414 3.4668 7.74414ZM5.56641 10.2637C5.85938 10.2637 6.12305 10.0195 6.12305 9.72656C6.12305 9.43359 5.85938 9.17969 5.56641 9.17969L3.4668 9.17969C3.17383 9.17969 2.91992 9.43359 2.91992 9.72656C2.91992 10.0195 3.17383 10.2637 3.4668 10.2637Z" fill="${color}"/></g></svg>`;
21
21
 
22
22
  export const Icons = {
23
- prevPage, nextPage,
24
- prevStep, nextStep,
25
- sideBar,
23
+ prevPage, nextPage,
24
+ prevStep, nextStep,
25
+ sideBar,
26
26
  };
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { SlideApplication } from "./SlideApplication";
2
- export { SlideForge } from "./Slide";
3
- export { ForgeSlidePermissionFlag } from "./ForgeSlidePermession";
1
+ export { SlideApplication } from './SlideApplication';
2
+ export { SlideForge } from './Slide';
3
+ export { ForgeSlidePermissionFlag } from './ForgeSlidePermession';
4
4
 
5
- export type { SlideApplicationOption } from "./SlideApplication";
5
+ export type { SlideApplicationOption } from './SlideApplication';
package/src/utils.ts CHANGED
@@ -1,62 +1,62 @@
1
- export function deepEqual(a: any, b: any, excludeKeys: string[] = ["time"]) {
2
- // 严格相等检查
3
- if (a === b) return true;
1
+ export function deepEqual(a: any, b: any, excludeKeys: string[] = ['time']) {
2
+ // 严格相等检查
3
+ if (a === b) return true;
4
4
 
5
- // 非对象类型检查
6
- if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) return false;
5
+ // 非对象类型检查
6
+ if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) return false;
7
7
 
8
- // 构造函数检查
9
- if (a.constructor !== b.constructor) return false;
8
+ // 构造函数检查
9
+ if (a.constructor !== b.constructor) return false;
10
10
 
11
- // 特殊对象处理
12
- if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
13
- if (a instanceof RegExp && b instanceof RegExp) return a.toString() === b.toString();
11
+ // 特殊对象处理
12
+ if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
13
+ if (a instanceof RegExp && b instanceof RegExp) return a.toString() === b.toString();
14
14
 
15
- // 获取并过滤属性键(核心修改点)
16
- const filterKeys = (obj: any) =>
17
- Reflect.ownKeys(obj).filter(k => typeof k === "string" ? !excludeKeys.includes(k) : false);
15
+ // 获取并过滤属性键(核心修改点)
16
+ const filterKeys = (obj: any) =>
17
+ Reflect.ownKeys(obj).filter(k => typeof k === 'string' ? !excludeKeys.includes(k) : false);
18
18
 
19
- const keysA = filterKeys(a);
20
- const keysB = filterKeys(b);
19
+ const keysA = filterKeys(a);
20
+ const keysB = filterKeys(b);
21
21
 
22
- // 属性数量检查
23
- if (keysA.length !== keysB.length) return false;
22
+ // 属性数量检查
23
+ if (keysA.length !== keysB.length) return false;
24
24
 
25
- // 分类型处理属性名
26
- const processKeys = (keys: (string | symbol)[]) => ({
27
- strings: keys.filter(k => typeof k === 'string').sort(),
28
- symbols: keys.filter(k => typeof k === 'symbol')
29
- });
25
+ // 分类型处理属性名
26
+ const processKeys = (keys: (string | symbol)[]) => ({
27
+ strings: keys.filter(k => typeof k === 'string').sort(),
28
+ symbols: keys.filter(k => typeof k === 'symbol'),
29
+ });
30
30
 
31
- const { strings: strA, symbols: symA } = processKeys(keysA);
32
- const { strings: strB, symbols: symB } = processKeys(keysB);
31
+ const { strings: strA, symbols: symA } = processKeys(keysA);
32
+ const { strings: strB, symbols: symB } = processKeys(keysB);
33
33
 
34
- // 字符串键顺序敏感比较
35
- if (!arrayEqual(strA, strB)) return false;
34
+ // 字符串键顺序敏感比较
35
+ if (!arrayEqual(strA, strB)) return false;
36
36
 
37
- // Symbol键存在性检查
38
- if (symA.length !== symB.length) return false;
39
- const symSet = new Set(symB);
40
- if (!symA.every(k => symSet.has(k))) return false;
37
+ // Symbol键存在性检查
38
+ if (symA.length !== symB.length) return false;
39
+ const symSet = new Set(symB);
40
+ if (!symA.every(k => symSet.has(k))) return false;
41
41
 
42
- // 合并所有需比较的键
43
- const allKeys = [...strA, ...symA];
42
+ // 合并所有需比较的键
43
+ const allKeys = [...strA, ...symA];
44
44
 
45
- // 递归比较属性值(传递排除键)
46
- for (const key of allKeys) {
47
- if (!deepEqual(a[key], b[key], excludeKeys)) return false;
48
- }
45
+ // 递归比较属性值(传递排除键)
46
+ for (const key of allKeys) {
47
+ if (!deepEqual(a[key], b[key], excludeKeys)) return false;
48
+ }
49
49
 
50
- return true;
50
+ return true;
51
51
  }
52
52
 
53
53
  // 辅助函数:比较数组是否严格相等
54
54
  function arrayEqual(arr1: any[], arr2: any[]) {
55
- if (arr1.length !== arr2.length) return false;
56
- for (let i = 0; i < arr1.length; i++) {
57
- if (arr1[i] !== arr2[i]) return false;
58
- }
59
- return true;
55
+ if (arr1.length !== arr2.length) return false;
56
+ for (let i = 0; i < arr1.length; i++) {
57
+ if (arr1[i] !== arr2[i]) return false;
58
+ }
59
+ return true;
60
60
  }
61
61
 
62
62
  export async function delay(time: number): Promise<void> { return new Promise(resolve => setTimeout(resolve, time)); }
@@ -1 +0,0 @@
1
- {"version":3,"file":"FoorerView.d.ts","sourceRoot":"","sources":["../src/FoorerView.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAGzC,UAAU,gBAAgB;IACtB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC7B;AAID,qBAAa,UAAW,SAAQ,YAAY,CAAC,gBAAgB,CAAC;IAE1D,SAAgB,IAAI,EAAE,cAAc,CAAC;IAErC,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,QAAQ,CAAiB;IAEjC,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,QAAQ,CAAiB;IAEjC,OAAO,CAAC,aAAa,CAAiB;;IAyC/B,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAUpC,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAU3C,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,UAAU;CAkBrB"}
package/src/FoorerView.ts DELETED
@@ -1,109 +0,0 @@
1
- import EventEmitter from "eventemitter3";
2
- import { Icons } from "./icons";
3
-
4
- interface FooterViewEvents {
5
- prevPage: () => void;
6
- nextPage: () => void;
7
- prevStep: () => void;
8
- nextStep: () => void;
9
- sideBarToggle: () => void;
10
- }
11
-
12
- const EM_COLOR = "#8C8C8C";
13
-
14
- export class FooterView extends EventEmitter<FooterViewEvents> {
15
-
16
- public readonly root: HTMLDivElement;
17
-
18
- private prevStep: HTMLDivElement;
19
- private nextStep: HTMLDivElement;
20
-
21
- private prevPage: HTMLDivElement;
22
- private nextPage: HTMLDivElement;
23
-
24
- private sideBarToggle: HTMLDivElement;
25
-
26
- public constructor() {
27
- super();
28
- this.root = document.createElement("div");
29
- this.root.style.height = "24px";
30
- this.root.style.zIndex = "6";
31
- this.root.style.display = "flex";
32
- this.root.style.alignItems = "center";
33
- this.root.style.justifyContent = "center";
34
- this.root.style.backgroundColor = "#fff";
35
-
36
- this.prevStep = this.createIcon(Icons.prevStep(EM_COLOR), () => {
37
- this.emit("prevStep");
38
- });
39
-
40
- this.nextStep = this.createIcon(Icons.nextStep(EM_COLOR), () => {
41
- this.emit("nextStep");
42
- });
43
-
44
- this.prevPage = this.createIcon(Icons.prevPage(EM_COLOR), () => {
45
- this.emit("prevPage");
46
- });
47
-
48
- this.nextPage = this.createIcon(Icons.nextPage(EM_COLOR), () => {
49
- this.emit("nextPage");
50
- });
51
-
52
- this.sideBarToggle = this.createIcon(Icons.sideBar(EM_COLOR), () => {
53
- this.emit("sideBarToggle")
54
- });
55
-
56
- this.root.appendChild(this.sideBarToggle);
57
- this.root.appendChild(this.createSpacer());
58
- this.root.appendChild(this.prevPage);
59
- this.root.appendChild(this.prevStep);
60
- this.root.appendChild(this.nextStep);
61
- this.root.appendChild(this.nextPage);
62
- this.root.appendChild(this.createSpacer());
63
- }
64
-
65
- public prevPageState(enable: boolean): void {
66
- if (enable) {
67
- this.prevPage.style.pointerEvents = "all";
68
- this.prevPage.style.opacity = "1";
69
- } else {
70
- this.prevPage.style.pointerEvents = "none";
71
- this.prevPage.style.opacity = "0.5";
72
- }
73
- }
74
-
75
- public nextPageState(enable: boolean): void {
76
- if (enable) {
77
- this.nextPage.style.pointerEvents = "all";
78
- this.nextPage.style.opacity = "1";
79
- } else {
80
- this.nextPage.style.pointerEvents = "none";
81
- this.nextPage.style.opacity = "0.5";
82
- }
83
- }
84
-
85
- private createSpacer(): HTMLDivElement {
86
- const div = document.createElement("div");
87
- div.style.flex = "1 1 auto";
88
- return div;
89
- }
90
-
91
- private createIcon(svgContent: string, action: () => void): HTMLDivElement {
92
- const icon = document.createElement("div");
93
- icon.style.width = "18px";
94
- icon.style.height = "18px";
95
- icon.style.borderRadius = "2px";
96
- icon.style.margin = "6px";
97
- icon.innerHTML = svgContent;
98
- icon.addEventListener("click", () => {
99
- action();
100
- });
101
- icon.addEventListener("mouseover", () => {
102
- icon.style.backgroundColor = "#f0f0f0";
103
- });
104
- icon.addEventListener("mouseout", () => {
105
- icon.style.backgroundColor = "transparent";
106
- });
107
- return icon;
108
- }
109
- }