@shijiu/jsview-vue 2.2.426-test.0 → 2.3.151-test.0

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 (126) hide show
  1. package/bin/browser/BrowserAudio.vue.mjs +4 -1
  2. package/bin/jsview-vue-common.mjs +1 -1
  3. package/bin/jsview-vue.mjs +9771 -7511
  4. package/bin/types/utils/JsViewEngineWidget/JsvFocus/JsvFocusHub.d.ts +21 -1
  5. package/bin/types/utils/JsViewEngineWidget/JsvFocus/JsvFocusManager.d.ts +11 -2
  6. package/bin/types/utils/JsViewEngineWidget/MetroWidget/DebugFrame.vue.d.ts +8 -0
  7. package/bin/types/utils/JsViewEngineWidget/MetroWidget/DebugTools.d.ts +5 -0
  8. package/bin/types/utils/JsViewEngineWidget/MetroWidget/ListWidget.vue.d.ts +24 -6
  9. package/bin/types/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue.d.ts +24 -6
  10. package/bin/types/utils/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.d.ts +9 -2
  11. package/bin/types/utils/JsViewEngineWidget/MetroWidget/RenderItem.d.ts +8 -1
  12. package/bin/types/utils/JsViewEngineWidget/TemplateParser/CommonMetroTemplate.d.ts +2 -1
  13. package/bin/types/utils/JsViewEngineWidget/WidgetCommon.d.ts +10 -7
  14. package/bin/types/utils/JsViewPlugin/JsvAudio/version.d.mts +1 -0
  15. package/bin/types/utils/JsViewPlugin/JsvAudio/version.d.ts +1 -0
  16. package/bin/types/utils/JsViewPlugin/JsvLatex/BrowserJsvLatex.vue.d.ts +1 -1
  17. package/bin/types/utils/JsViewPlugin/JsvLatex/JsvLatex.vue.d.ts +1 -1
  18. package/bin/types/utils/JsViewPlugin/JsvPlayer/AckEventDefine.d.ts +10 -0
  19. package/bin/types/utils/JsViewPlugin/JsvPlayer/BrowserJsvPlayer.vue.d.ts +1 -2
  20. package/bin/types/utils/JsViewPlugin/JsvPlayer/JsvMedia.d.ts +2 -2
  21. package/bin/types/utils/JsViewVueTools/ForgeHandles.d.ts +1 -0
  22. package/bin/types/utils/JsViewVueTools/JsvRuntimeBridge.d.ts +43 -1
  23. package/bin/types/utils/JsViewVueTools/JsvTextureStore/CanvasTexture/Path.d.ts +21 -0
  24. package/bin/types/utils/JsViewVueTools/JsvTextureStore/CapturedTexture/CapturedTexture.d.ts +3 -3
  25. package/bin/types/utils/JsViewVueTools/JsvTextureStore/DominantColor/GetDominantColor.d.ts +7 -0
  26. package/bin/types/utils/JsViewVueTools/JsvTextureStore/JsvTextureStore.d.ts +15 -2
  27. package/bin/types/utils/JsViewVueTools/JsvTextureStore/Store.d.ts +2 -0
  28. package/bin/types/utils/JsViewVueTools/JsvTextureStore/Texture.d.ts +4 -0
  29. package/bin/types/utils/JsViewVueTools/index.d.ts +0 -1
  30. package/bin/types/utils/JsViewVueWidget/Jsv3dDiv.vue.d.ts +120 -0
  31. package/bin/types/utils/JsViewVueWidget/Jsv3dStage.vue.d.ts +144 -0
  32. package/bin/types/utils/JsViewVueWidget/JsvApic/JsvApic/index.d.ts +50 -2
  33. package/bin/types/utils/JsViewVueWidget/JsvApic/JsvApic2/index.d.ts +23 -2
  34. package/bin/types/utils/JsViewVueWidget/JsvDashPath.vue.d.ts +11 -0
  35. package/bin/types/utils/JsViewVueWidget/JsvDriftScope/JsvDriftScope.vue.d.ts +4 -4
  36. package/bin/types/utils/JsViewVueWidget/JsvFilterView.vue.d.ts +3 -3
  37. package/bin/types/utils/JsViewVueWidget/JsvFlexCell/JsvFullScrAdjust.vue.d.ts +78 -0
  38. package/bin/types/utils/JsViewVueWidget/JsvFlexCell/index.d.ts +1 -0
  39. package/bin/types/utils/JsViewVueWidget/JsvFragShaderView/JsvFragShaderView.vue.d.ts +2 -1
  40. package/bin/types/utils/JsViewVueWidget/JsvFreeMoveActor/FreeMoveActor.vue.d.ts +3 -3
  41. package/bin/types/utils/JsViewVueWidget/JsvFreeMoveActor/JsvEnvBlocker.vue.d.ts +3 -3
  42. package/bin/types/utils/JsViewVueWidget/JsvFreeMoveActor/SetState.d.ts +1 -0
  43. package/bin/types/utils/JsViewVueWidget/JsvInput/Cursor.vue.d.ts +1 -1
  44. package/bin/types/utils/JsViewVueWidget/JsvMindMap/JsvMindMap.vue.d.ts +3 -3
  45. package/bin/types/utils/JsViewVueWidget/JsvNinePatch.vue.d.ts +4 -4
  46. package/bin/types/utils/JsViewVueWidget/JsvPosterDiv.vue.d.ts +3 -0
  47. package/bin/types/utils/JsViewVueWidget/JsvPosterImage.vue.d.ts +3 -0
  48. package/bin/types/utils/JsViewVueWidget/JsvRipple/JsvRipple.vue.d.ts +3 -3
  49. package/bin/types/utils/JsViewVueWidget/JsvSmoothSlideContainer.vue.d.ts +72 -0
  50. package/bin/types/utils/JsViewVueWidget/JsvSoundPool.d.ts +26 -0
  51. package/bin/types/utils/JsViewVueWidget/JsvSpray/JsvSpray.vue.d.ts +10 -37
  52. package/bin/types/utils/JsViewVueWidget/JsvSpriteAnim/JsvSpriteAnim.vue.d.ts +1 -1
  53. package/bin/types/utils/JsViewVueWidget/JsvSwiper/JsvSmoothSwiper.vue.d.ts +112 -0
  54. package/bin/types/utils/JsViewVueWidget/JsvSwiper/JsvSwiper.vue.d.ts +1 -1
  55. package/bin/types/utils/JsViewVueWidget/JsvSwiper/JsvSwiper2.vue.d.ts +142 -0
  56. package/bin/types/utils/JsViewVueWidget/JsvSwiper/index.d.ts +3 -1
  57. package/bin/types/utils/JsViewVueWidget/JsvSwiper3D/JsvSwiper.vue.d.ts +3 -3
  58. package/bin/types/utils/JsViewVueWidget/JsvTextureAnim/JsvTextureAnim.vue.d.ts +4 -3
  59. package/bin/types/utils/JsViewVueWidget/JsvVisibleSensor/JsvVisibleSensor.vue.d.ts +3 -3
  60. package/bin/types/utils/JsViewVueWidget/JsvVisibleSensor/index.d.ts +3 -3
  61. package/bin/types/utils/JsViewVueWidget/index.d.ts +4 -1
  62. package/package.json +1 -1
  63. package/utils/JsViewEngineWidget/CheckType.js +3 -3
  64. package/utils/JsViewEngineWidget/JsvFocus/JsvFocusBlock.vue +25 -6
  65. package/utils/JsViewEngineWidget/JsvFocus/JsvFocusHub.ts +27 -1
  66. package/utils/JsViewEngineWidget/JsvFocus/JsvFocusManager.ts +22 -3
  67. package/utils/JsViewEngineWidget/MetroWidget/DebugFrame.vue +22 -0
  68. package/utils/JsViewEngineWidget/MetroWidget/DebugTools.ts +37 -0
  69. package/utils/JsViewEngineWidget/MetroWidget/ListWidget.vue +42 -7
  70. package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +97 -13
  71. package/utils/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.js +876 -412
  72. package/utils/JsViewEngineWidget/MetroWidget/RenderItem.ts +43 -2
  73. package/utils/JsViewEngineWidget/MetroWidget/TaskManager.ts +38 -26
  74. package/utils/JsViewEngineWidget/TemplateParser/CommonMetroTemplate.ts +144 -73
  75. package/utils/JsViewEngineWidget/WidgetCommon.ts +12 -0
  76. package/utils/JsViewPlugin/JsvAudio/BrowserAudio/BrowserAudio.vue +4 -0
  77. package/utils/JsViewPlugin/JsvAudio/BrowserAudio/JsvSystemAudio.vue +13 -13
  78. package/utils/JsViewPlugin/JsvAudio/version.js +1 -1
  79. package/utils/JsViewPlugin/JsvAudio/version.mjs +1 -1
  80. package/utils/JsViewPlugin/JsvPlayer/AckEventDefine.ts +82 -0
  81. package/utils/JsViewPlugin/JsvPlayer/BrowserJsvPlayer.vue +50 -32
  82. package/utils/JsViewVueTools/FeatureActive.ts +2 -1
  83. package/utils/JsViewVueTools/ForgeHandles.ts +5 -2
  84. package/utils/JsViewVueTools/JsvRuntimeBridge.js +109 -4
  85. package/utils/JsViewVueTools/JsvTextTools.ts +3 -1
  86. package/utils/JsViewVueTools/JsvTextureStore/CanvasTexture/Path.ts +38 -2
  87. package/utils/JsViewVueTools/JsvTextureStore/CapturedTexture/CapturedTexture.ts +15 -12
  88. package/utils/JsViewVueTools/JsvTextureStore/DominantColor/GetDominantColor.ts +36 -0
  89. package/utils/JsViewVueTools/JsvTextureStore/JsvTextureStore.ts +24 -3
  90. package/utils/JsViewVueTools/JsvTextureStore/Store.ts +33 -21
  91. package/utils/JsViewVueTools/JsvTextureStore/Texture.ts +56 -41
  92. package/utils/JsViewVueTools/index.js +0 -1
  93. package/utils/JsViewVueWidget/Jsv3dDiv.vue +85 -0
  94. package/utils/JsViewVueWidget/Jsv3dStage.vue +50 -0
  95. package/utils/JsViewVueWidget/JsvApic/JsvApic/index.js +1 -8
  96. package/utils/JsViewVueWidget/JsvApic/JsvApic2/index.js +1 -8
  97. package/utils/JsViewVueWidget/JsvDashPath.vue +150 -0
  98. package/utils/JsViewVueWidget/JsvFlexCell/JsvFlexDiv.vue +1 -1
  99. package/utils/JsViewVueWidget/JsvFlexCell/JsvFullScrAdjust.vue +153 -0
  100. package/utils/JsViewVueWidget/JsvFlexCell/JsvScreenFlex.vue +2 -2
  101. package/utils/JsViewVueWidget/JsvFlexCell/index.js +1 -0
  102. package/utils/JsViewVueWidget/JsvFragShaderView/JsvFragShaderView.vue +26 -22
  103. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetAction.ts +1 -1
  104. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetState.ts +8 -0
  105. package/utils/JsViewVueWidget/JsvInput/EditViewOperator.ts +1 -1
  106. package/utils/JsViewVueWidget/JsvInput/JsvInput.vue +1 -0
  107. package/utils/JsViewVueWidget/JsvMaskClipDiv.vue +0 -9
  108. package/utils/JsViewVueWidget/JsvNativeSharedDiv.vue +57 -71
  109. package/utils/JsViewVueWidget/JsvPosterDiv.vue +15 -8
  110. package/utils/JsViewVueWidget/JsvPosterImage.vue +11 -1
  111. package/utils/JsViewVueWidget/JsvPreload/JsvPreload.vue +2 -2
  112. package/utils/JsViewVueWidget/JsvQrcode/JsvQrcode.vue +1 -1
  113. package/utils/JsViewVueWidget/JsvSmoothSlideContainer.vue +108 -0
  114. package/utils/JsViewVueWidget/JsvSoundPool.js +75 -12
  115. package/utils/JsViewVueWidget/JsvSpray/JsvSpray.vue +99 -61
  116. package/utils/JsViewVueWidget/JsvSwiper/JsvSmoothSwiper.vue +543 -0
  117. package/utils/JsViewVueWidget/JsvSwiper/JsvSwiper.vue +3 -3
  118. package/utils/JsViewVueWidget/JsvSwiper/JsvSwiper2.vue +644 -0
  119. package/utils/JsViewVueWidget/JsvSwiper/index.js +3 -1
  120. package/utils/JsViewVueWidget/JsvTextureAnim/JsvTextureAnim.vue +56 -50
  121. package/utils/JsViewVueWidget/index.js +4 -1
  122. package/bin/browser/BrowserApic.vue.mjs +0 -114
  123. package/bin/browser/BrowserApic2.vue.mjs +0 -108
  124. package/bin/browser/BrowserApicLib.mjs +0 -431
  125. package/bin/types/utils/JsViewVueTools/JsvDemoTester.d.ts +0 -2
  126. package/utils/JsViewVueTools/JsvDemoTester.js +0 -81
@@ -27,12 +27,22 @@ import { RenderItem } from "./RenderItem";
27
27
  import { VisibleInfo } from "./VisibleInfo";
28
28
  import { WidgetRectInfo } from "./WidgetRectInfo";
29
29
  import ActorControl from "../../JsViewVueWidget/JsvFreeMoveActor/ActorControl.ts";
30
- import { TaskType, TaskManager, AnimationManager, SlideTaskType } from "./TaskManager.ts";
30
+ import {
31
+ TaskType,
32
+ TaskManager,
33
+ AnimationManager,
34
+ SlideTaskType,
35
+ } from "./TaskManager.ts";
31
36
  import { getDirectionByRect, RectCache } from "./Slide.ts";
32
- import { ForgeConst } from "../../JsViewVueTools/ForgeConstDefine.ts";
33
- import { FeatureNames, JsvUseFeature } from "../../JsViewVueTools/FeatureActive.ts";
37
+ import {
38
+ FeatureNames,
39
+ JsvUseFeature,
40
+ } from "../../JsViewVueTools/FeatureActive.ts";
41
+ import { randomColor } from "./DebugTools.ts";
34
42
 
35
43
  const TAG = "MetroWidget";
44
+ const LONGPRESS_TIMEOUT = 600;
45
+ const DATA_ID_KEY = "jsvKey";
36
46
 
37
47
  let metroWidgetTokenGen = 1;
38
48
 
@@ -91,13 +101,17 @@ export const setup = (
91
101
  pageUpdateToken,
92
102
  touchDiv,
93
103
  touchDivSize,
94
- templateMode) => {
95
-
104
+ templateMode
105
+ ) => {
96
106
  if (props.itemConfig) {
97
- console.error(TAG, "prop: itemCofig will be deprecated soon.")
107
+ console.error(TAG, "prop: itemCofig will be deprecated soon.");
98
108
  }
99
109
 
100
- let widgetRectInfo = new WidgetRectInfo(props.width, props.height, props.padding);
110
+ let widgetRectInfo = new WidgetRectInfo(
111
+ props.width,
112
+ props.height,
113
+ props.padding
114
+ );
101
115
  let metroTemplate = _getMetroTemplate(
102
116
  widgetRectInfo,
103
117
  props.direction,
@@ -119,7 +133,7 @@ export const setup = (
119
133
  } else {
120
134
  if (props.touchFlag > 0) {
121
135
  // 激活引擎功能的支持
122
- JsvUseFeature('MetroWidget', FeatureNames.TouchReceiver);
136
+ JsvUseFeature("MetroWidget", FeatureNames.TouchReceiver);
123
137
 
124
138
  //触控默认3屏
125
139
  innerKeepTraceRange = 3;
@@ -163,8 +177,7 @@ export const setup = (
163
177
  this._touchState = TouchState.DRAG;
164
178
  }
165
179
  },
166
- dragEnd(touchCount) {
167
- },
180
+ dragEnd(touchCount) {},
168
181
  keyDown() {
169
182
  this._mode = FOCUS_MODE;
170
183
  modeForExport.value = FOCUS_MODE;
@@ -184,11 +197,12 @@ export const setup = (
184
197
  },
185
198
  getTouchCount() {
186
199
  return this._touchCount;
187
- }
188
- }
200
+ },
201
+ };
189
202
 
190
203
  let innerData = [];
191
204
  let dataList = [];
205
+ let dataKeyList = [];
192
206
  let pageUpdater = null;
193
207
  let enterFocusId = -1;
194
208
  let enterFocusRect = null;
@@ -205,8 +219,8 @@ export const setup = (
205
219
  let childSlideEventLock = false;
206
220
  let onKeyDownLock = false;
207
221
  let visibleInfo = new VisibleInfo();
208
- let alreadyCallItemFocus = false;
209
- let innerSlideSetting = props.slideSetting
222
+ let firstOnItemFocusCalled = false;
223
+ let innerSlideSetting = props.slideSetting;
210
224
  const currentFocusIndex = ref(0);
211
225
 
212
226
  // 当sliderDiv变化时,渲染端在响应此变化前的gap记录,用于准确计算getVisibleStart
@@ -215,23 +229,40 @@ export const setup = (
215
229
 
216
230
  const DEFAULT_ANIMATION_DURATION = 200;
217
231
 
218
- const isItemVisible = (item) => {
232
+ //rect {left: number, top: number, width: number, height: number }
233
+ const rectVisibleState = (rect) => {
234
+ if (!rect) {
235
+ return 0;
236
+ }
219
237
  let pos_key = vertical ? "top" : "left";
220
238
  let size_key = vertical ? "height" : "width";
221
- return item.templateInfo[pos_key] >= visibleInfo.start
222
- && item.templateInfo[pos_key] + item.templateInfo[size_key] - 1 < visibleInfo.end;
223
- }
239
+ if (
240
+ rect[pos_key] + rect[size_key] - 1 < visibleInfo.start ||
241
+ rect[pos_key] > visibleInfo.end
242
+ ) {
243
+ return 0; // 完全不可见
244
+ } else if (
245
+ rect[pos_key] < visibleInfo.start ||
246
+ rect[pos_key] + rect[size_key] - 1 > visibleInfo.end
247
+ ) {
248
+ return 1; // 部分可见
249
+ } else {
250
+ return 2; // 完全可见
251
+ }
252
+ };
224
253
 
225
254
  //tools
226
255
  const lastOfArray = (array) => {
227
256
  if (array instanceof Array && array.length > 0) {
228
- return array[array.length - 1]
257
+ return array[array.length - 1];
229
258
  }
230
259
  return null;
231
- }
260
+ };
232
261
 
233
262
  const onAddTask = (allTask) => {
234
- if (!innerData || innerData.length <= 0) { return; }
263
+ if (!innerData || innerData.length <= 0) {
264
+ return;
265
+ }
235
266
  let resizeTaskMap = {};
236
267
  //统一处理itemResize和slide动画
237
268
  let minIndex = Infinity;
@@ -252,24 +283,25 @@ export const setup = (
252
283
  doAnim: false,
253
284
  duration: 200,
254
285
  easing: "",
255
- }
286
+ };
256
287
  let resizeList = allTask.resize.concat();
257
288
  if (resizeList.length > 0) {
258
289
  //resize
259
- resizeList.forEach(task => {
290
+ resizeList.forEach((task) => {
260
291
  resizeTaskMap[task.params.index] = task;
261
292
  const { index, animInfo } = task.params;
262
293
  if (animInfo) {
263
294
  resizeAnimInfo.doAnim = true;
264
- resizeAnimInfo.duration = animInfo.duration ?? resizeAnimInfo.duration;
265
- resizeAnimInfo.easing = animInfo.duration ?? "";
295
+ resizeAnimInfo.duration =
296
+ animInfo.duration ?? resizeAnimInfo.duration;
297
+ resizeAnimInfo.easing = animInfo.easing ?? "";
266
298
  }
267
299
  minIndex = Math.min(minIndex, index);
268
300
 
269
301
  metroTemplate.updateItemSize(task.params.index, {
270
302
  width: task.params.width,
271
303
  height: task.params.height,
272
- })
304
+ });
273
305
  });
274
306
 
275
307
  //更新touch的size
@@ -280,12 +312,17 @@ export const setup = (
280
312
  const task = resizeTaskMap[id2Index(focusId)];
281
313
  const animInfo = task.params.animInfo;
282
314
  if (typeof animInfo?.anchor == "number") {
283
- const preRect = getItemById(focusId)?.templateInfo?.layoutCache.getPreRect();
315
+ const preRect =
316
+ getItemById(focusId)?.templateInfo?.layoutCache.getPreRect();
284
317
  if (preRect) {
285
318
  anchorInfo = {
286
- anchorPosition: preRect[pos_key] + preRect[size_key] * animInfo.anchor - 1 - visibleInfo.start,
319
+ anchorPosition:
320
+ preRect[pos_key] +
321
+ preRect[size_key] * animInfo.anchor -
322
+ 1 -
323
+ visibleInfo.start,
287
324
  anchor: animInfo.anchor,
288
- }
325
+ };
289
326
  }
290
327
  }
291
328
  }
@@ -301,55 +338,73 @@ export const setup = (
301
338
  let direction = undefined;
302
339
 
303
340
  let validSlideTask = false;
341
+ let forceSlide = false;
304
342
  if (allTask.slide.length > 0) {
305
343
  validSlideTask = true;
306
344
  //有滚动时, 取消延时加载
307
345
  tryCancelDelayLoad();
308
346
  let slideTask = lastOfArray(allTask.slide);
309
347
  slideDoAnim = slideTask.params.doAnim;
348
+ forceSlide = slideTask.params.force;
310
349
  switch (slideTask.subType) {
311
- case SlideTaskType.SLIDE_BY_DIV: {
312
- const div = slideTask.params.div;
313
- const item_layout = div.jsvGetRelativePosition(toRaw(locateDiv.value));
314
- let fakeItem = {
315
- templateInfo: {
316
- left: item_layout.left,
317
- top: item_layout.top,
318
- width: item_layout.width,
319
- height: item_layout.height,
320
- centerYPos: Math.floor(item_layout.top + item_layout.height / 2),
321
- centerXPos: Math.floor(item_layout.left + item_layout.width / 2),
322
- index: id2Index(focusId),
323
- },
324
- };
325
- templateItemAdder.tryAddItemByPosition(vertical ? fakeItem.templateInfo.top : fakeItem.templateInfo.left);
326
- targetRect = fakeItem.templateInfo;
327
- } break;
328
- case SlideTaskType.SLIDE_BY_POS: {
329
- const position = slideTask.params.position;
330
- templateItemAdder.tryAddItemByPosition(position);
331
- targetVisibleStart = position;
332
- } break;
333
- case SlideTaskType.SLIDE_BY_ITEM: {
334
- const index = slideTask.params.index;
335
- templateItemAdder.tryAddItemByIndex(index);
336
- const targetItem = getItemByIndex(index);
337
- if (targetItem) {
350
+ case SlideTaskType.SLIDE_BY_DIV:
351
+ {
352
+ const div = slideTask.params.div;
353
+ const item_layout = div.jsvGetRelativePosition(
354
+ toRaw(locateDiv.value)
355
+ );
356
+ let fakeItem = {
357
+ templateInfo: {
358
+ left: item_layout.left,
359
+ top: item_layout.top,
360
+ width: item_layout.width,
361
+ height: item_layout.height,
362
+ centerYPos: Math.floor(
363
+ item_layout.top + item_layout.height / 2
364
+ ),
365
+ centerXPos: Math.floor(
366
+ item_layout.left + item_layout.width / 2
367
+ ),
368
+ index: id2Index(focusId),
369
+ },
370
+ };
371
+ templateItemAdder.tryAddItemByPosition(
372
+ vertical ? fakeItem.templateInfo.top : fakeItem.templateInfo.left
373
+ );
374
+ targetRect = fakeItem.templateInfo;
375
+ }
376
+ break;
377
+ case SlideTaskType.SLIDE_BY_POS:
378
+ {
379
+ const position = slideTask.params.position;
380
+ templateItemAdder.tryAddItemByPosition(position);
381
+ targetVisibleStart = position;
382
+ }
383
+ break;
384
+ case SlideTaskType.SLIDE_BY_ITEM:
385
+ {
386
+ const index = slideTask.params.index;
387
+ templateItemAdder.tryAddItemByIndex(index);
388
+ const targetItem = getItemByIndex(index);
389
+ if (targetItem) {
390
+ if (typeof slideTask.params.direction != "undefined") {
391
+ direction = slideTask.params.direction;
392
+ }
393
+ targetRect = targetItem.templateInfo;
394
+ } else {
395
+ //无效的滚动
396
+ validSlideTask = false;
397
+ }
398
+ }
399
+ break;
400
+ case SlideTaskType.SLIDE_BY_RECT:
401
+ {
338
402
  if (typeof slideTask.params.direction != "undefined") {
339
403
  direction = slideTask.params.direction;
340
404
  }
341
- targetRect = targetItem.templateInfo;
342
- } else {
343
- //无效的滚动
344
- validSlideTask = false;
345
- }
346
- } break;
347
- case SlideTaskType.SLIDE_BY_RECT: {
348
- if (typeof slideTask.params.direction != "undefined") {
349
- direction = slideTask.params.direction;
405
+ targetRect = slideTask.params.rect;
350
406
  }
351
- targetRect = slideTask.params.rect;
352
- } break;
407
+ break;
353
408
  default:
354
409
  break;
355
410
  }
@@ -361,10 +416,39 @@ export const setup = (
361
416
  if (anchorInfo) {
362
417
  //保持anchor
363
418
  const focusItem = getItemById(focusId);
364
- let start = focusItem.templateInfo[pos_key] + focusItem.templateInfo[size_key] * anchorInfo.anchor - 1 - anchorInfo.anchorPosition;
419
+ let start =
420
+ focusItem.templateInfo[pos_key] +
421
+ focusItem.templateInfo[size_key] * anchorInfo.anchor -
422
+ 1 -
423
+ anchorInfo.anchorPosition;
365
424
  let totalSize = metroTemplate.getBoundingBoxSize();
366
- start = Math.min(Math.max(0, start), totalSize[size_key] - visibleInfo.range)
367
- targetVisibleStart = normalizeVisibleStart(start, focusItem.templateInfo, focusItem.templateInfo.index, visibleInfo);
425
+ start = Math.min(
426
+ Math.max(0, start),
427
+ totalSize[size_key] - visibleInfo.range
428
+ );
429
+ //resize的情况下, 需要保证第一个和最后一个尺寸变化后, 能完整展示
430
+ if (focusItem.index == 0) {
431
+ if (start > focusItem.templateInfo[pos_key]) {
432
+ start = 0;
433
+ }
434
+ } else if (
435
+ focusItem.templateInfo.index == metroTemplate.getTailItemIndex()
436
+ ) {
437
+ if (start + visibleInfo.range > focusItem.templateInfo[pos_key]) {
438
+ start = Math.max(
439
+ focusItem.templateInfo[size_key] +
440
+ focusItem.templateInfo[pos_key] -
441
+ visibleInfo.range,
442
+ 0
443
+ );
444
+ }
445
+ }
446
+ targetVisibleStart = normalizeVisibleStart(
447
+ start,
448
+ focusItem.templateInfo,
449
+ focusItem.templateInfo.index,
450
+ visibleInfo
451
+ );
368
452
  } else {
369
453
  targetRect = getItemById(focusId).templateInfo;
370
454
  }
@@ -379,11 +463,20 @@ export const setup = (
379
463
  preInfo = mRectCache.getPreRect();
380
464
  if (preInfo) {
381
465
  let totalSize = metroTemplate.getBoundingBoxSize();
382
- v.start = Math.min(Math.max(0, targetRect[pos_key] - preInfo[pos_key] + v.start), Math.max(0, totalSize[size_key] - v.range));
383
- preInfo[pos_key] += (v.start - visibleInfo.start);
466
+ v.start = Math.min(
467
+ Math.max(0, targetRect[pos_key] - preInfo[pos_key] + v.start),
468
+ Math.max(0, totalSize[size_key] - v.range)
469
+ );
470
+ preInfo[pos_key] += v.start - visibleInfo.start;
384
471
  }
385
472
  }
386
- targetVisibleStart = _calculateVisibleStart(targetRect, direction, targetRect, v, preInfo);
473
+ targetVisibleStart = _calculateVisibleStart(
474
+ targetRect,
475
+ direction,
476
+ targetRect,
477
+ v,
478
+ preInfo
479
+ );
387
480
  } else {
388
481
  //resize通过anchor直接设置了visibleStart
389
482
  if (resizeList.length > 0) {
@@ -395,7 +488,7 @@ export const setup = (
395
488
  width: tRect.width,
396
489
  height: tRect.height,
397
490
  frameCount: Forge.sFrameCount.count,
398
- })
491
+ });
399
492
  }
400
493
  }
401
494
  }
@@ -408,12 +501,12 @@ export const setup = (
408
501
  visibleInfo.start = targetVisibleStart;
409
502
  return () => {
410
503
  visibleInfo.start = preVisibleStart;
411
- }
504
+ };
412
505
  });
413
506
  }
414
507
 
415
508
  //updatePage
416
- let updateHandler
509
+ let updateHandler;
417
510
  taskManager.run(() => {
418
511
  updateHandler = pageUpdater.update(
419
512
  metroTemplate,
@@ -425,8 +518,8 @@ export const setup = (
425
518
  );
426
519
  return () => {
427
520
  updateHandler.recover();
428
- }
429
- })
521
+ };
522
+ });
430
523
 
431
524
  // resize item 动画
432
525
  if (resizeList.length > 0) {
@@ -438,7 +531,8 @@ export const setup = (
438
531
  const renderItem = getItemByIndex(index);
439
532
  const { left, top } = renderItem.templateInfo;
440
533
  if (index >= minIndex) {
441
- const layoutCache = renderItem.templateInfo.layoutCache.getPreRect();
534
+ const layoutCache =
535
+ renderItem.templateInfo.layoutCache.getPreRect();
442
536
  if (layoutCache) {
443
537
  const doItemSlide = (div) => {
444
538
  taskManager.run(() => {
@@ -446,15 +540,18 @@ export const setup = (
446
540
  div,
447
541
  [layoutCache.left - left, layoutCache.top - top],
448
542
  [0, 0],
449
- resizeTaskMap[index] ?
450
- resizeTaskMap[index].params.animInfo
451
- : { duration: resizeAnimInfo.duration }
452
- )
543
+ resizeTaskMap[index]
544
+ ? resizeTaskMap[index].params.animInfo
545
+ : {
546
+ duration: resizeAnimInfo.duration,
547
+ easing: resizeAnimInfo.easing,
548
+ }
549
+ );
453
550
  return () => {
454
- cancel()
455
- }
551
+ cancel();
552
+ };
456
553
  });
457
- }
554
+ };
458
555
 
459
556
  if (renderItem.mounted.value) {
460
557
  doItemSlide(renderItem.rootDiv);
@@ -473,18 +570,22 @@ export const setup = (
473
570
  }
474
571
 
475
572
  //处理滚动动画
476
- if (needSlide) {
573
+ if (forceSlide || needSlide) {
477
574
  let animInfo = undefined;
478
575
  if (slideDoAnim) {
479
576
  animInfo = {
480
- easing: null,//resizeAnimInfo.doAnim ? resizeAnimInfo.easing : '' /* innerSlideSetting.Easing */,
481
- duration: resizeAnimInfo.doAnim ? resizeAnimInfo.duration : innerSlideSetting.Duration,
577
+ easing: resizeAnimInfo.doAnim
578
+ ? resizeAnimInfo.easing
579
+ : innerSlideSetting.Easing /* innerSlideSetting.Easing */,
580
+ duration: resizeAnimInfo.doAnim
581
+ ? resizeAnimInfo.duration
582
+ : innerSlideSetting.Duration,
482
583
  speed: innerSlideSetting.Speed,
483
584
  onStart: null,
484
585
  onEnd: null,
485
- }
586
+ };
486
587
  }
487
- executeSlide(visibleInfo.start, animInfo, updateHandler)
588
+ executeSlide(visibleInfo.start, animInfo, updateHandler);
488
589
  }
489
590
 
490
591
  //回调
@@ -495,8 +596,8 @@ export const setup = (
495
596
  }, 0);
496
597
  return () => {
497
598
  clearTimeout(handler);
498
- }
499
- })
599
+ };
600
+ });
500
601
  }
501
602
  if ((needSlide || allTask.focus.length > 0) && props.onFocusRectChange) {
502
603
  taskManager.run(() => {
@@ -505,10 +606,10 @@ export const setup = (
505
606
  }, 0);
506
607
  return () => {
507
608
  clearTimeout(handler);
508
- }
509
- })
609
+ };
610
+ });
510
611
  }
511
- }
612
+ };
512
613
  const taskManager = new TaskManager(onAddTask);
513
614
  const animationManager = new AnimationManager();
514
615
 
@@ -521,12 +622,14 @@ export const setup = (
521
622
  return () => {
522
623
  slideDivLeft.value = preLeft;
523
624
  slideDivTop.value = preTop;
524
- }
625
+ };
525
626
  });
526
627
  if (animObj) {
527
628
  updateHandler.applyTmp();
528
629
  taskManager.run(() => {
529
- const from = vertical ? [0, preTop - slideDivTop.value] : [preLeft - slideDivLeft.value, 0];
630
+ const from = vertical
631
+ ? [0, preTop - slideDivTop.value]
632
+ : [preLeft - slideDivLeft.value, 0];
530
633
  const cancel = animationManager.startSlideAnim(
531
634
  slideDiv.value,
532
635
  from,
@@ -534,13 +637,13 @@ export const setup = (
534
637
  {
535
638
  ...animObj,
536
639
  onEnd: () => {
537
- updateHandler.apply()
538
- }
640
+ updateHandler.apply();
641
+ },
539
642
  }
540
643
  );
541
644
  return () => {
542
- cancel()
543
- }
645
+ cancel();
646
+ };
544
647
  });
545
648
  } else {
546
649
  updateHandler.apply();
@@ -551,28 +654,31 @@ export const setup = (
551
654
  }, 0);
552
655
  return () => {
553
656
  clearTimeout(handler);
554
- }
555
- })
556
- }
657
+ };
658
+ });
659
+ };
557
660
 
558
661
  const updateItemSize = (index, newSize, animInfo) => {
559
662
  const item = getItemByIndex(index);
560
- if (item && (item.templateInfo.width !== newSize.width || item.templateInfo.height !== newSize.height)) {
561
- taskManager.addTask(TaskType.RESIZE_ITEM,
562
- {
563
- index,
564
- width: newSize.width,
565
- height: newSize.height,
566
- animInfo,
567
- preRect: {
568
- left: item.templateInfo.left,
569
- top: item.templateInfo.top,
570
- width: item.templateInfo.width,
571
- height: item.templateInfo.height,
572
- },
573
- });
663
+ if (
664
+ item &&
665
+ (item.templateInfo.width !== newSize.width ||
666
+ item.templateInfo.height !== newSize.height)
667
+ ) {
668
+ taskManager.addTask(TaskType.RESIZE_ITEM, {
669
+ index,
670
+ width: newSize.width,
671
+ height: newSize.height,
672
+ animInfo,
673
+ preRect: {
674
+ left: item.templateInfo.left,
675
+ top: item.templateInfo.top,
676
+ width: item.templateInfo.width,
677
+ height: item.templateInfo.height,
678
+ },
679
+ });
574
680
  }
575
- }
681
+ };
576
682
 
577
683
  let callFocusAfterUpdate = false;
578
684
 
@@ -602,12 +708,16 @@ export const setup = (
602
708
  };
603
709
  const _getTemplatePosition = (index) => {
604
710
  let templateInfo = getItemByIndex(index).templateInfo;
605
- return {
606
- left: templateInfo.left,
607
- top: templateInfo.top,
608
- width: templateInfo.width,
609
- height: templateInfo.height,
610
- };
711
+ if (templateInfo) {
712
+ return {
713
+ left: templateInfo.left,
714
+ top: templateInfo.top,
715
+ width: templateInfo.width,
716
+ height: templateInfo.height,
717
+ };
718
+ } else {
719
+ return null;
720
+ }
611
721
  };
612
722
 
613
723
  const id2Index = (id) => {
@@ -654,7 +764,9 @@ export const setup = (
654
764
  };
655
765
 
656
766
  const onItemClick = (item) => {
657
- if (!item) { return };
767
+ if (!item) {
768
+ return;
769
+ }
658
770
  if (isFocus) {
659
771
  item.onClick();
660
772
  }
@@ -668,23 +780,64 @@ export const setup = (
668
780
  }
669
781
  };
670
782
 
783
+ let gazeIndex = -1;
671
784
  const onItemFocus = (focusItem, rect) => {
672
785
  //触控模式不触发item的onFocus
673
786
  if (!focusItem) return;
674
787
  setItemZIndex(focusItem, innerData.length, true);
675
788
  if (isFocus) {
676
789
  _itemOnFocusSideEffect(focusItem, rect);
677
- const called = focusItem.onFocus(rect);
678
- if (!called) {
679
- callFocusAfterUpdate = true;
790
+ }
791
+
792
+ if (focusItem.mounted.value) {
793
+ if (gazeIndex != focusItem.templateInfo.index) {
794
+ let preGazeItem = getItemByIndex(gazeIndex);
795
+ if (preGazeItem) {
796
+ preGazeItem.onIgnore();
797
+ }
798
+ gazeIndex = focusItem.templateInfo.index;
799
+ focusItem.onGaze(rect);
800
+ }
801
+ if (isFocus) {
802
+ focusItem.onFocus(rect);
680
803
  }
681
- return called;
804
+ return true;
805
+ } else {
806
+ callFocusAfterUpdate = true;
807
+ return false;
682
808
  }
683
- return false;
684
809
  };
685
810
 
686
- const setFocusByUid = (uid, needSlide = true, doAnim = false, extraSetting) => {
687
- if (!uid || innerData.length <= 0) { return; }
811
+ const onItemLongPress = (item) => {
812
+ if (!item) {
813
+ return;
814
+ }
815
+ if (isFocus) {
816
+ item.onLongPress();
817
+ }
818
+ };
819
+
820
+ //tap的时候触发ongaze
821
+ const onItemTap = (gazeItem) => {
822
+ if (gazeIndex != gazeItem.templateInfo.index) {
823
+ let preGazeItem = getItemByIndex(gazeIndex);
824
+ if (preGazeItem) {
825
+ preGazeItem.onIgnore();
826
+ }
827
+ gazeIndex = gazeItem.templateInfo.index;
828
+ gazeItem.onGaze(null);
829
+ }
830
+ };
831
+
832
+ const setFocusByUid = (
833
+ uid,
834
+ needSlide = true,
835
+ doAnim = false,
836
+ extraSetting
837
+ ) => {
838
+ if (!uid || innerData.length <= 0) {
839
+ return;
840
+ }
688
841
  //添加item
689
842
  templateItemAdder.tryAddItemByUid(uid);
690
843
  const item = metroTemplate.getItemByUid(uid);
@@ -694,7 +847,7 @@ export const setup = (
694
847
  }
695
848
 
696
849
  setFocusId(item.id, needSlide, doAnim, extraSetting);
697
- }
850
+ };
698
851
 
699
852
  const setFocusId = (id, needSlide = true, doAnim = false, extraSetting) => {
700
853
  if (id == focusId || innerData.length <= 0) {
@@ -792,20 +945,32 @@ export const setup = (
792
945
  const setZIndex = (index, normalZIndex, focusZIndex) => {
793
946
  const targetItem = getItemByIndex(index);
794
947
  if (targetItem) {
795
- const n = normalZIndex, f = focusZIndex ?? normalZIndex;
948
+ const n = normalZIndex,
949
+ f = focusZIndex ?? normalZIndex;
796
950
 
797
951
  targetItem.itemConfig.focusZIndex = f;
798
952
  targetItem.itemConfig.normalZIndex = n;
799
953
  const focused = isFocus && focusId == index2Id(index);
800
954
  setItemZIndex(targetItem, focused ? f : n, focused);
801
955
  }
802
- }
956
+ };
803
957
 
804
- const slideToInner = (position, doAnim, updateParam = { mergeTmp: false }) => {
805
- if (slideLock || position == (vertical ? slideDivTop.value : slideDivLeft.value)) {
806
- return
807
- };
808
- taskManager.addTask(TaskType.SLIDE, { position, doAnim, updateParam }, SlideTaskType.SLIDE_BY_POS);
958
+ const slideToInner = (
959
+ position,
960
+ doAnim,
961
+ updateParam = { mergeTmp: false }
962
+ ) => {
963
+ if (
964
+ slideLock ||
965
+ position == (vertical ? slideDivTop.value : slideDivLeft.value)
966
+ ) {
967
+ return;
968
+ }
969
+ taskManager.addTask(
970
+ TaskType.SLIDE,
971
+ { position, doAnim, updateParam },
972
+ SlideTaskType.SLIDE_BY_POS
973
+ );
809
974
  };
810
975
 
811
976
  const slideTo = (position, doAnim) => {
@@ -814,7 +979,13 @@ export const setup = (
814
979
  }
815
980
  };
816
981
 
817
- const slideToItemInner = (index, doAnim, direction = undefined, preItem = undefined) => {
982
+ const slideToItemInner = (
983
+ index,
984
+ doAnim,
985
+ direction = undefined,
986
+ preItem = undefined,
987
+ force = false
988
+ ) => {
818
989
  taskManager.addTask(
819
990
  TaskType.SLIDE,
820
991
  {
@@ -822,16 +993,18 @@ export const setup = (
822
993
  doAnim,
823
994
  direction,
824
995
  preItem,
996
+ force,
825
997
  },
826
- SlideTaskType.SLIDE_BY_ITEM);
998
+ SlideTaskType.SLIDE_BY_ITEM
999
+ );
827
1000
  };
828
1001
  const slideToItem = (index, doAnim) => {
829
- slideToItemInner(index, doAnim)
830
- }
1002
+ slideToItemInner(index, doAnim);
1003
+ };
831
1004
 
832
1005
  const slideToDiv = (div, doAnim) => {
833
1006
  slideToDivInner(div, doAnim);
834
- }
1007
+ };
835
1008
  const slideToDivInner = (div, doAnim, direction = undefined) => {
836
1009
  if (div) {
837
1010
  taskManager.addTask(
@@ -841,97 +1014,139 @@ export const setup = (
841
1014
  doAnim,
842
1015
  direction,
843
1016
  },
844
- SlideTaskType.SLIDE_BY_DIV);
1017
+ SlideTaskType.SLIDE_BY_DIV
1018
+ );
845
1019
  }
846
- }
847
- const slideToRect = (rect, doAnim, direction = undefined) => {
848
- if (rect
849
- && typeof rect.left == 'number'
850
- && typeof rect.top == 'number'
851
- && typeof rect.width == 'number'
852
- && typeof rect.height == 'number') {
1020
+ };
1021
+ const slideToRectInner = (rect, doAnim, direction, force) => {
1022
+ if (
1023
+ rect &&
1024
+ typeof rect.left == "number" &&
1025
+ typeof rect.top == "number" &&
1026
+ typeof rect.width == "number" &&
1027
+ typeof rect.height == "number"
1028
+ ) {
853
1029
  taskManager.addTask(
854
1030
  TaskType.SLIDE,
855
1031
  {
856
1032
  rect,
857
1033
  doAnim,
858
1034
  direction,
1035
+ force,
859
1036
  },
860
- SlideTaskType.SLIDE_BY_RECT);
1037
+ SlideTaskType.SLIDE_BY_RECT
1038
+ );
861
1039
  }
862
- }
1040
+ };
1041
+ const slideToRect = (rect, doAnim, direction = undefined) => {
1042
+ slideToRectInner(rect, doAnim, direction, false);
1043
+ };
863
1044
 
864
1045
  function ifLayoutChange(type, oldMeasureItem, newMeasureItem) {
865
- let changed = newMeasureItem.width !== oldMeasureItem.width
866
- || newMeasureItem.height !== oldMeasureItem.height
867
- || newMeasureItem.focusable !== oldMeasureItem.focusable
868
- || newMeasureItem.marginRight !== oldMeasureItem.marginRight
869
- || newMeasureItem.marginBottom !== oldMeasureItem.marginBottom;
1046
+ let changed =
1047
+ newMeasureItem.width !== oldMeasureItem.width ||
1048
+ newMeasureItem.height !== oldMeasureItem.height ||
1049
+ newMeasureItem.focusable !== oldMeasureItem.focusable ||
1050
+ newMeasureItem.marginRight !== oldMeasureItem.marginRight ||
1051
+ newMeasureItem.marginBottom !== oldMeasureItem.marginBottom;
870
1052
  if (type !== "relative") {
871
- changed = changed
872
- || newMeasureItem.left !== oldMeasureItem.left
873
- || newMeasureItem.top !== oldMeasureItem.top
1053
+ changed =
1054
+ changed ||
1055
+ newMeasureItem.left !== oldMeasureItem.left ||
1056
+ newMeasureItem.top !== oldMeasureItem.top;
874
1057
  }
875
1058
  return changed;
876
1059
  }
877
1060
 
878
- const DATA_ID_KEY = "jsvKey";
879
- const refreshData = (forceUpdate) => {
1061
+ /**
1062
+ * 刷新数据
1063
+ * @param {boolean} forceUpdate 是否强制更新
1064
+ * @param {string} slideToFocus 是否滚动到焦点 "auto" 自动滚动到焦点 "enable" 滚动到焦点 "disable" 不滚动到焦点
1065
+ */
1066
+ const refreshData = (forceUpdate, slideToFocus = "auto") => {
880
1067
  //由于data不支持reactive, 因此数据的更新只通过provideData
881
1068
  if (!props.provideData) {
882
1069
  console.error("refreshData: provideData is null.");
883
1070
  return;
884
1071
  }
885
1072
  try {
886
- let newData = toRaw(props.provideData());
1073
+ let newData = toRaw(safeProvideData()).concat();
887
1074
  if (newData instanceof Array) {
888
1075
  let maxSameIndex = -1;
889
1076
  let layoutChange = false;
890
1077
  let onlyDataChangeList = [];
891
- if (focusId >= newData.length) {
892
- _changeFocusId(newData.length - 1, false)
893
- }
894
-
895
- if (!forceUpdate) {
896
- for (let i = 0; i < dataList.length; ++i) {
897
- let oldItem = dataList[i];
898
- let newItem = newData[i];
899
- if (newItem) {
900
- if (newItem === oldItem
901
- || (typeof newItem[DATA_ID_KEY] !== "undefined" && typeof oldItem[DATA_ID_KEY] !== "undefined" && newItem[DATA_ID_KEY] === oldItem[DATA_ID_KEY])) {
902
- //相同的item
903
- maxSameIndex = Math.max(maxSameIndex, i);
904
- } else {
905
- const newMeasureItem = props.measures(newItem);
906
- const oldMeasureItem = props.measures(oldItem);
907
- layoutChange = ifLayoutChange(props.layoutType, oldMeasureItem, newMeasureItem);
908
- if (layoutChange) {
909
- break;
1078
+ let targetFocusId = focusId;
1079
+ let curFocusItemChanged = true;
1080
+ if (newData.length == 0) {
1081
+ layoutChange = true;
1082
+ targetFocusId = -1;
1083
+ } else {
1084
+ if (focusId < 0) {
1085
+ targetFocusId = 0;
1086
+ } else if (focusId >= newData.length) {
1087
+ targetFocusId = newData.length - 1;
1088
+ }
1089
+ if (!forceUpdate) {
1090
+ const curFocusIndex = id2Index(focusId);
1091
+ for (let i = 0; i < dataList.length; ++i) {
1092
+ let oldItem = dataList[i];
1093
+ let newItem = newData[i];
1094
+ if (newItem) {
1095
+ if (
1096
+ ((typeof newItem[DATA_ID_KEY] == "undefined" ||
1097
+ typeof dataKeyList[i] == "undefined") &&
1098
+ newItem === oldItem) ||
1099
+ (typeof newItem[DATA_ID_KEY] !== "undefined" &&
1100
+ typeof dataKeyList[i] !== "undefined" &&
1101
+ newItem[DATA_ID_KEY] === dataKeyList[i])
1102
+ ) {
1103
+ //相同的item
1104
+ maxSameIndex = Math.max(maxSameIndex, i);
1105
+ if (curFocusIndex == i) {
1106
+ curFocusItemChanged = false;
1107
+ }
910
1108
  } else {
911
- if (i < innerData.length) {
912
- onlyDataChangeList.push({
913
- templateInfo: innerData[i].templateInfo,
914
- measureObj: newMeasureItem,
915
- data: newItem,
916
- index: i,
917
- });
1109
+ const newMeasureItem = props.measures(newItem);
1110
+ const oldMeasureItem = props.measures(oldItem);
1111
+ layoutChange = ifLayoutChange(
1112
+ props.layoutType,
1113
+ oldMeasureItem,
1114
+ newMeasureItem
1115
+ );
1116
+ if (layoutChange) {
1117
+ break;
1118
+ } else {
1119
+ if (i < innerData.length) {
1120
+ onlyDataChangeList.push({
1121
+ templateInfo: innerData[i].templateInfo,
1122
+ measureObj: newMeasureItem,
1123
+ data: newItem,
1124
+ index: i,
1125
+ });
1126
+ }
918
1127
  }
919
1128
  }
920
- }
921
- } else {
922
- if (i >= newData.length) {
923
- //item减少需要布局改变
924
- layoutChange = true;
925
- break;
926
1129
  } else {
927
- //数据中存在undefined item
928
- throw new Error("undefined item in data list.", i, newData);
1130
+ if (i >= newData.length) {
1131
+ //item减少需要布局改变
1132
+ layoutChange = true;
1133
+ break;
1134
+ } else {
1135
+ //数据中存在undefined item
1136
+ throw new Error("undefined item in data list.", i, newData);
1137
+ }
929
1138
  }
930
1139
  }
931
1140
  }
932
1141
  }
933
1142
 
934
- dataList = newData.concat();
1143
+ // 刷新数据时, 重置gazeIndex
1144
+ if (forceUpdate || curFocusItemChanged || targetFocusId != focusId) {
1145
+ gazeIndex = -1;
1146
+ }
1147
+ //更新template
1148
+ dataList = newData;
1149
+ dataKeyList = dataList.map((i) => i[DATA_ID_KEY]);
935
1150
  if (forceUpdate || layoutChange) {
936
1151
  //需要更新布局
937
1152
  pageUpdateToken.value++;
@@ -954,19 +1169,19 @@ export const setup = (
954
1169
  props.name,
955
1170
  _onTemplateAddDone
956
1171
  );
957
- if (props.onScroll) {
1172
+ if (props.onScroll || props.touchFlag > 0) {
958
1173
  templateItemAdder.tryAddItemByIndex(dataList.length - 1);
959
1174
  } else {
960
- templateItemAdder.tryAddItemById(focusId);
1175
+ templateItemAdder.tryAddItemById(targetFocusId);
961
1176
  }
962
1177
  } else {
963
- if (maxSameIndex < newData.length) {
1178
+ templateItemAdder.updateData(newData);
1179
+ if (maxSameIndex < newData.length - 1) {
964
1180
  //追加数据
965
- templateItemAdder.updateData(newData);
966
- if (props.onScroll) {
1181
+ if (props.onScroll || props.touchFlag > 0) {
967
1182
  templateItemAdder.tryAddItemByIndex(dataList.length - 1);
968
1183
  } else {
969
- templateItemAdder.tryAddItemById(focusId);
1184
+ templateItemAdder.tryAddItemById(targetFocusId);
970
1185
  }
971
1186
  }
972
1187
 
@@ -974,7 +1189,10 @@ export const setup = (
974
1189
  if (onlyDataChangeList.length > 0) {
975
1190
  for (let i of onlyDataChangeList) {
976
1191
  if (i.index < innerData.length) {
977
- innerData[i.index].updateCustomData(i.data, _getItemConfigFromMeasursObj(i.measureObj));
1192
+ innerData[i.index].updateCustomData(
1193
+ i.data,
1194
+ _getItemConfigFromMeasursObj(i.measureObj)
1195
+ );
978
1196
  innerData[i.index].enableTap = i.measureObj.enableTap ?? false;
979
1197
  } else {
980
1198
  //之后的数据未布局, 尚未添加到innerData中
@@ -983,7 +1201,7 @@ export const setup = (
983
1201
  }
984
1202
  }
985
1203
  }
986
-
1204
+ //更新可视
987
1205
  const updater = pageUpdater.update(
988
1206
  metroTemplate,
989
1207
  visibleInfo.startWithPadding - innerKeepTraceRange * pageRange,
@@ -993,18 +1211,71 @@ export const setup = (
993
1211
  permanentItemList
994
1212
  );
995
1213
  updater.apply();
996
- onItemFocus(getItemById(focusId), null);
997
- let targetRect = mRectCache.getCurRect() ?? mRectCache.getPreRect();
998
- if (targetRect) {
999
- slideToRect(targetRect, false);
1214
+
1215
+ //其他处理
1216
+ if (mode.getMode() == TOUCH_MODE) {
1217
+ //TODO touch模式的refresh还是有问题,
1218
+ // 1. 点击删除item, 会触发onDragStart, 这里onDragStart正好更新了visibleInfo.start导致可以运行, 但这里还是要正确更新visibleInfo.start
1219
+ // let divPos = vertical ? slideDivTop.value + freeMoveSlideGapTop : slideDivLeft.value + freeMoveSlideGapLeft;
1220
+ // visibleInfo.start = getVisibleStart(data);
1000
1221
  } else {
1001
- slideToItem(id2Index(focusId), false);
1222
+ //非触控模式的更新处理
1223
+ //记录刷新前焦点的可视状态, 若焦点可视, 则刷新后也需要保证焦点的可视
1224
+ let needSlide = false;
1225
+ let targetRect = mRectCache.getCurRect() ?? mRectCache.getPreRect();
1226
+ if (targetFocusId != focusId) {
1227
+ needSlide = true;
1228
+ } else if (slideToFocus == "enable") {
1229
+ needSlide = true;
1230
+ } else if (slideToFocus == "disable") {
1231
+ needSlide = false;
1232
+ } else {
1233
+ if (targetRect) {
1234
+ needSlide = rectVisibleState(targetRect) !== 0;
1235
+ } else {
1236
+ needSlide =
1237
+ rectVisibleState(getItemById(focusId)?.templateInfo) !== 0;
1238
+ }
1239
+ }
1240
+ if (targetFocusId != focusId) {
1241
+ //由于template add done 回调里会更新box, 需要在template重新创建前, 重置所有的滚动信息
1242
+ visibleInfo = visibleInfo.copy();
1243
+ visibleInfo.start = 0;
1244
+ visibleInfo._startMax = 0;
1245
+ slideDivLeft.value = 0;
1246
+ slideDivTop.value = 0;
1247
+ }
1248
+
1249
+ if (targetFocusId != focusId) {
1250
+ //重置所有的滚动信息
1251
+ _changeFocusId(targetFocusId, false);
1252
+ }
1253
+
1254
+ const focusItem = getItemById(focusId);
1255
+ if (focusItem) {
1256
+ //数据刷新时, 重置preEdgeRect, 否则再嵌套模式下, 会使用上一次的preEdgeRect, 导致子又findNearestByRect
1257
+ preEdgeRect = null;
1258
+ onItemFocus(focusItem, null);
1259
+ if (needSlide) {
1260
+ if (targetRect) {
1261
+ slideToRectInner(targetRect, false, 0, true);
1262
+ } else if (
1263
+ focusItem.itemConfig.itemSlide ==
1264
+ METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS
1265
+ ) {
1266
+ //只有这个item是控制滚动的才slide, 其他如嵌套时不需要slide
1267
+ slideToItemInner(id2Index(focusId), false, 0, 0, true);
1268
+ }
1269
+ }
1270
+ } else {
1271
+ slideToInner(0, false);
1272
+ preEdgeRect = null;
1273
+ mRectCache.clean();
1274
+ }
1002
1275
  }
1003
- //template和slideDivStyle均确定后再次重设box condition
1004
- updateTouchBoxCondition();
1005
1276
  }
1006
1277
  } catch (e) {
1007
- console.log(TAG, "refresh error", e)
1278
+ console.log(TAG, "refresh error", e);
1008
1279
  }
1009
1280
  };
1010
1281
 
@@ -1022,16 +1293,34 @@ export const setup = (
1022
1293
  };
1023
1294
 
1024
1295
  const moveFocus = (direction) => {
1025
- if (innerData.length <= 0) { return; }
1296
+ if (innerData.length <= 0) {
1297
+ return;
1298
+ }
1026
1299
  //有外部触发的滚动时, 取消load
1027
1300
  tryCancelDelayLoad();
1028
- if (direction == "left" || direction == 37 || direction == EdgeDirection.left) {
1301
+ if (
1302
+ direction == "left" ||
1303
+ direction == 37 ||
1304
+ direction == EdgeDirection.left
1305
+ ) {
1029
1306
  _moveToNext(-1, 0);
1030
- } else if (direction == "right" || direction == 39 || direction == EdgeDirection.right) {
1307
+ } else if (
1308
+ direction == "right" ||
1309
+ direction == 39 ||
1310
+ direction == EdgeDirection.right
1311
+ ) {
1031
1312
  _moveToNext(1, 0);
1032
- } else if (direction == "top" || direction == 38 || direction == EdgeDirection.top) {
1313
+ } else if (
1314
+ direction == "top" ||
1315
+ direction == 38 ||
1316
+ direction == EdgeDirection.top
1317
+ ) {
1033
1318
  _moveToNext(0, -1);
1034
- } else if (direction == "bottom" || direction == 40 || direction == EdgeDirection.bottom) {
1319
+ } else if (
1320
+ direction == "bottom" ||
1321
+ direction == 40 ||
1322
+ direction == EdgeDirection.bottom
1323
+ ) {
1035
1324
  _moveToNext(0, 1);
1036
1325
  } else {
1037
1326
  console.error(TAG, "moveFocus direction is invalid.", direction);
@@ -1040,23 +1329,23 @@ export const setup = (
1040
1329
 
1041
1330
  const getCustomerDataSize = () => {
1042
1331
  return dataList.length;
1043
- }
1332
+ };
1044
1333
 
1045
1334
  const getCurrentFocusIndex = () => {
1046
1335
  return id2Index(focusId);
1047
- }
1336
+ };
1048
1337
 
1049
1338
  const getTemplatePosition = (index) => {
1050
1339
  return _getTemplatePosition(index);
1051
- }
1340
+ };
1052
1341
 
1053
1342
  const lockSlide = () => {
1054
1343
  slideLock = true;
1055
- }
1344
+ };
1056
1345
 
1057
1346
  const unlockSlide = () => {
1058
1347
  slideLock = false;
1059
- }
1348
+ };
1060
1349
 
1061
1350
  const setSlideSetting = (setting) => {
1062
1351
  if (!setting) {
@@ -1064,14 +1353,14 @@ export const setup = (
1064
1353
  } else {
1065
1354
  innerSlideSetting = setting;
1066
1355
  }
1067
- }
1356
+ };
1068
1357
 
1069
1358
  const tryCancelDelayLoad = () => {
1070
1359
  if (delayLoadHandler > 0) {
1071
1360
  clearTimeout(delayLoadHandler);
1072
1361
  delayLoadHandler = -1;
1073
1362
  }
1074
- }
1363
+ };
1075
1364
 
1076
1365
  const exportObject = {
1077
1366
  lockSlide,
@@ -1096,6 +1385,7 @@ export const setup = (
1096
1385
  setSlideSetting,
1097
1386
  cancelDelayLoad: tryCancelDelayLoad,
1098
1387
  setSensorSensitivity,
1388
+ getItemLayoutInfo: _getTemplatePosition,
1099
1389
  };
1100
1390
 
1101
1391
  const _calculateNearestItemByRect = (visibleSet, enter_rect_info) => {
@@ -1146,16 +1436,14 @@ export const setup = (
1146
1436
  let full_show =
1147
1437
  itemTemplateInfo[key_pos] >= visibleInfo.start &&
1148
1438
  itemTemplateInfo[key_pos] + itemTemplateInfo[key_width] - 1 <=
1149
- visibleInfo.end;
1439
+ visibleInfo.end;
1150
1440
  if (full_show) {
1151
- let x_pos =
1152
- vertical
1153
- ? itemTemplateInfo.left
1154
- : itemTemplateInfo.left - visibleInfo.start;
1155
- let y_pos =
1156
- vertical
1157
- ? itemTemplateInfo.top - visibleInfo.start
1158
- : itemTemplateInfo.top;
1441
+ let x_pos = vertical
1442
+ ? itemTemplateInfo.left
1443
+ : itemTemplateInfo.left - visibleInfo.start;
1444
+ let y_pos = vertical
1445
+ ? itemTemplateInfo.top - visibleInfo.start
1446
+ : itemTemplateInfo.top;
1159
1447
  var target_x_range = new SingleRangeModel(
1160
1448
  x_pos,
1161
1449
  x_pos + itemTemplateInfo.width - 1
@@ -1295,62 +1583,112 @@ export const setup = (
1295
1583
 
1296
1584
  const onDispatchKeyDown = (ev) => {
1297
1585
  if (mode.getMode() == TOUCH_MODE && !mode.duringTouch()) {
1298
- if (ev.keyCode == 37 || ev.keyCode == 38 || ev.keyCode == 39 || ev.keyCode == 40) {
1586
+ if (
1587
+ ev.keyCode == 37 ||
1588
+ ev.keyCode == 38 ||
1589
+ ev.keyCode == 39 ||
1590
+ ev.keyCode == 40
1591
+ ) {
1299
1592
  //只有在上下左右键切换为focus_mode
1300
1593
  mode.keyDown();
1301
1594
  //touch切换为focus的首次按键只显示焦点
1302
1595
  const focusItem = _getVisibleFocusableItem();
1303
- const preFocusItem = getItemById(focusId);
1304
- _changeFocusId(focusItem.id, false);
1305
- if (preFocusItem.id !== focusItem.id) {
1306
- onItemBlur(preFocusItem);
1596
+ if (focusItem) {
1597
+ const preFocusItem = getItemById(focusId);
1598
+ _changeFocusId(focusItem.id, false);
1599
+ if (preFocusItem.id !== focusItem.id) {
1600
+ onItemBlur(preFocusItem);
1601
+ }
1602
+ onItemFocus(focusItem);
1307
1603
  }
1308
- onItemFocus(focusItem);
1309
- }
1310
- }
1311
- return false;
1312
- }
1313
-
1314
- const focusBlockOnKeyDown = (ev) => {
1315
- if (onKeyDownLock) {
1316
- return true;
1317
- }
1318
- tryCancelDelayLoad();
1319
- if (mode.getMode() == TOUCH_MODE) {
1320
- if (mode.duringTouch()) {
1321
- //touch过程中的按键不处理
1322
1604
  return true;
1323
1605
  }
1324
1606
  }
1607
+ return false;
1608
+ };
1325
1609
 
1326
- switch (ev.keyCode) {
1610
+ const _moveByKey = (keyCode) => {
1611
+ switch (keyCode) {
1327
1612
  case 37:
1328
1613
  _moveToNext(-1, 0);
1329
- break;
1614
+ return true;
1330
1615
  case 38:
1331
1616
  _moveToNext(0, -1);
1332
- break;
1617
+ return true;
1333
1618
  case 39:
1334
1619
  _moveToNext(1, 0);
1335
- break;
1620
+ return true;
1336
1621
  case 40:
1337
1622
  _moveToNext(0, 1);
1338
- break;
1339
- case 13:
1340
- onItemClick(getItemById(focusId));
1341
- break;
1623
+ return true;
1342
1624
  default:
1343
- //只接受上下左右确定键
1344
1625
  return false;
1345
1626
  }
1346
- return true;
1347
1627
  };
1348
1628
 
1349
- const randomColor = () => {
1350
- let randomColor = Math.round(Math.random() * 2 ** 24).toString(16);
1351
- return (
1352
- "#" + new Array(6 - randomColor.length).fill("0").join("") + randomColor + "77"
1353
- );
1629
+ let clickDownReceived = false;
1630
+ let longPressTriggered = false;
1631
+
1632
+ const focusBlockOnKeyUp = (ev) => {
1633
+ const curFocusItem = getItemById(focusId);
1634
+ if (!curFocusItem || !curFocusItem.itemConfig.enableLongPress) {
1635
+ return false;
1636
+ }
1637
+ //支持长按时 onClick 由 keyup 处理
1638
+ //longpress触发时, 不触发onClick
1639
+ //没有keydown, 只有keyup时, 不处理keyup
1640
+ if (!longPressTriggered) {
1641
+ if (ev.keyCode == 13 && clickDownReceived) {
1642
+ clickDownReceived = false;
1643
+ onItemClick(curFocusItem);
1644
+ return true;
1645
+ }
1646
+ } else {
1647
+ longPressTriggered = false;
1648
+ }
1649
+ return false;
1650
+ };
1651
+
1652
+ let preStartKeyDownTime = -1;
1653
+ const focusBlockOnKeyDown = (ev) => {
1654
+ if (onKeyDownLock) {
1655
+ return true;
1656
+ }
1657
+ if (!ev.repeat) {
1658
+ longPressTriggered = false;
1659
+ preStartKeyDownTime = ev.timeStamp;
1660
+ }
1661
+ tryCancelDelayLoad();
1662
+ if (mode.getMode() == TOUCH_MODE) {
1663
+ if (mode.duringTouch()) {
1664
+ //touch过程中的按键不处理
1665
+ return true;
1666
+ }
1667
+ }
1668
+
1669
+ if (_moveByKey(ev.keyCode)) {
1670
+ return true;
1671
+ }
1672
+ if (ev.keyCode == 13) {
1673
+ const curFocusItem = getItemById(focusId);
1674
+ clickDownReceived = true;
1675
+ if (curFocusItem.itemConfig.enableLongPress) {
1676
+ if (
1677
+ ev.repeat &&
1678
+ ev.timeStamp - preStartKeyDownTime > LONGPRESS_TIMEOUT &&
1679
+ !longPressTriggered
1680
+ ) {
1681
+ longPressTriggered = true;
1682
+ onItemLongPress(curFocusItem);
1683
+ }
1684
+ } else if (!ev.repeat) {
1685
+ onItemClick(curFocusItem);
1686
+ }
1687
+ return true;
1688
+ } else {
1689
+ clickDownReceived = false;
1690
+ }
1691
+ return false;
1354
1692
  };
1355
1693
 
1356
1694
  function updateTouchDivSize() {
@@ -1360,7 +1698,8 @@ export const setup = (
1360
1698
  if (lastTemplateInfo) {
1361
1699
  if (vertical) {
1362
1700
  touchDivSize.width = props.width;
1363
- touchDivSize.height = lastTemplateInfo.top + lastTemplateInfo.height - 1;
1701
+ touchDivSize.height =
1702
+ lastTemplateInfo.top + lastTemplateInfo.height - 1;
1364
1703
  } else {
1365
1704
  touchDivSize.width = lastTemplateInfo.left + lastTemplateInfo.width - 1;
1366
1705
  touchDivSize.height = props.height;
@@ -1376,7 +1715,7 @@ export const setup = (
1376
1715
  if (preTouchW !== touchDivSize.width || preTouchH !== touchDivSize.height) {
1377
1716
  updateTouchBoxCondition();
1378
1717
  }
1379
- }
1718
+ };
1380
1719
 
1381
1720
  const _getItemConfigFromMeasursObj = (measuresObj) => {
1382
1721
  let focusZIndex = -1,
@@ -1401,10 +1740,12 @@ export const setup = (
1401
1740
  focusZIndex,
1402
1741
  normalZIndex,
1403
1742
  permanent: measuresObj.permanent ?? false,
1404
- itemSlide: measuresObj.itemSlide ?? METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS,
1743
+ itemSlide:
1744
+ measuresObj.itemSlide ?? METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS,
1405
1745
  showSkeleton: measuresObj.showSkeleton ?? true,
1746
+ enableLongPress: measuresObj.enableLongPress ?? props.enableLongPress,
1406
1747
  };
1407
- }
1748
+ };
1408
1749
 
1409
1750
  const _onTemplateItemAdd = (customerData, templateItem, measuresObj) => {
1410
1751
  let itemConfig = _getItemConfigFromMeasursObj(measuresObj);
@@ -1440,10 +1781,31 @@ export const setup = (
1440
1781
  slideTo: slideTo,
1441
1782
  updateItemSize,
1442
1783
  widgetHandler: exportObject,
1784
+ },
1785
+ {
1786
+ onTap: onItemTap,
1443
1787
  }
1444
1788
  );
1445
1789
  item.enableTap = measuresObj.enableTap ?? false;
1446
-
1790
+ // 占位图布局
1791
+ if (props.enableItemRenderBreak) {
1792
+ if (measuresObj.placeHolderLayout
1793
+ && typeof measuresObj.placeHolderLayout.left == "number"
1794
+ && typeof measuresObj.placeHolderLayout.top == "number"
1795
+ && typeof measuresObj.placeHolderLayout.width == "number"
1796
+ && typeof measuresObj.placeHolderLayout.height == "number"
1797
+ ) {
1798
+ item.placeHolderLayout = Object.assign({}, measuresObj.placeHolderLayout);
1799
+ } else {
1800
+ item.placeHolderLayout = {
1801
+ left: 0,
1802
+ top: 0,
1803
+ width: item.renderStyle.width - (props.placeHolderSetting.gap ?? 0),
1804
+ height: item.renderStyle.height - (props.placeHolderSetting.gap ?? 0)
1805
+ }
1806
+ }
1807
+ }
1808
+
1447
1809
  innerData.push(item);
1448
1810
  if (item.itemConfig.permanent) {
1449
1811
  permanentItemList.push({
@@ -1474,7 +1836,10 @@ export const setup = (
1474
1836
  return false;
1475
1837
  }
1476
1838
  const focusItem = getItemById(focusId);
1477
- if (focusItem.itemConfig.itemSlide !== METRO_WIDGET_CONST.ITEM_SLIDE.ACT_FOCUS_RECT_EVENT) {
1839
+ if (
1840
+ focusItem.itemConfig.itemSlide !==
1841
+ METRO_WIDGET_CONST.ITEM_SLIDE.ACT_FOCUS_RECT_EVENT
1842
+ ) {
1478
1843
  return;
1479
1844
  }
1480
1845
  let item_div = ev.element;
@@ -1492,7 +1857,9 @@ export const setup = (
1492
1857
  direction = 1;
1493
1858
  }
1494
1859
  }
1495
- const item_layout = item_div.jsvGetRelativePosition(toRaw(locateDiv.value));
1860
+ const item_layout = item_div.jsvGetRelativePosition(
1861
+ toRaw(locateDiv.value)
1862
+ );
1496
1863
 
1497
1864
  let fakeItem = {
1498
1865
  templateInfo: {
@@ -1506,14 +1873,18 @@ export const setup = (
1506
1873
  },
1507
1874
  };
1508
1875
 
1509
- let cur_slide = _calculateVisibleStart(fakeItem.templateInfo, direction, fakeItem.templateInfo, visibleInfo);
1876
+ let cur_slide = _calculateVisibleStart(
1877
+ fakeItem.templateInfo,
1878
+ direction,
1879
+ fakeItem.templateInfo,
1880
+ visibleInfo
1881
+ );
1510
1882
  if (cur_slide != visibleInfo.start) {
1511
- slideToInner(
1512
- cur_slide,
1513
- true,
1514
- {
1515
- mergeTmp: true
1516
- });
1883
+ slideToInner(cur_slide, true, {
1884
+ //250207 change: 为true时, 会导致不可见的item反复加载,释放, 所以改为false
1885
+ //但之前设为true应该是为了保证滚动时的楼层不提前消失, 此后若再遇到这类问题再考虑
1886
+ mergeTmp: false,
1887
+ });
1517
1888
  return true;
1518
1889
  }
1519
1890
  }
@@ -1522,10 +1893,14 @@ export const setup = (
1522
1893
 
1523
1894
  const _changeFocusId = (id, cache_pre = true) => {
1524
1895
  preFocusId = cache_pre ? focusId : -1;
1525
- focusId = id >= 0 && id < metroTemplate.size ? id : 0;
1526
- currentFocusIndex.value = id2Index(id);
1896
+ if (metroTemplate.size == 0) {
1897
+ focusId = -1;
1898
+ } else {
1899
+ focusId = id >= 0 && id < metroTemplate.size ? id : 0;
1900
+ }
1901
+ currentFocusIndex.value = id2Index(focusId);
1527
1902
  taskManager.addTask(TaskType.ON_FOCUS_CHANGE);
1528
- }
1903
+ };
1529
1904
 
1530
1905
  const _bubbleCustomEvent = (event) => {
1531
1906
  if (props.sendFocusRectEvent && event) {
@@ -1579,8 +1954,10 @@ export const setup = (
1579
1954
  templateItemAdder.tryAddItem(next_focus_item.templateInfo, 1);
1580
1955
 
1581
1956
  // itemFocus 和 itemBlur放在计算visibleStart之前, 以便用户更改template后在计算滚动
1582
- let x_off_set = preFocusItem.templateInfo.left - next_focus_item.templateInfo.left;
1583
- let y_off_set = preFocusItem.templateInfo.top - next_focus_item.templateInfo.top;
1957
+ let x_off_set =
1958
+ preFocusItem.templateInfo.left - next_focus_item.templateInfo.left;
1959
+ let y_off_set =
1960
+ preFocusItem.templateInfo.top - next_focus_item.templateInfo.top;
1584
1961
  if (item_edge_rect && item_edge_rect.rect) {
1585
1962
  item_edge_rect.rect.x += x_off_set;
1586
1963
  item_edge_rect.rect.y += y_off_set;
@@ -1609,12 +1986,16 @@ export const setup = (
1609
1986
  onItemBlur(preFocusItem);
1610
1987
  onItemFocus(next_focus_item, preEdgeRect);
1611
1988
 
1612
- if (next_focus_item.itemConfig.itemSlide == METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS) {
1989
+ if (
1990
+ next_focus_item.itemConfig.itemSlide ==
1991
+ METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS
1992
+ ) {
1613
1993
  slideToItemInner(
1614
1994
  next_focus_item.index,
1615
1995
  true,
1616
1996
  vertical ? vertical_direction : horizontal_direction,
1617
- preFocusItem);
1997
+ preFocusItem
1998
+ );
1618
1999
  } else {
1619
2000
  const updater = pageUpdater.update(
1620
2001
  metroTemplate,
@@ -1645,7 +2026,7 @@ export const setup = (
1645
2026
  edge = EdgeDirection.top;
1646
2027
  }
1647
2028
  const curTemplateInfo = getItemById(focusId)?.templateInfo;
1648
- let rect
2029
+ let rect;
1649
2030
  if (curTemplateInfo) {
1650
2031
  rect = {
1651
2032
  x: curTemplateInfo.left - x_off_set,
@@ -1665,7 +2046,7 @@ export const setup = (
1665
2046
  props.onEdge?.({
1666
2047
  direction: edge,
1667
2048
  rect: rect,
1668
- childEdgeInfo: item_edge_rect
2049
+ childEdgeInfo: item_edge_rect,
1669
2050
  });
1670
2051
  innerData[id2Index(focusId)]?.onWidgetEdge({
1671
2052
  direction: edge,
@@ -1682,15 +2063,6 @@ export const setup = (
1682
2063
  if ((innerSlideSetting.BoundaryProtect & SlideSetting.START_PROTECT) > 0) {
1683
2064
  if (vInfo.start >= 0) {
1684
2065
  let boundary = 0;
1685
- const headTemplateInfo = getItemByIndex(0).templateInfo;
1686
- if (
1687
- targetRect
1688
- && (index == headTemplateInfo.index)
1689
- && targetRect[pos_key] + targetRect[size_key] <=
1690
- vInfo.range
1691
- ) {
1692
- boundary = headTemplateInfo[size_key];
1693
- }
1694
2066
  visibleStart = visibleStart < boundary ? 0 : visibleStart;
1695
2067
  } else {
1696
2068
  // 以最后一个item的位置作为动态的保护边界
@@ -1698,30 +2070,32 @@ export const setup = (
1698
2070
  }
1699
2071
  }
1700
2072
  if ((innerSlideSetting.BoundaryProtect & SlideSetting.END_PROTECT) > 0) {
1701
- let lastTemplateInfo = getItemByIndex(metroTemplate.getTailItemIndex()).templateInfo;
2073
+ let lastTemplateInfo = getItemByIndex(
2074
+ metroTemplate.getTailItemIndex()
2075
+ ).templateInfo;
1702
2076
  const lastEnd = lastTemplateInfo[pos_key] + lastTemplateInfo[size_key];
1703
2077
  const lastVisibleStart = Math.max(lastEnd - vInfo.range, 0);
1704
2078
  //边界必须大于等于0, 同时若最后一个缩进时, 边界采用最后一个item的位置
1705
2079
  if (vInfo.end <= lastEnd) {
1706
2080
  let boundary = lastVisibleStart;
1707
- if (
1708
- targetRect
1709
- && (index == lastTemplateInfo.index)
1710
- && targetRect[pos_key] - lastVisibleStart >= 0
1711
- ) {
1712
- boundary = lastTemplateInfo[pos_key] - vInfo.range;
1713
- }
1714
- visibleStart = visibleStart > boundary ? lastVisibleStart : visibleStart;
2081
+ visibleStart =
2082
+ visibleStart > boundary ? lastVisibleStart : visibleStart;
1715
2083
  } else {
1716
2084
  // 以最后一个item的位置作为动态的保护边界
1717
2085
  visibleStart = visibleStart > vInfo.start ? vInfo.start : visibleStart;
1718
2086
  }
1719
2087
  }
1720
2088
  return visibleStart;
1721
- }
2089
+ };
1722
2090
 
1723
2091
  const mRectCache = new RectCache();
1724
- const _calculateVisibleStart = (targetRect, _direction, templateInfo, vInfo, preInfo = null) => {
2092
+ const _calculateVisibleStart = (
2093
+ targetRect,
2094
+ _direction,
2095
+ templateInfo,
2096
+ vInfo,
2097
+ preInfo = null
2098
+ ) => {
1725
2099
  if (!targetRect) {
1726
2100
  console.error("MetroWidget: _calculateVisibleStart target item is null");
1727
2101
  return 0;
@@ -1732,7 +2106,7 @@ export const setup = (
1732
2106
  width: targetRect.width,
1733
2107
  height: targetRect.height,
1734
2108
  frameCount: Forge.sFrameCount.count,
1735
- }
2109
+ };
1736
2110
  mRectCache.cache(curRect);
1737
2111
  let preRect = mRectCache.getPreRect();
1738
2112
  if (preInfo) {
@@ -1766,9 +2140,14 @@ export const setup = (
1766
2140
  }
1767
2141
 
1768
2142
  if (needCalculate) {
2143
+ let target = targetRect[pos_key] + targetRect[size_key] / 2;
2144
+ if (innerSlideSetting.Align == "start") {
2145
+ target = targetRect[pos_key];
2146
+ } else if (innerSlideSetting.Align == "end") {
2147
+ target = targetRect[pos_key] + targetRect[size_key];
2148
+ }
1769
2149
  new_visible_start = Math.ceil(
1770
- targetRect[pos_key] + targetRect[size_key] / 2 -
1771
- vInfo.range * innerSlideSetting.FixPercent
2150
+ target - vInfo.range * innerSlideSetting.FixPercent
1772
2151
  );
1773
2152
  }
1774
2153
  break;
@@ -1806,14 +2185,19 @@ export const setup = (
1806
2185
 
1807
2186
  if (preRect) {
1808
2187
  const rect0Start = vInfo.start;
1809
- const rect0End = vInfo.start + vInfo.range * innerSlideSetting.StartPercent;
1810
- const rect0Range = rect0End - rect0Start + 1
1811
- const rect1Start = vInfo.start + vInfo.range * innerSlideSetting.EndPercent;
2188
+ const rect0End =
2189
+ vInfo.start + vInfo.range * innerSlideSetting.StartPercent;
2190
+ const rect0Range = rect0End - rect0Start + 1;
2191
+ const rect1Start =
2192
+ vInfo.start + vInfo.range * innerSlideSetting.EndPercent;
1812
2193
  const rect1End = vInfo.start + vInfo.range - 1;
1813
2194
  const rect1Range = rect1End - rect1Start + 1;
1814
2195
 
1815
2196
  let target0 = Math.min(preRect[pos_key], rect0End);
1816
- let target1 = Math.max(preRect[pos_key] + preRect[size_key] - 1, rect1Start);
2197
+ let target1 = Math.max(
2198
+ preRect[pos_key] + preRect[size_key] - 1,
2199
+ rect1Start
2200
+ );
1817
2201
 
1818
2202
  let rect0Result = undefined;
1819
2203
  let rect1Result = undefined;
@@ -1826,7 +2210,7 @@ export const setup = (
1826
2210
  } else {
1827
2211
  if (direction <= 0) {
1828
2212
  //inRect0, 只处理往左/往上
1829
- rect0Result = vInfo.start + (itemStart - target0)
2213
+ rect0Result = vInfo.start + (itemStart - target0);
1830
2214
  }
1831
2215
  }
1832
2216
  }
@@ -1844,7 +2228,10 @@ export const setup = (
1844
2228
  }
1845
2229
  }
1846
2230
 
1847
- if (typeof rect0Result !== "undefined" && typeof rect1Result !== "undefined") {
2231
+ if (
2232
+ typeof rect0Result !== "undefined" &&
2233
+ typeof rect1Result !== "undefined"
2234
+ ) {
1848
2235
  //重叠区域
1849
2236
  new_visible_start = rect0Result;
1850
2237
  } else if (typeof rect0Result !== "undefined") {
@@ -1859,11 +2246,16 @@ export const setup = (
1859
2246
  const tailSafeArea = innerSlideSetting.TailSafeArea * vInfo.range;
1860
2247
  if (itemMainSize > vInfo.range - headSafeArea - tailSafeArea) {
1861
2248
  // 大item
1862
- new_visible_start = Math.round(itemStart - (vInfo.range - itemMainSize) / 2)
2249
+ new_visible_start = Math.round(
2250
+ itemStart - (vInfo.range - itemMainSize) / 2
2251
+ );
1863
2252
  } else {
1864
2253
  if (itemStart < new_visible_start + headSafeArea) {
1865
2254
  new_visible_start = itemStart - headSafeArea;
1866
- } else if (itemEnd > new_visible_start + vInfo.range - 1 - tailSafeArea) {
2255
+ } else if (
2256
+ itemEnd >
2257
+ new_visible_start + vInfo.range - 1 - tailSafeArea
2258
+ ) {
1867
2259
  new_visible_start = itemEnd - vInfo.range + tailSafeArea;
1868
2260
  }
1869
2261
  }
@@ -1876,7 +2268,12 @@ export const setup = (
1876
2268
  );
1877
2269
  }
1878
2270
 
1879
- new_visible_start = normalizeVisibleStart(new_visible_start, targetRect, templateInfo?.index, vInfo);
2271
+ new_visible_start = normalizeVisibleStart(
2272
+ new_visible_start,
2273
+ targetRect,
2274
+ templateInfo?.index,
2275
+ vInfo
2276
+ );
1880
2277
  return Math.round(new_visible_start);
1881
2278
  };
1882
2279
 
@@ -1913,12 +2310,13 @@ export const setup = (
1913
2310
  return;
1914
2311
  }
1915
2312
 
1916
- let focus_id =
2313
+ let focus_id = index2Id(gazeIndex);
2314
+ focus_id =
1917
2315
  typeof enterFocusId !== "undefined" &&
1918
- enterFocusId >= 0 &&
1919
- enterFocusId < metroTemplate.size
2316
+ enterFocusId >= 0 &&
2317
+ enterFocusId < metroTemplate.size
1920
2318
  ? enterFocusId
1921
- : focusId;
2319
+ : focus_id;
1922
2320
  focus_id = _ifValidEnterRect(enterFocusRect)
1923
2321
  ? _calculateNearestItemByRect(pageUpdater.getRange(), enterFocusRect)
1924
2322
  : focus_id;
@@ -1926,7 +2324,7 @@ export const setup = (
1926
2324
  _changeFocusId(focus_id, false);
1927
2325
  enterFocusId = -1;
1928
2326
  enterFocusRect = null;
1929
- alreadyCallItemFocus = onItemFocus(getItemById(focusId), preEdgeRect);
2327
+ firstOnItemFocusCalled = onItemFocus(getItemById(focusId), preEdgeRect);
1930
2328
  props.onFocus?.();
1931
2329
  };
1932
2330
 
@@ -1938,19 +2336,21 @@ export const setup = (
1938
2336
  onItemBlur(getItemById(preFocusId));
1939
2337
  props.onBlur?.();
1940
2338
  isFocus = false;
1941
- mRectCache.clean()
2339
+ mRectCache.clean();
1942
2340
  };
1943
2341
 
1944
2342
  const _updatePage = (rangeSet) => {
1945
2343
  let cur = id2Index(focusId);
1946
2344
  if (cur >= 0) {
1947
- rangeSet.add(cur)
2345
+ rangeSet.add(cur);
1948
2346
  }
1949
2347
  const tmpArray = Array.from(rangeSet);
1950
2348
  let newArray = tmpArray.map((item) => {
1951
2349
  return getItemByIndex(item);
1952
2350
  });
1953
- const newItemList = newArray.filter((i) => { return !renderData.value?.includes(i) });
2351
+ const newItemList = newArray.filter((i) => {
2352
+ return !renderData.value?.includes(i);
2353
+ });
1954
2354
  renderData.value = newArray;
1955
2355
  if (props.enableItemRenderBreak) {
1956
2356
  itemRender.value = false;
@@ -1966,18 +2366,25 @@ export const setup = (
1966
2366
  };
1967
2367
 
1968
2368
  const _getVisibleFocusableItem = () => {
1969
- const focusItem = getItemById(focusId);
1970
- if (isItemVisible(focusItem)) {
2369
+ let item = getItemByIndex(gazeIndex);
2370
+ if (rectVisibleState(item.templateInfo) == 2) {
2371
+ return item;
2372
+ }
2373
+ item = getItemById(focusId);
2374
+ if (rectVisibleState(focusItem.templateInfo) == 2) {
1971
2375
  return focusItem;
1972
- } else {
1973
- //遍历renderList, 找到第一个可见的 focusable item
1974
- for (let item of renderData.value) {
1975
- if (item.templateInfo.focusable && isItemVisible(item)) {
1976
- return item;
1977
- }
2376
+ }
2377
+ //遍历renderList, 找到第一个可见的 focusable item
2378
+ for (let item of renderData.value) {
2379
+ if (
2380
+ item.templateInfo.focusable &&
2381
+ rectVisibleState(item.templateInfo) == 2
2382
+ ) {
2383
+ return item;
1978
2384
  }
1979
2385
  }
1980
- }
2386
+ return null;
2387
+ };
1981
2388
 
1982
2389
  const _onScroll = () => {
1983
2390
  if (props.onScroll) {
@@ -2009,13 +2416,15 @@ export const setup = (
2009
2416
  let onMoveSensitivity = -1;
2010
2417
 
2011
2418
  const getVisibleStart = (moveInfo) => {
2012
- divPos = vertical ? slideDivTop.value + freeMoveSlideGapTop : slideDivLeft.value + freeMoveSlideGapLeft;
2419
+ divPos = vertical
2420
+ ? slideDivTop.value + freeMoveSlideGapTop
2421
+ : slideDivLeft.value + freeMoveSlideGapLeft;
2013
2422
  if (vertical) {
2014
2423
  return -(divPos + Math.round(moveInfo.yPos));
2015
2424
  } else {
2016
2425
  return -(divPos + Math.round(moveInfo.xPos));
2017
2426
  }
2018
- }
2427
+ };
2019
2428
 
2020
2429
  function onSensor(pos) {
2021
2430
  const lastTemplateInfo = getItemByIndex(
@@ -2030,7 +2439,9 @@ export const setup = (
2030
2439
  }
2031
2440
  }
2032
2441
  props.onScroll?.(
2033
- vertical ? -(pos.yPos + slideDivTop.value + freeMoveSlideGapTop) : -(pos.xPos + slideDivLeft.value + freeMoveSlideGapLeft),
2442
+ vertical
2443
+ ? -(pos.yPos + slideDivTop.value + freeMoveSlideGapTop)
2444
+ : -(pos.xPos + slideDivLeft.value + freeMoveSlideGapLeft),
2034
2445
  visibleInfo.range,
2035
2446
  totalWidth
2036
2447
  );
@@ -2048,7 +2459,9 @@ export const setup = (
2048
2459
  }
2049
2460
 
2050
2461
  function setSensorSensitivity(sensitivity = DEFAULT_SENSITIVITY) {
2051
- if (!actorController) { return }
2462
+ if (!actorController) {
2463
+ return;
2464
+ }
2052
2465
  if (sensitivity <= 0) {
2053
2466
  actorController.run((cmds) => [
2054
2467
  cmds.state().removeConditionByGroup(ScensorCondigionGroup),
@@ -2057,11 +2470,10 @@ export const setup = (
2057
2470
  }
2058
2471
 
2059
2472
  if (sensitivity != onMoveSensitivity) {
2060
- setOnMovement(sensitivity)
2473
+ setOnMovement(sensitivity);
2061
2474
  }
2062
2475
  }
2063
2476
 
2064
-
2065
2477
  const getTouchCount = (nexusCustomData) => {
2066
2478
  let touchCount = -1;
2067
2479
  if (nexusCustomData) {
@@ -2072,7 +2484,7 @@ export const setup = (
2072
2484
  }
2073
2485
  }
2074
2486
  return touchCount;
2075
- }
2487
+ };
2076
2488
 
2077
2489
  const mergeTouchSlideToSlideDiv = (touchCount) => {
2078
2490
  let originSlideDivTop = slideDivTop.value;
@@ -2084,24 +2496,28 @@ export const setup = (
2084
2496
  }
2085
2497
  let newSlideGapTop = originSlideDivTop - slideDivTop.value;
2086
2498
  let newSlideGapLeft = originSlideDivLeft - slideDivLeft.value;
2087
- freeMoveSlideGapTop += newSlideGapTop; // 累计slider变化的gap,等待同步完毕时消除gap
2499
+ freeMoveSlideGapTop += newSlideGapTop; // 累计slider变化的gap,等待同步完毕时消除gap
2088
2500
  freeMoveSlideGapLeft += newSlideGapLeft;
2089
2501
 
2090
2502
  const walls = getTouchWall();
2091
2503
  actorController.run((cmds) => [
2092
2504
  cmds.state().removeConditionByGroup(wallConditionGroup),
2093
- cmds.condition(wallConditionGroup, true)
2505
+ cmds
2506
+ .condition(wallConditionGroup, true)
2094
2507
  .boxPosition(walls.left, walls.top, walls.right, walls.bottom)
2095
2508
  .then([cmds.state().setHitWallOverflow()]), //TODO 通过prop设置哪个方向overflow
2096
2509
  cmds.state().setStartOffsetPos(newSlideGapLeft, newSlideGapTop), // 将div的位置调整回馈给FreeMove计量系统
2097
- cmds.condition().onNextTick(0).then([
2098
- SliderEditFuncReOrderWrap(() => {
2099
- freeMoveSlideGapTop -= newSlideGapTop;
2100
- freeMoveSlideGapLeft -= newSlideGapLeft;
2101
- }, true) // Slide调整回调要放在其他事件之前,调整slide的gap值
2102
- ])
2510
+ cmds
2511
+ .condition()
2512
+ .onNextTick(0)
2513
+ .then([
2514
+ SliderEditFuncReOrderWrap(() => {
2515
+ freeMoveSlideGapTop -= newSlideGapTop;
2516
+ freeMoveSlideGapLeft -= newSlideGapLeft;
2517
+ }, true), // Slide调整回调要放在其他事件之前,调整slide的gap值
2518
+ ]),
2103
2519
  ]);
2104
- }
2520
+ };
2105
2521
  function onTouchActionDone(touchCount) {
2106
2522
  //一次触控动作结束
2107
2523
  mergeTouchSlideToSlideDiv(touchCount);
@@ -2128,20 +2544,30 @@ export const setup = (
2128
2544
  right: vertical ? undefined : lockThreshhold,
2129
2545
  top: vertical ? lockThreshhold : undefined,
2130
2546
  bottom: vertical ? lockThreshhold : undefined,
2131
- }
2547
+ };
2132
2548
 
2133
2549
  let passDownTouchInfo = nexusCustomData;
2134
2550
  actorController.run((cmds) => [
2135
2551
  cmds
2136
2552
  .condition(TouchDownConditionGroup, false)
2137
- .offsetPosition(offsetThreshold.left, offsetThreshold.top, offsetThreshold.right, offsetThreshold.bottom)
2553
+ .offsetPosition(
2554
+ offsetThreshold.left,
2555
+ offsetThreshold.top,
2556
+ offsetThreshold.right,
2557
+ offsetThreshold.bottom
2558
+ )
2138
2559
  .then([
2139
- cmds.state().touchLockSwitch(true, vertical ? 1 : 2, unlockThreshold)]),
2560
+ cmds.state().touchLockSwitch(true, vertical ? 1 : 2, unlockThreshold),
2561
+ ]),
2140
2562
  cmds
2141
2563
  .condition(TouchDownConditionGroup, false)
2142
2564
  .startMove(true, true)
2143
- .then([SliderEditFuncReOrderWrap((d) => { onDragStart(d, null, passDownTouchInfo) })]),
2144
- ])
2565
+ .then([
2566
+ SliderEditFuncReOrderWrap((d) => {
2567
+ onDragStart(d, null, passDownTouchInfo);
2568
+ }),
2569
+ ]),
2570
+ ]);
2145
2571
 
2146
2572
  //blur item
2147
2573
  // onItemBlur(getItemById(focusId));
@@ -2161,26 +2587,32 @@ export const setup = (
2161
2587
  //创建锚点
2162
2588
  const anchorArea = 2 * Forge.sRenderBridge.GetScreenInfo().designedWidth;
2163
2589
  let anchorPosList = [];
2164
- let anchorSpacing = visibleInfo.range * 2 / 3;
2590
+ let anchorSpacing = (visibleInfo.range * 2) / 3;
2165
2591
  let anchorPos = anchorSpacing;
2166
2592
  while (anchorPos < anchorArea) {
2167
2593
  anchorPosList.push(-visibleInfo.start + anchorPos);
2168
- anchorPosList.push(-visibleInfo.start - visibleInfo.range - anchorPos + 1);
2594
+ anchorPosList.push(
2595
+ -visibleInfo.start - visibleInfo.range - anchorPos + 1
2596
+ );
2169
2597
  anchorPos += anchorSpacing;
2170
2598
  }
2171
2599
  actorController.run((cmds) => {
2172
- const reachConditionList = anchorPosList.map(pos => {
2600
+ const reachConditionList = anchorPosList.map((pos) => {
2173
2601
  return cmds
2174
2602
  .condition(reachAnchorGroup)
2175
2603
  .reachPosition(pos, undefined)
2176
- .then([SliderEditFuncReOrderWrap((data) => { updateRenderItems(true, true) })])
2177
- })
2604
+ .then([
2605
+ SliderEditFuncReOrderWrap((data) => {
2606
+ updateRenderItems(true, true);
2607
+ }),
2608
+ ]);
2609
+ });
2178
2610
  reachConditionList.unshift(
2179
- cmds.state().removeConditionByGroup(reachAnchorGroup),
2180
- )
2181
- return reachConditionList
2611
+ cmds.state().removeConditionByGroup(reachAnchorGroup)
2612
+ );
2613
+ return reachConditionList;
2182
2614
  });
2183
- }
2615
+ };
2184
2616
 
2185
2617
  const onTouchRelease = (touchCount) => {
2186
2618
  if (mode.getTouchState() == TouchState.TAP) {
@@ -2191,14 +2623,14 @@ export const setup = (
2191
2623
  if (touchRecorder.moved && !mode.duringFling()) {
2192
2624
  onTouchActionDone(touchRecorder.touchCount);
2193
2625
  updateRenderItems(false, false);
2194
- mode.touchEnd(touchCount)
2626
+ mode.touchEnd(touchCount);
2195
2627
  }
2196
2628
  }
2197
2629
  actorController.run((cmds) => [
2198
2630
  cmds.state().removeConditionByGroup(TouchDownConditionGroup),
2199
- cmds.state().touchLockSwitch(false, vertical ? 1 : 2)
2200
- ])
2201
- }
2631
+ cmds.state().touchLockSwitch(false, vertical ? 1 : 2),
2632
+ ]);
2633
+ };
2202
2634
 
2203
2635
  const exportOnTouchRelease = props.touchFlag > 0 ? onTouchRelease : undefined;
2204
2636
 
@@ -2207,10 +2639,10 @@ export const setup = (
2207
2639
  touchRecorder.move();
2208
2640
  if (!(mode.getTouchCount() == touchCount && mode.duringFling())) {
2209
2641
  //dragStart event may be triggered after fling event because of sending it when startMove condition is satisfied
2210
- mode.dragStart(touchCount)
2642
+ mode.dragStart(touchCount);
2211
2643
  }
2212
2644
  visibleInfo.start = getVisibleStart(data);
2213
- }
2645
+ };
2214
2646
 
2215
2647
  const onDragEnd = (data, customData, nexusCustomData) => {
2216
2648
  let touchCount = getTouchCount(nexusCustomData);
@@ -2219,7 +2651,7 @@ export const setup = (
2219
2651
  actorController.run((cmds) => [
2220
2652
  cmds.state().removeConditionByGroup(reachAnchorGroup),
2221
2653
  ]);
2222
- }
2654
+ };
2223
2655
 
2224
2656
  const onFlingStart = (data, customData, nexusCustomData) => {
2225
2657
  let touchCount = getTouchCount(nexusCustomData);
@@ -2227,13 +2659,13 @@ export const setup = (
2227
2659
  mode.flingStart(touchCount);
2228
2660
  visibleInfo.start = getVisibleStart(data);
2229
2661
  updateRenderItems(true, true);
2230
- }
2662
+ };
2231
2663
 
2232
2664
  const onFlingProgress = (data, customData, nexusCustomData) => {
2233
2665
  let touchCount = getTouchCount(nexusCustomData);
2234
2666
  visibleInfo.start = getVisibleStart(data);
2235
2667
  updateRenderItems(true, true);
2236
- }
2668
+ };
2237
2669
 
2238
2670
  const onFlingEnd = (data, customData, nexusCustomData) => {
2239
2671
  visibleInfo.start = getVisibleStart(data);
@@ -2245,12 +2677,12 @@ export const setup = (
2245
2677
  mode.flingEnd(touchCount);
2246
2678
  mode.touchEnd(touchCount);
2247
2679
  }
2248
- }
2680
+ };
2249
2681
 
2250
2682
  const onFlingDrop = (data, customData, nexusCustomData) => {
2251
2683
  let touchCount = getTouchCount(nexusCustomData);
2252
2684
  visibleInfo.start = getVisibleStart(data);
2253
- }
2685
+ };
2254
2686
 
2255
2687
  const getTouchWall = () => {
2256
2688
  const boxSize = metroTemplate.getBoundingBoxSize();
@@ -2259,15 +2691,23 @@ export const setup = (
2259
2691
  top: 0,
2260
2692
  right: 0,
2261
2693
  bottom: 0,
2262
- }
2694
+ };
2263
2695
  if (vertical) {
2264
- wall.top = -boxSize.height + props.height - slideDivTop.value - (widgetRectInfo.padding.top + widgetRectInfo.padding.bottom);
2696
+ wall.top =
2697
+ -boxSize.height +
2698
+ props.height -
2699
+ slideDivTop.value -
2700
+ (widgetRectInfo.padding.top + widgetRectInfo.padding.bottom);
2265
2701
  wall.bottom = -slideDivTop.value;
2266
2702
  if (wall.top > wall.bottom) {
2267
2703
  wall.top = wall.bottom;
2268
2704
  }
2269
2705
  } else {
2270
- wall.left = -boxSize.width + props.width - slideDivLeft.value - (widgetRectInfo.padding.left + widgetRectInfo.padding.right);
2706
+ wall.left =
2707
+ -boxSize.width +
2708
+ props.width -
2709
+ slideDivLeft.value -
2710
+ (widgetRectInfo.padding.left + widgetRectInfo.padding.right);
2271
2711
  wall.right = -slideDivLeft.value;
2272
2712
  if (wall.left > wall.right) {
2273
2713
  wall.left = wall.right;
@@ -2275,10 +2715,12 @@ export const setup = (
2275
2715
  }
2276
2716
 
2277
2717
  return wall;
2278
- }
2718
+ };
2279
2719
 
2280
2720
  const updateRenderItems = (applyTmp, expand) => {
2281
- templateItemAdder.tryAddItemByPosition(visibleInfo.start + visibleInfo.range);
2721
+ templateItemAdder.tryAddItemByPosition(
2722
+ visibleInfo.start + visibleInfo.range
2723
+ );
2282
2724
  const updater = pageUpdater.update(
2283
2725
  metroTemplate,
2284
2726
  visibleInfo.startWithPadding - innerKeepTraceRange * pageRange,
@@ -2288,9 +2730,10 @@ export const setup = (
2288
2730
  permanentItemList
2289
2731
  );
2290
2732
  applyTmp ? updater.applyTmp() : updater.apply();
2291
- }
2733
+ };
2292
2734
 
2293
2735
  const updateTouchBoxCondition = () => {
2736
+ if (mode.getMode() != TOUCH_MODE) return;
2294
2737
  if (actorController != null) {
2295
2738
  const walls = getTouchWall();
2296
2739
 
@@ -2303,7 +2746,7 @@ export const setup = (
2303
2746
  .then([cmds.state().setHitWallOverflow()]), //TODO 通过prop设置哪个方向overflow
2304
2747
  ]);
2305
2748
  }
2306
- }
2749
+ };
2307
2750
 
2308
2751
  const touchRecorder = {
2309
2752
  moved: false,
@@ -2317,7 +2760,7 @@ export const setup = (
2317
2760
  },
2318
2761
  setTouchCount: function (count) {
2319
2762
  this.touchCount = count;
2320
- }
2763
+ },
2321
2764
  };
2322
2765
 
2323
2766
  const metroWidgetToken = metroWidgetTokenGen++;
@@ -2325,14 +2768,14 @@ export const setup = (
2325
2768
  let orderTouchSlideCallbacks;
2326
2769
  const SliderEditFuncReOrderWrap = (callback, addHeader = false) => {
2327
2770
  return (...args) => {
2328
- let pkg = { cb: callback, a: args }
2771
+ let pkg = { cb: callback, a: args };
2329
2772
  if (addHeader) {
2330
2773
  orderTouchSlideCallbacks.splice(0, 0, pkg);
2331
2774
  } else {
2332
2775
  orderTouchSlideCallbacks.push(pkg);
2333
2776
  }
2334
- }
2335
- }
2777
+ };
2778
+ };
2336
2779
 
2337
2780
  //TODO debug
2338
2781
  // let debugAnimId = -1;
@@ -2360,7 +2803,7 @@ export const setup = (
2360
2803
  // 执行结束后进行清理
2361
2804
  orderTouchSlideCallbacks.length = 0;
2362
2805
  }
2363
- )
2806
+ );
2364
2807
 
2365
2808
  // debugAnimId = actorController.debugGetAnimId();
2366
2809
  // debugViewId = divView.ViewId;
@@ -2409,16 +2852,27 @@ export const setup = (
2409
2852
  if (props.onScroll) {
2410
2853
  setOnMovement(DEFAULT_SENSITIVITY);
2411
2854
  }
2412
- }
2855
+ };
2413
2856
 
2414
2857
  function cleanTouch() {
2415
2858
  actorController.run((cmds) => [
2416
2859
  cmds.state().clearAllConditions(),
2417
- cmds.state().touchLockSwitch(false, vertical ? 1 : 2)
2418
- ])
2860
+ cmds.state().touchLockSwitch(false, vertical ? 1 : 2),
2861
+ ]);
2419
2862
  }
2420
2863
 
2421
2864
  //init
2865
+
2866
+ function safeProvideData() {
2867
+ const d = props.provideData();
2868
+ if (d instanceof Array) {
2869
+ return d;
2870
+ }
2871
+ console.warn(
2872
+ `MetroWidget provideData must return an array. name:${props.name} provideData:${d}`
2873
+ );
2874
+ return [];
2875
+ }
2422
2876
  pageUpdater = new PageUpdater(_updatePage, props.name);
2423
2877
  visibleInfo.range = vertical
2424
2878
  ? widgetRectInfo.contentHeight
@@ -2428,10 +2882,11 @@ export const setup = (
2428
2882
  : { start: widgetRectInfo.padding.left, end: widgetRectInfo.padding.right };
2429
2883
 
2430
2884
  if (props.provideData) {
2431
- dataList = toRaw(props.provideData());
2885
+ dataList = toRaw(safeProvideData())?.concat();
2432
2886
  } else if (props.data) {
2433
- dataList = toRaw(props.data);
2887
+ dataList = toRaw(props.data ?? [])?.concat();
2434
2888
  }
2889
+ dataKeyList = dataList.map((i) => i[DATA_ID_KEY]);
2435
2890
 
2436
2891
  templateItemAdder = new TemplateItemAdder(
2437
2892
  metroTemplate,
@@ -2456,8 +2911,16 @@ export const setup = (
2456
2911
  const item = getItemById(props.initFocusId);
2457
2912
  if (item) {
2458
2913
  init_focus_id = props.initFocusId;
2459
- if (item.itemConfig.itemSlide == METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS) {
2460
- initVisibleStart = _calculateVisibleStart(item.templateInfo, 0, item.templateInfo, visibleInfo);
2914
+ if (
2915
+ item.itemConfig.itemSlide ==
2916
+ METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS
2917
+ ) {
2918
+ initVisibleStart = _calculateVisibleStart(
2919
+ item.templateInfo,
2920
+ 0,
2921
+ item.templateInfo,
2922
+ visibleInfo
2923
+ );
2461
2924
  }
2462
2925
  }
2463
2926
  }
@@ -2497,8 +2960,8 @@ export const setup = (
2497
2960
  if (initVisibleStart) {
2498
2961
  slideToInner(initVisibleStart, false);
2499
2962
  }
2500
- if (isFocus && !alreadyCallItemFocus) {
2501
- onItemFocus(getItemById(focusId), preEdgeRect);
2963
+ if (!firstOnItemFocusCalled) {
2964
+ firstOnItemFocusCalled = onItemFocus(getItemById(focusId), preEdgeRect);
2502
2965
  }
2503
2966
 
2504
2967
  if (props.enableItemRenderBreak) {
@@ -2511,7 +2974,7 @@ export const setup = (
2511
2974
  }
2512
2975
  });
2513
2976
 
2514
- onUpdated(() => { });
2977
+ onUpdated(() => {});
2515
2978
 
2516
2979
  onBeforeUnmount(() => {
2517
2980
  taskManager.cancelAllTask();
@@ -2527,6 +2990,7 @@ export const setup = (
2527
2990
  focusBlockOnFocus,
2528
2991
  focusBlockOnBlur,
2529
2992
  focusBlockOnKeyDown,
2993
+ focusBlockOnKeyUp,
2530
2994
  focusBlockOnCustomEvent,
2531
2995
  _onFocusableItemEdge,
2532
2996
  exportObject,
@@ -2535,6 +2999,6 @@ export const setup = (
2535
2999
  onTouchRelease: exportOnTouchRelease,
2536
3000
  currentFocusIndex,
2537
3001
  modeForExport,
2538
- onDispatchKeyDown
2539
- }
2540
- }
3002
+ onDispatchKeyDown,
3003
+ };
3004
+ };