hzengine-core 0.1.2-dev

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.
Files changed (103) hide show
  1. package/dist/async/index.js +162 -0
  2. package/dist/async/zeppos_timer.js +58 -0
  3. package/dist/audio/index.js +260 -0
  4. package/dist/config/index.js +57 -0
  5. package/dist/debug/index.js +8 -0
  6. package/dist/index.js +103 -0
  7. package/dist/platform/index.js +1 -0
  8. package/dist/plugins/basic_command/$.js +8 -0
  9. package/dist/plugins/basic_command/audio.js +40 -0
  10. package/dist/plugins/basic_command/basic.js +124 -0
  11. package/dist/plugins/basic_command/character.js +112 -0
  12. package/dist/plugins/basic_command/conditional.js +260 -0
  13. package/dist/plugins/basic_command/config.js +22 -0
  14. package/dist/plugins/basic_command/decorator.js +24 -0
  15. package/dist/plugins/basic_command/eval.js +67 -0
  16. package/dist/plugins/basic_command/img.js +249 -0
  17. package/dist/plugins/basic_command/index.js +22 -0
  18. package/dist/plugins/basic_command/menu.js +140 -0
  19. package/dist/plugins/global_gesture/index.js +25 -0
  20. package/dist/plugins/transform/animation.js +440 -0
  21. package/dist/plugins/transform/commands.js +38 -0
  22. package/dist/plugins/transform/example_profiles.js +32 -0
  23. package/dist/plugins/transform/hz_anime.js +211 -0
  24. package/dist/plugins/transform/index.js +93 -0
  25. package/dist/script/index.js +537 -0
  26. package/dist/script/readscript.js +15 -0
  27. package/dist/script/strtools.js +157 -0
  28. package/dist/storage/decorator.js +260 -0
  29. package/dist/storage/fs.js +96 -0
  30. package/dist/storage/index.js +442 -0
  31. package/dist/system/index.js +144 -0
  32. package/dist/ui/index.js +535 -0
  33. package/dist/utils/path.js +289 -0
  34. package/license.txt +202 -0
  35. package/package.json +26 -0
  36. package/src/async/index.ts +124 -0
  37. package/src/async/zeppos_timer.js +65 -0
  38. package/src/audio/index.ts +224 -0
  39. package/src/config/index.ts +80 -0
  40. package/src/debug/index.ts +11 -0
  41. package/src/index.ts +122 -0
  42. package/src/platform/index.ts +158 -0
  43. package/src/plugins/basic_command/$.ts +11 -0
  44. package/src/plugins/basic_command/audio.ts +53 -0
  45. package/src/plugins/basic_command/basic.ts +145 -0
  46. package/src/plugins/basic_command/character.ts +144 -0
  47. package/src/plugins/basic_command/conditional.ts +349 -0
  48. package/src/plugins/basic_command/config.ts +29 -0
  49. package/src/plugins/basic_command/decorator.ts +29 -0
  50. package/src/plugins/basic_command/eval.ts +88 -0
  51. package/src/plugins/basic_command/img.ts +317 -0
  52. package/src/plugins/basic_command/index.ts +24 -0
  53. package/src/plugins/basic_command/menu.ts +178 -0
  54. package/src/plugins/global_gesture/index.ts +29 -0
  55. package/src/plugins/transform/animation.ts +542 -0
  56. package/src/plugins/transform/commands.ts +53 -0
  57. package/src/plugins/transform/example_profiles.ts +36 -0
  58. package/src/plugins/transform/hz_anime.ts +214 -0
  59. package/src/plugins/transform/index.ts +141 -0
  60. package/src/plugins/transform/readme.md +1 -0
  61. package/src/script/index.ts +623 -0
  62. package/src/script/readscript.ts +17 -0
  63. package/src/script/strtools.ts +159 -0
  64. package/src/storage/decorator.ts +473 -0
  65. package/src/storage/fs.ts +104 -0
  66. package/src/storage/index.ts +541 -0
  67. package/src/system/index.ts +95 -0
  68. package/src/ui/index.ts +699 -0
  69. package/src/utils/path.js +338 -0
  70. package/tsconfig.json +111 -0
  71. package/types/async/index.d.ts +24 -0
  72. package/types/async/zeppos_timer.d.ts +14 -0
  73. package/types/audio/index.d.ts +64 -0
  74. package/types/config/index.d.ts +9 -0
  75. package/types/debug/index.d.ts +6 -0
  76. package/types/index.d.ts +41 -0
  77. package/types/platform/index.d.ts +134 -0
  78. package/types/plugins/basic_command/$.d.ts +2 -0
  79. package/types/plugins/basic_command/audio.d.ts +2 -0
  80. package/types/plugins/basic_command/basic.d.ts +3 -0
  81. package/types/plugins/basic_command/character.d.ts +2 -0
  82. package/types/plugins/basic_command/conditional.d.ts +2 -0
  83. package/types/plugins/basic_command/config.d.ts +2 -0
  84. package/types/plugins/basic_command/decorator.d.ts +2 -0
  85. package/types/plugins/basic_command/eval.d.ts +2 -0
  86. package/types/plugins/basic_command/img.d.ts +2 -0
  87. package/types/plugins/basic_command/index.d.ts +2 -0
  88. package/types/plugins/basic_command/menu.d.ts +2 -0
  89. package/types/plugins/global_gesture/index.d.ts +2 -0
  90. package/types/plugins/transform/animation.d.ts +131 -0
  91. package/types/plugins/transform/commands.d.ts +7 -0
  92. package/types/plugins/transform/example_profiles.d.ts +2 -0
  93. package/types/plugins/transform/hz_anime.d.ts +51 -0
  94. package/types/plugins/transform/index.d.ts +13 -0
  95. package/types/script/index.d.ts +123 -0
  96. package/types/script/readscript.d.ts +2 -0
  97. package/types/script/strtools.d.ts +31 -0
  98. package/types/storage/decorator.d.ts +41 -0
  99. package/types/storage/fs.d.ts +1 -0
  100. package/types/storage/index.d.ts +86 -0
  101. package/types/system/index.d.ts +35 -0
  102. package/types/ui/index.d.ts +167 -0
  103. package/types/utils/path.d.ts +84 -0
@@ -0,0 +1,699 @@
1
+ import { HZEngineCore, Platform } from "../index.js";
2
+ import { Save, CustomSave } from "../storage/decorator.js";
3
+ import { Storage } from "../storage/index.js";
4
+ // / <reference path="node_modules/@zeppos/device-types/dist/index.d.ts" />
5
+ // import * as hmUI from "@zos/ui";
6
+ // import {} from "@zos/ui";
7
+
8
+ // import { getDeviceInfo, SCREEN_SHAPE_SQUARE } from "@zos/device";
9
+ // const { width, height, screenShape } = getDeviceInfo();
10
+ export class UI<PlatformType extends Platform = any> {
11
+ constructor(public _core: HZEngineCore<PlatformType>) {
12
+ this._initUI();
13
+ }
14
+
15
+ private _initUI() {
16
+ this.addLayer("bg", 1);
17
+ this.addLayer("fg", 2);
18
+ this.addLayer("ct", 3);
19
+ this.addLayer("overlay", 4);
20
+ this.addRouter("page", "overlay", false);
21
+ }
22
+
23
+ private _cleanUI() {
24
+ for (let [key, value] of this.layerList) {
25
+ value.destroy();
26
+ }
27
+ this.layerList.clear();
28
+ this._routerMap.clear();
29
+ }
30
+
31
+ resetUI() {
32
+ this._cleanUI();
33
+ this._initUI();
34
+ }
35
+
36
+ // Layer
37
+ @CustomSave(
38
+ "ui.layerList",
39
+ function serializer(layerList) {
40
+ let obj: Record<string, [name: string, z_index: number]> = {};
41
+ for (let [key, value] of this.layerList) {
42
+ obj[key] = [value.name, value.z_index];
43
+ }
44
+ return obj;
45
+ },
46
+ function deserializer(obj) {
47
+ // destroy old layer
48
+ for (let [key, value] of this.layerList) {
49
+ value.destroy();
50
+ }
51
+ this.layerList.clear();
52
+
53
+ let newLayerList = new Map<string, UI.Layer<PlatformType>>();
54
+ // create new layer
55
+ for (let key in obj) {
56
+ let newLayer = new UI.Layer(this._core, obj[key][0], obj[key][1]);
57
+ newLayerList.set(key, newLayer);
58
+ this._core.emit("afterAddLayer", newLayer);
59
+ }
60
+
61
+ return newLayerList;
62
+ }
63
+ )
64
+ private accessor _layerList: Map<string, UI.Layer<PlatformType>> = new Map();
65
+
66
+ get layerList() {
67
+ return this._layerList;
68
+ }
69
+ addLayer(name: string, z_index: number) {
70
+ this._core.emit("beforeAddLayer", name, z_index);
71
+ if (this._layerList.has(name)) throw `Layer ${name} already exist`;
72
+ let newLayer = new UI.Layer(this._core, name, z_index);
73
+ this._layerList.set(name, newLayer);
74
+ this._core.emit("afterAddLayer", newLayer);
75
+ }
76
+ getLayer(name: string): UI.Layer<PlatformType> | undefined {
77
+ return this.layerList.get(name);
78
+ }
79
+
80
+ // View Class
81
+ private _viewClassMap: Map<
82
+ string,
83
+ UI.ViewClass<Storage.Saveable<unknown>, PlatformType>
84
+ > = new Map();
85
+ // _activeViewList: [name: string, layer: string, instance: UI.View<unknown>][] =
86
+ // [];
87
+
88
+ registerView<PropType extends Storage.Saveable<PropType>>(
89
+ name: string,
90
+ cls: UI.ViewClass<PropType, PlatformType>
91
+ ): void {
92
+ this._viewClassMap.set(name, cls);
93
+ }
94
+
95
+ // View
96
+ @Save("ui.nextViewId")
97
+ private accessor _nextViewId: number = 50;
98
+
99
+ @CustomSave(
100
+ "ui.viewMap",
101
+ function serializer(viewMap) {
102
+ let obj: Record<string, UI.View.Serialized> = {};
103
+ for (let [id, view] of viewMap) {
104
+ // 注意viewMap中的id是number,而obj中的id會自動轉成string
105
+ if (view.isSave) obj[id] = view.serialize();
106
+ }
107
+ return obj;
108
+ },
109
+ function deserializer(obj) {
110
+ let newViewMap = new Map<
111
+ number,
112
+ UI.View<Storage.Saveable<unknown>, PlatformType>
113
+ >();
114
+ for (let key in obj) {
115
+ let item = obj[key] as UI.View.Serialized;
116
+ let view = this._produceViewWithId(
117
+ item.name,
118
+ item.layer,
119
+ item.prop,
120
+ Number(key)
121
+ );
122
+ view.isSave = true;
123
+ newViewMap.set(Number(key), view);
124
+ }
125
+ return newViewMap;
126
+ }
127
+ )
128
+ private accessor _viewMap: Map<
129
+ number,
130
+ UI.View<Storage.Saveable<unknown>, PlatformType>
131
+ > = new Map();
132
+
133
+ getView(id: number): UI.View<Storage.Saveable<unknown>, PlatformType> | null {
134
+ return this._viewMap.get(id) ?? null;
135
+ }
136
+
137
+ createView<PropType extends Storage.Saveable<PropType>>(
138
+ name: string,
139
+ layer: string,
140
+ prop: PropType,
141
+ isSave: boolean
142
+ ): UI.View<PropType, PlatformType> {
143
+ let id = this._nextViewId++;
144
+ let viewInstance = this._produceViewWithId(name, layer, prop, id);
145
+ this._core.debug.log(`creating view ${viewInstance.name}`);
146
+ viewInstance.isSave = isSave;
147
+ this._viewMap.set(id, viewInstance);
148
+ return viewInstance;
149
+ }
150
+ updateView<PropType extends Storage.Saveable<PropType>>(
151
+ viewInstance: UI.View<PropType, PlatformType>,
152
+ new_prop: PropType
153
+ ) {
154
+ viewInstance.commit(new_prop);
155
+ }
156
+ destroyView(viewInstance: UI.View<Storage.Saveable<unknown>, PlatformType>) {
157
+ if (viewInstance.id != null) this._viewMap.delete(viewInstance.id);
158
+ viewInstance.destroy();
159
+ }
160
+ /**由調用者提供id,創建一個View,不會處理isSave,也不會更新viewMap */
161
+ private _produceViewWithId<PropType extends Storage.Saveable<PropType>>(
162
+ name: string,
163
+ layer: string,
164
+ prop: PropType,
165
+ id: number
166
+ ): UI.View<PropType, PlatformType> {
167
+ if (!this._viewClassMap.get(name)) {
168
+ throw "要创建的View不存在";
169
+ }
170
+ let _ViewFactory = this._viewClassMap.get(name);
171
+ let viewInstance = new _ViewFactory!(layer, this._core) as UI.View<
172
+ PropType,
173
+ PlatformType
174
+ >;
175
+ viewInstance.id = id;
176
+ viewInstance.name = name;
177
+ viewInstance.create(prop);
178
+ this._core.debug.log(`producing view ${viewInstance.name}`);
179
+ return viewInstance;
180
+ }
181
+
182
+ @CustomSave(
183
+ "ui.routerMap",
184
+ function serializer(routerMap) {
185
+ let obj: Record<string, UI.Router.Serialized> = {};
186
+ for (let [key, value] of routerMap) {
187
+ if (!value.isSave) continue;
188
+ obj[key] = value.serialize();
189
+ }
190
+ return obj;
191
+ },
192
+ function deserializer(obj) {
193
+ let newRouterMap = new Map<string, UI.Router<PlatformType>>();
194
+ // reshow not save router
195
+ for (let [name, router] of this._routerMap) {
196
+ if (!router.isSave) {
197
+ if (router.length > 0) {
198
+ // TODO 因爲讀檔的時候會重置整個ui系統,所以要重新創建activeViewInstance 這裏感覺有點問題
199
+ router.activeViewInstance = this._core.ui.createView(
200
+ router.viewStack[0][0],
201
+ router.layer,
202
+ router.viewStack[0][1],
203
+ router.isSave
204
+ );
205
+ }
206
+ newRouterMap.set(name, router);
207
+ }
208
+ }
209
+ // reshow save router
210
+ for (let key in obj) {
211
+ newRouterMap.set(key, UI.Router.deserialize(this, obj[key]));
212
+ }
213
+ return newRouterMap;
214
+ }
215
+ )
216
+ private accessor _routerMap: Map<string, UI.Router<PlatformType>> = new Map();
217
+
218
+ getRouter(tag: string) {
219
+ return this._routerMap.get(tag);
220
+ }
221
+
222
+ addRouter(tag: string, layer: string, isSave: boolean = true) {
223
+ if (this._routerMap.has(tag))
224
+ throw `Route with tag [${tag}] already exist!`;
225
+ let router = new UI.Router(this, tag, layer, isSave);
226
+ this._routerMap.set(tag, router);
227
+ return router;
228
+ }
229
+
230
+ getScreenSize() {
231
+ let [width, height] = this._core.platform.getScreenSize();
232
+ return { width, height };
233
+ }
234
+ /**
235
+ * 根据 BasicUniversalProp 计算屏幕上的位置
236
+ * @param prop 包含 BasicUniversalProp 的 prop
237
+ * @param size (可选)图像的尺寸,若不指定,返回的anchor坐标和origin坐标一样
238
+ * @returns
239
+ */
240
+ calcPosition(
241
+ prop: UI.BasicUniversalProp,
242
+ size?: UI.Size
243
+ ): {
244
+ /** 锚点(算上偏移)的屏幕位置 */
245
+ anchor: UI.Coordinate;
246
+ /** 图像左上角的屏幕位置 */
247
+ origin: UI.Coordinate;
248
+ } {
249
+ let { width, height } = this.getScreenSize();
250
+ // 1. 确定 anchor
251
+ // 2. 通过 align 确定初始位置
252
+ // 3. offset
253
+ // 返回左上角的位置
254
+ let anchor_coord = {
255
+ x:
256
+ (width * ((prop.xalign ?? 0) + 1)) / 2 + // 根据 align 求出 anchor 位置
257
+ (prop.xoffset ?? 0), // offset
258
+ y:
259
+ (height * ((prop.yalign ?? 0) + 1)) / 2 + // 根据 align 求出 anchor 位置
260
+ (prop.yoffset ?? 0), // offset
261
+ };
262
+ let origin_coord = {
263
+ x: anchor_coord.x - (((prop.xanchor ?? 0) + 1) / 2) * (size?.width ?? 0),
264
+ y: anchor_coord.y - (((prop.yanchor ?? 0) + 1) / 2) * (size?.height ?? 0),
265
+ };
266
+ return {
267
+ anchor: anchor_coord,
268
+ origin: origin_coord,
269
+ };
270
+ }
271
+ }
272
+
273
+ export namespace UI {
274
+ export type ViewClass<
275
+ PropType extends Storage.Saveable<PropType>,
276
+ PlatformType extends Platform
277
+ > = {
278
+ new (layer: string, core: HZEngineCore<PlatformType>): View<
279
+ PropType,
280
+ PlatformType
281
+ >;
282
+ };
283
+
284
+ export abstract class View<
285
+ PropType extends Storage.Saveable<PropType>,
286
+ PlatformType extends Platform = any
287
+ > {
288
+ public id: number | null = null;
289
+ public name: string | null = null;
290
+ public isSave: boolean = true;
291
+ private _prop: PropType | null = null;
292
+ public get prop(): PropType | null {
293
+ return this._prop;
294
+ }
295
+ private set prop(prop: PropType | null) {
296
+ this._prop = prop;
297
+ }
298
+ constructor(
299
+ public layer: string,
300
+ public core: HZEngineCore<PlatformType>
301
+ ) {}
302
+ create(prop: PropType) {
303
+ this.prop = prop;
304
+ this.onCreate(prop);
305
+ }
306
+ protected abstract onCreate(prop: PropType): void;
307
+ commit(prop: PropType) {
308
+ this.prop = prop;
309
+ this.onCommit(prop);
310
+ }
311
+ protected abstract onCommit(prop: PropType): void;
312
+ destroy() {
313
+ this.onDestroy();
314
+ this.prop = null;
315
+ this.id = null;
316
+ }
317
+ protected abstract onDestroy(): void;
318
+
319
+ serialize(): View.Serialized {
320
+ if (this.name == null)
321
+ throw new Error("View name is null when serialize");
322
+ return {
323
+ name: this.name,
324
+ layer: this.layer,
325
+ prop: this.prop,
326
+ };
327
+ }
328
+ }
329
+
330
+ export namespace View {
331
+ export interface Serialized {
332
+ name: string;
333
+ layer: string;
334
+ prop: Storage.Saveable<unknown>;
335
+ }
336
+ }
337
+
338
+ export interface BasicUniversalProp {
339
+ // 透明度 [0, 1]
340
+ alpha?: number;
341
+ // 锚点对齐位置 [0, 1]; 在不指定的情况下,默认位于屏幕中心
342
+ xalign?: number;
343
+ yalign?: number;
344
+ // 锚点相对图像位置 [0, 1]; 在不指定的情况下,以图像中心作为锚点
345
+ xanchor?: number;
346
+ yanchor?: number;
347
+ // px; 不指定就是不偏移
348
+ xoffset?: number;
349
+ yoffset?: number;
350
+ }
351
+
352
+ // export function getScreenSize(): Size {
353
+ // let [width, height] =
354
+ // return {
355
+ // width,
356
+ // height,
357
+ // };
358
+ // }
359
+
360
+ export interface Message {
361
+ who: string;
362
+ what: string;
363
+ }
364
+ export abstract class MessageView<PlatformType extends Platform> extends View<
365
+ Message,
366
+ PlatformType
367
+ > {}
368
+
369
+ export interface MenuItemData {
370
+ text: string;
371
+ position: [path: string, index: number];
372
+ enable_js_expression?: string;
373
+ }
374
+ export type MenuViewProp = {
375
+ itemList: MenuItemData[];
376
+ };
377
+ export abstract class MenuView<PlatformType extends Platform> extends View<
378
+ MenuViewProp,
379
+ PlatformType
380
+ > {}
381
+
382
+ export type Coordinate = { x: number; y: number };
383
+ export type Size = { width: number; height: number };
384
+
385
+ /**
386
+ * 立绘/道具等显示在`fg`layer上的图片View
387
+ */
388
+ export type FgImgViewProp = {
389
+ imgPath: string;
390
+ offset: Coordinate;
391
+ size: Size;
392
+ };
393
+ export abstract class FgImgView<PlatformType extends Platform> extends View<
394
+ FgImgViewProp,
395
+ PlatformType
396
+ > {}
397
+
398
+ /**
399
+ * cg等显示在`bg`layer上的图片View
400
+ */
401
+ export type BgImgViewProp = {
402
+ imgPath: string;
403
+ offset: Coordinate;
404
+ size: Size;
405
+ };
406
+ export abstract class BgImgView<PlatformType extends Platform> extends View<
407
+ FgImgViewProp,
408
+ PlatformType
409
+ > {}
410
+
411
+ export class Layer<PlatformType extends Platform> {
412
+ widgetFactory: ReturnType<PlatformType["createUILayer"]>;
413
+ constructor(
414
+ public _core: HZEngineCore<PlatformType>,
415
+ public name: string,
416
+ public z_index: number
417
+ ) {
418
+ // this.widgetFactory = hmUI.createWidget(
419
+ // (hmUI.widget as any).VIEW_CONTAINER,
420
+ // {
421
+ // scroll_enable: 0,
422
+ // z_index,
423
+ // }
424
+ // ) as unknown as Layer.WidgetFactory;
425
+ this.widgetFactory = _core.platform.createUILayer({
426
+ z_index,
427
+ });
428
+ }
429
+ destroy() {
430
+ // hmUI.deleteWidget(this.widgetFactory as any);
431
+ this._core.platform.deleteUILayer(this.widgetFactory);
432
+ }
433
+ }
434
+ export namespace Layer {
435
+ // export interface WidgetFactory {
436
+ // createWidget(widgetType: number, option: Record<string, any>): any;
437
+ // deleteWidget(widget: any): void;
438
+ // }
439
+ }
440
+
441
+ export class Router<PlatformType extends Platform> {
442
+ constructor(
443
+ private _ui: UI<PlatformType>,
444
+ public tag: string,
445
+ public layer: string,
446
+ public isSave = true
447
+ ) {}
448
+ serialize(): Router.Serialized {
449
+ return {
450
+ tag: this.tag,
451
+ layer: this.layer,
452
+ isSave: this.isSave,
453
+ viewStack: this.viewStack,
454
+ activeViewId: this.activeViewInstance?.id ?? null,
455
+ };
456
+ }
457
+ defaultRouteStrategy: Router.RouteStrategy = {
458
+ destroy: (viewInstance, ui) => {
459
+ this._ui._core.debug.log(`destroy view ${viewInstance.name}`);
460
+ ui.destroyView(viewInstance);
461
+ },
462
+ create: (viewName, layer, prop, ui, isSave) => {
463
+ this._ui._core.debug.log(`create view ${viewName}`);
464
+ return ui.createView(viewName, layer, prop, isSave);
465
+ },
466
+ update: (viewInstance, prop, ui) => {
467
+ this._ui._core.debug.log(`update view ${viewInstance.name}`);
468
+ ui.updateView(viewInstance, prop);
469
+ },
470
+ };
471
+ static deserialize<PlatformType extends Platform>(
472
+ ui: UI<PlatformType>,
473
+ data: Router.Serialized
474
+ ) {
475
+ let router = new Router(ui, data.tag, data.layer, data.isSave);
476
+ router.viewStack = data.viewStack;
477
+ if (data.activeViewId != null) {
478
+ let viewInstance = ui.getView(data.activeViewId);
479
+ if (!viewInstance)
480
+ throw `View [${data.activeViewId}] not found when deserialize`;
481
+ router.activeViewInstance = viewInstance;
482
+ }
483
+ return router;
484
+ }
485
+ viewStack: [view_name: string, prop: Storage.Saveable<unknown>][] = [];
486
+ get length() {
487
+ return this.viewStack.length;
488
+ }
489
+ activeViewInstance: View<Storage.Saveable<unknown>, PlatformType> | null =
490
+ null;
491
+ push<T extends Storage.Saveable<T>>(
492
+ view_name: string,
493
+ prop: T,
494
+ strategy?: Router.RouteStrategy
495
+ ) {
496
+ if (this.activeViewInstance) {
497
+ // this._ui.destroyView(this.activeViewInstance);
498
+ // (strategy?.destroy ?? this.defaultRouteStrategy.destroy!)(
499
+ // this.activeViewInstance,
500
+ // this._ui
501
+ // );
502
+ if (strategy?.destroy) {
503
+ strategy.destroy(this.activeViewInstance, this._ui);
504
+ } else {
505
+ this.defaultRouteStrategy.destroy!(this.activeViewInstance, this._ui);
506
+ }
507
+ this.activeViewInstance = null;
508
+ }
509
+ let layerInstance = this._ui.getLayer(this.layer);
510
+ if (!layerInstance) throw `Layer [${this.layer}] not found`;
511
+ // this.activeViewInstance = (
512
+ // strategy?.create ?? this.defaultRouteStrategy.create!
513
+ // )(view_name, this.layer, prop, this._ui, this.isSave);
514
+ if (strategy?.create) {
515
+ this.activeViewInstance = strategy.create(
516
+ view_name,
517
+ this.layer,
518
+ prop,
519
+ this._ui,
520
+ this.isSave
521
+ );
522
+ } else {
523
+ this.activeViewInstance = this.defaultRouteStrategy.create!(
524
+ view_name,
525
+ this.layer,
526
+ prop,
527
+ this._ui,
528
+ this.isSave
529
+ );
530
+ }
531
+ this.viewStack.push([view_name, prop]);
532
+ }
533
+ pop<T extends Storage.Saveable<T>>(
534
+ back_prop?: T,
535
+ strategy?: Router.RouteStrategy
536
+ ) {
537
+ if (this.activeViewInstance) {
538
+ // this._ui.destroyView(this.activeViewInstance);
539
+ // (strategy?.destroy ?? this.defaultRouteStrategy.destroy!)(
540
+ // this.activeViewInstance,
541
+ // this._ui
542
+ // );
543
+ if (strategy?.destroy) {
544
+ strategy.destroy(this.activeViewInstance, this._ui);
545
+ } else {
546
+ this.defaultRouteStrategy.destroy!(this.activeViewInstance, this._ui);
547
+ }
548
+ this.activeViewInstance = null;
549
+ }
550
+ this.viewStack.pop();
551
+
552
+ if (this.viewStack.length) {
553
+ let backViewInfo = this.viewStack[this.viewStack.length - 1];
554
+ let layerInstance = this._ui.getLayer(this.layer);
555
+ if (!layerInstance) throw `Layer [${this.layer}] not found`;
556
+ // this.activeViewInstance = (
557
+ // strategy?.create ?? this.defaultRouteStrategy.create!
558
+ // )(
559
+ // backViewInfo[0],
560
+ // this.layer,
561
+ // back_prop ?? backViewInfo[1],
562
+ // this._ui,
563
+ // this.isSave
564
+ // );
565
+ if (strategy?.create) {
566
+ this.activeViewInstance = strategy.create(
567
+ backViewInfo[0],
568
+ this.layer,
569
+ back_prop ?? backViewInfo[1],
570
+ this._ui,
571
+ this.isSave
572
+ );
573
+ } else {
574
+ this.activeViewInstance = this.defaultRouteStrategy.create!(
575
+ backViewInfo[0],
576
+ this.layer,
577
+ back_prop ?? backViewInfo[1],
578
+ this._ui,
579
+ this.isSave
580
+ );
581
+ }
582
+ }
583
+ }
584
+ replace<T extends Storage.Saveable<T>>(
585
+ view_name: string,
586
+ prop: T,
587
+ strategy?: Router.RouteStrategy
588
+ ) {
589
+ if (this.activeViewInstance) {
590
+ // this._ui.destroyView(this.activeViewInstance);
591
+ // (strategy?.destroy ?? this.defaultRouteStrategy.destroy!)(
592
+ // this.activeViewInstance,
593
+ // this._ui
594
+ // );
595
+ if (strategy?.destroy) {
596
+ strategy.destroy(this.activeViewInstance, this._ui);
597
+ } else {
598
+ this.defaultRouteStrategy.destroy!(this.activeViewInstance, this._ui);
599
+ }
600
+ this.activeViewInstance = null;
601
+ }
602
+ this.viewStack.pop();
603
+
604
+ let layerInstance = this._ui.getLayer(this.layer);
605
+ if (!layerInstance) throw `Layer [${this.layer}] not found`;
606
+ // this.activeViewInstance = (
607
+ // strategy?.create ?? this.defaultRouteStrategy.create!
608
+ // )(view_name, this.layer, prop, this._ui, this.isSave);
609
+ if (strategy?.create) {
610
+ this.activeViewInstance = strategy.create(
611
+ view_name,
612
+ this.layer,
613
+ prop,
614
+ this._ui,
615
+ this.isSave
616
+ );
617
+ } else {
618
+ this.activeViewInstance = this.defaultRouteStrategy.create!(
619
+ view_name,
620
+ this.layer,
621
+ prop,
622
+ this._ui,
623
+ this.isSave
624
+ );
625
+ }
626
+ this.viewStack.push([view_name, prop]);
627
+ }
628
+ update<T extends Storage.Saveable<T>>(
629
+ prop: T,
630
+ strategy?: Router.RouteStrategy
631
+ ) {
632
+ if (!this.activeViewInstance)
633
+ throw `Update View but activeViewInstance is null`;
634
+ this.viewStack[this.viewStack.length - 1][1] = prop;
635
+ // (strategy?.update ?? this.defaultRouteStrategy.update!)(
636
+ // this.activeViewInstance,
637
+ // prop,
638
+ // this._ui
639
+ // );
640
+ if (strategy?.update) {
641
+ strategy.update(this.activeViewInstance, prop, this._ui);
642
+ } else {
643
+ this.defaultRouteStrategy.update!(
644
+ this.activeViewInstance,
645
+ prop,
646
+ this._ui
647
+ );
648
+ }
649
+ }
650
+ clear(strategy?: Router.RouteStrategy) {
651
+ if (this.activeViewInstance) {
652
+ // (strategy?.destroy ?? this.defaultRouteStrategy.destroy!)(
653
+ // this.activeViewInstance,
654
+ // this._ui
655
+ // );
656
+ if (strategy?.destroy) {
657
+ strategy.destroy(this.activeViewInstance, this._ui);
658
+ } else {
659
+ this.defaultRouteStrategy.destroy!(this.activeViewInstance, this._ui);
660
+ }
661
+ this.activeViewInstance = null;
662
+ }
663
+ this.viewStack = [];
664
+ }
665
+ }
666
+ export namespace Router {
667
+ export interface Serialized {
668
+ tag: string;
669
+ layer: string;
670
+ isSave: boolean;
671
+ viewStack: [view_name: string, prop: Storage.Saveable<unknown>][];
672
+ activeViewId: number | null;
673
+ }
674
+
675
+ // 实现自定义路由策略,允许接管Router对View的创建和销毁,实现例如动画等功能
676
+ export interface RouteStrategy<
677
+ PropType extends Storage.Saveable<PropType> = Storage.Saveable<unknown>,
678
+ PlatformType extends Platform = any
679
+ > {
680
+ destroy?(
681
+ viewInstance: View<PropType, PlatformType>,
682
+ ui: UI<PlatformType>
683
+ ): void;
684
+ create?(
685
+ viewName: string,
686
+ layer: string,
687
+ prop: PropType,
688
+ ui: UI<PlatformType>,
689
+ isSave: boolean
690
+ ): View<Storage.Saveable<PropType>, PlatformType>;
691
+
692
+ update?(
693
+ viewInstance: View<PropType, PlatformType>,
694
+ prop: PropType,
695
+ ui: UI<PlatformType>
696
+ ): void;
697
+ }
698
+ }
699
+ }