@shijiu/jsview-vue 2.3.151-test.0 → 3.0.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 (244) hide show
  1. package/bin/browser/BrowserAudio.mjs +200 -0
  2. package/bin/browser/BrowserJsvLatex.mjs +61 -0
  3. package/bin/export-sfc.mjs +8 -9
  4. package/bin/jsview-vue-common.mjs +9 -35
  5. package/bin/jsview-vue.mjs +22246 -23643
  6. package/bin/types/utils/JsViewEngineWidget/JsvFocus/JsvFocusBlock.vue.d.ts +9 -71
  7. package/bin/types/utils/JsViewEngineWidget/JsvFocus/JsvFocusHub.d.ts +18 -2
  8. package/bin/types/utils/JsViewEngineWidget/MetroWidget/Const.d.ts +4 -1
  9. package/bin/types/utils/JsViewEngineWidget/MetroWidget/DebugFrame.vue.d.ts +10 -7
  10. package/bin/types/utils/JsViewEngineWidget/MetroWidget/ListWidget.vue.d.ts +19 -178
  11. package/bin/types/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue.d.ts +19 -178
  12. package/bin/types/utils/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.d.ts +24 -3
  13. package/bin/types/utils/JsViewEngineWidget/MetroWidget/PageUpdater.d.ts +7 -1
  14. package/bin/types/utils/JsViewEngineWidget/MetroWidget/RenderItem.d.ts +25 -5
  15. package/bin/types/utils/JsViewEngineWidget/MetroWidget/SlotComponent.vue.d.ts +9 -47
  16. package/bin/types/utils/JsViewEngineWidget/MetroWidget/TaskManager.d.ts +2 -1
  17. package/bin/types/utils/JsViewEngineWidget/MetroWidget/Utils.d.ts +2 -0
  18. package/bin/types/utils/JsViewEngineWidget/MetroWidget/WidgetRectInfo.d.ts +1 -1
  19. package/bin/types/utils/JsViewEngineWidget/SpatialNavigator/SpatialNavProvider.vue.d.ts +40 -0
  20. package/bin/types/utils/JsViewEngineWidget/SpatialNavigator/SpatialNavigationAlgorithm.d.ts +24 -0
  21. package/bin/types/utils/JsViewEngineWidget/SpatialNavigator/SpatialNavigationNode.d.ts +19 -0
  22. package/bin/types/utils/JsViewEngineWidget/SpatialNavigator/SpatialNavigator.d.ts +42 -0
  23. package/bin/types/utils/JsViewEngineWidget/TemplateParser/CommonMetroTemplate.d.ts +2 -1
  24. package/bin/types/utils/JsViewEngineWidget/TemplateParser/ListMetroTemplate.d.ts +2 -1
  25. package/bin/types/utils/JsViewEngineWidget/TemplateParser/MetroTemplate.d.ts +6 -4
  26. package/bin/types/utils/JsViewEngineWidget/TemplateParser/TemplateItemAdder.d.ts +9 -7
  27. package/bin/types/utils/JsViewEngineWidget/WidgetCommon.d.ts +17 -7
  28. package/bin/types/utils/JsViewEngineWidget/index.d.ts +3 -1
  29. package/bin/types/utils/JsViewPlugin/JsvAudio/BrowserAudio/BrowserAudio.vue.d.ts +140 -7
  30. package/bin/types/utils/JsViewPlugin/JsvAudio/BrowserAudio/JsvSystemAudio.vue.d.ts +12 -11
  31. package/bin/types/utils/JsViewPlugin/JsvAudio/Events.d.ts +10 -10
  32. package/bin/types/utils/JsViewPlugin/JsvAudio/JsvAudio.vue.d.ts +204 -17
  33. package/bin/types/utils/JsViewPlugin/JsvAudio/JsvAudioProxy.vue.d.ts +2 -1
  34. package/bin/types/utils/JsViewPlugin/JsvAudio/version.d.mts +11 -11
  35. package/bin/types/utils/JsViewPlugin/JsvAudio/version.d.ts +11 -11
  36. package/bin/types/utils/JsViewPlugin/JsvLatex/BrowserDomBuilder.d.ts +0 -1
  37. package/bin/types/utils/JsViewPlugin/JsvLatex/BrowserJsvLatex.vue.d.ts +75 -12
  38. package/bin/types/utils/JsViewPlugin/JsvLatex/GetVersion.d.ts +14 -0
  39. package/bin/types/utils/JsViewPlugin/JsvLatex/JsvLatex.vue.d.ts +88 -13
  40. package/bin/types/utils/JsViewPlugin/JsvLatex/JsvLatexBridgeProxy.d.ts +1 -0
  41. package/bin/types/utils/JsViewPlugin/JsvLatex/JsvLatexProxy.vue.d.ts +5 -1
  42. package/bin/types/utils/JsViewPlugin/JsvLatex/version.d.mts +39 -12
  43. package/bin/types/utils/JsViewPlugin/JsvPlayer/JsvMedia.d.ts +120 -17
  44. package/bin/types/utils/JsViewPlugin/JsvPlayer/JsvMediaBrowserInterface.d.ts +62 -0
  45. package/bin/types/utils/JsViewPlugin/JsvPlayer/JsvPlayer.vue.d.ts +108 -29
  46. package/bin/types/utils/JsViewPlugin/JsvPlayer/{BrowserJsvPlayer-0.9.vue.d.ts → JsvPlayerBrowser-0.9.vue.d.ts} +8 -7
  47. package/bin/types/utils/JsViewPlugin/JsvPlayer/JsvPlayerBrowser-wasm.vue.d.ts +614 -0
  48. package/bin/types/utils/JsViewPlugin/JsvPlayer/{BrowserJsvPlayer.vue.d.ts → JsvPlayerBrowser.vue.d.ts} +36 -34
  49. package/bin/types/utils/JsViewPlugin/JsvPlayer/index-0.9.d.ts +89 -30
  50. package/bin/types/utils/JsViewPlugin/JsvPlayer/index.d.ts +89 -30
  51. package/bin/types/utils/JsViewPlugin/JsvPlayer/version.d.mts +11 -11
  52. package/bin/types/utils/JsViewVueTools/BlobApi.d.ts +38 -0
  53. package/bin/types/utils/JsViewVueTools/DebugTool.d.ts +1 -1
  54. package/bin/types/utils/JsViewVueTools/DefaultKeyMap.d.ts +7 -7
  55. package/bin/types/utils/JsViewVueTools/FeatureActive.d.ts +1 -0
  56. package/bin/types/utils/JsViewVueTools/JsvInteractionMode.d.ts +6 -0
  57. package/bin/types/utils/JsViewVueTools/JsvRuntimeBridge.d.ts +3 -3
  58. package/bin/types/utils/JsViewVueTools/JsvTextTools.d.ts +1 -0
  59. package/bin/types/utils/JsViewVueTools/JsvTextureStore/BitPalette/BitPalette.d.ts +43 -0
  60. package/bin/types/utils/JsViewVueTools/JsvTextureStore/CanvasTexture/CommandList.d.ts +1 -0
  61. package/bin/types/utils/JsViewVueTools/JsvTextureStore/CanvasTexture/DrawHelper.d.ts +54 -0
  62. package/bin/types/utils/JsViewVueTools/JsvTextureStore/CanvasTexture/Path.d.ts +13 -0
  63. package/bin/types/utils/JsViewVueTools/JsvTextureStore/CapturedTexture/CapturedTexture.d.ts +2 -0
  64. package/bin/types/utils/JsViewVueTools/JsvTextureStore/JsvTextureStore.d.ts +76 -26
  65. package/bin/types/utils/JsViewVueTools/JsvTextureStore/TextureBuilder.d.ts +49 -0
  66. package/bin/types/utils/JsViewVueTools/JsvTextureStore/index.d.ts +2 -0
  67. package/bin/types/utils/JsViewVueTools/index.d.ts +4 -1
  68. package/bin/types/utils/JsViewVueWidget/Jsv3dDiv.vue.d.ts +10 -98
  69. package/bin/types/utils/JsViewVueWidget/Jsv3dStage.vue.d.ts +10 -114
  70. package/bin/types/utils/JsViewVueWidget/JsvActorMove/JsvActorMove.vue.d.ts +20 -61
  71. package/bin/types/utils/JsViewVueWidget/JsvApic/JsvApic/BrowserApic.vue.d.ts +44 -13
  72. package/bin/types/utils/JsViewVueWidget/JsvApic/JsvApic/JsvApic.vue.d.ts +12 -11
  73. package/bin/types/utils/JsViewVueWidget/JsvApic/JsvApic/index.d.ts +5 -5
  74. package/bin/types/utils/JsViewVueWidget/JsvApic/JsvApic2/BrowserApic2.vue.d.ts +16 -10
  75. package/bin/types/utils/JsViewVueWidget/JsvApic/JsvApic2/JsvApic2.vue.d.ts +21 -17
  76. package/bin/types/utils/JsViewVueWidget/JsvApic/JsvApic2/index.d.ts +19 -16
  77. package/bin/types/utils/JsViewVueWidget/JsvApic/JsvCommonLoopToolBase.d.ts +7 -7
  78. package/bin/types/utils/JsViewVueWidget/JsvClipDiv/JsvClipDiv.vue.d.ts +12 -66
  79. package/bin/types/utils/JsViewVueWidget/JsvConnectLine/JsvConnectLine.vue.d.ts +73 -12
  80. package/bin/types/utils/JsViewVueWidget/JsvDashPath.vue.d.ts +59 -10
  81. package/bin/types/utils/JsViewVueWidget/JsvDragBox/JsvDragBox.vue.d.ts +41 -81
  82. package/bin/types/utils/JsViewVueWidget/JsvDriftScope/JsvDriftScope.vue.d.ts +17 -100
  83. package/bin/types/utils/JsViewVueWidget/JsvEnableRenderBreak.vue.d.ts +13 -50
  84. package/bin/types/utils/JsViewVueWidget/JsvFilterView.vue.d.ts +50 -70
  85. package/bin/types/utils/JsViewVueWidget/JsvFlexCell/JsvFlexDiv.vue.d.ts +32 -68
  86. package/bin/types/utils/JsViewVueWidget/JsvFlexCell/JsvFullScrAdjust.vue.d.ts +57 -74
  87. package/bin/types/utils/JsViewVueWidget/JsvFlexCell/JsvScreenFlex.vue.d.ts +41 -71
  88. package/bin/types/utils/JsViewVueWidget/JsvFragShaderView/JsvFragShaderView.vue.d.ts +83 -14
  89. package/bin/types/utils/JsViewVueWidget/JsvFreeMoveActor/ActorControl.d.ts +151 -18
  90. package/bin/types/utils/JsViewVueWidget/JsvFreeMoveActor/JsvEnvBlocker.vue.d.ts +79 -83
  91. package/bin/types/utils/JsViewVueWidget/JsvFreeMoveActor/JsvFreeMoveActor.vue.d.ts +70 -0
  92. package/bin/types/utils/JsViewVueWidget/JsvFreeMoveActor/SetAction.d.ts +20 -0
  93. package/bin/types/utils/JsViewVueWidget/JsvFreeMoveActor/SetCondition.d.ts +108 -5
  94. package/bin/types/utils/JsViewVueWidget/JsvFreeMoveActor/SetState.d.ts +88 -3
  95. package/bin/types/utils/JsViewVueWidget/JsvFreeMoveActor/index.d.ts +6 -1
  96. package/bin/types/utils/JsViewVueWidget/JsvGrid.vue.d.ts +19 -18
  97. package/bin/types/utils/JsViewVueWidget/JsvInput/Cursor.vue.d.ts +34 -11
  98. package/bin/types/utils/JsViewVueWidget/JsvInput/EditViewOperator.d.ts +4 -1
  99. package/bin/types/utils/JsViewVueWidget/JsvInput/JsvInput.vue.d.ts +193 -6
  100. package/bin/types/utils/JsViewVueWidget/JsvLine/JsvLine.vue.d.ts +54 -11
  101. package/bin/types/utils/JsViewVueWidget/JsvMarquee.vue.d.ts +89 -11
  102. package/bin/types/utils/JsViewVueWidget/JsvMaskClipDiv.vue.d.ts +9 -8
  103. package/bin/types/utils/JsViewVueWidget/JsvMindMap/Geometry.d.ts +2 -2
  104. package/bin/types/utils/JsViewVueWidget/JsvMindMap/JsvMindMap.vue.d.ts +170 -138
  105. package/bin/types/utils/JsViewVueWidget/JsvMindMap/rtree.d.ts +5 -5
  106. package/bin/types/utils/JsViewVueWidget/JsvNativeSharedDiv.vue.d.ts +48 -72
  107. package/bin/types/utils/JsViewVueWidget/JsvNinePatch.vue.d.ts +139 -20
  108. package/bin/types/utils/JsViewVueWidget/JsvPieChart.vue.d.ts +56 -8
  109. package/bin/types/utils/JsViewVueWidget/JsvPreload/JsvPreload.vue.d.ts +20 -11
  110. package/bin/types/utils/JsViewVueWidget/JsvProgressBar.vue.d.ts +63 -11
  111. package/bin/types/utils/JsViewVueWidget/JsvQrcode/JsvQrcode.vue.d.ts +8 -7
  112. package/bin/types/utils/JsViewVueWidget/JsvRadarChart.vue.d.ts +95 -12
  113. package/bin/types/utils/JsViewVueWidget/JsvRipple/Constant.d.ts +2 -2
  114. package/bin/types/utils/JsViewVueWidget/JsvRipple/JsvRipple.vue.d.ts +51 -78
  115. package/bin/types/utils/JsViewVueWidget/JsvScaleTextBox.vue.d.ts +5 -4
  116. package/bin/types/utils/JsViewVueWidget/JsvScrollBox/JsvScrollBox.vue.d.ts +84 -193
  117. package/bin/types/utils/JsViewVueWidget/JsvScrollBox/JsvScrollFollow.vue.d.ts +23 -148
  118. package/bin/types/utils/JsViewVueWidget/JsvSector.vue.d.ts +56 -9
  119. package/bin/types/utils/JsViewVueWidget/JsvSmoothSlideContainer.vue.d.ts +22 -67
  120. package/bin/types/utils/JsViewVueWidget/JsvSpray/JsvSpray.vue.d.ts +44 -10
  121. package/bin/types/utils/JsViewVueWidget/JsvSpriteAnim/JsvSpriteAnim.vue.d.ts +47 -14
  122. package/bin/types/utils/JsViewVueWidget/JsvSpriteAnim/JsvSpriteLoader.vue.d.ts +26 -67
  123. package/bin/types/utils/JsViewVueWidget/JsvSwiper/Indicator.vue.d.ts +7 -6
  124. package/bin/types/utils/JsViewVueWidget/JsvSwiper/JsvSmoothSwiper.vue.d.ts +147 -109
  125. package/bin/types/utils/JsViewVueWidget/JsvSwiper/JsvSwiper.vue.d.ts +173 -16
  126. package/bin/types/utils/JsViewVueWidget/JsvSwiper/JsvSwiper2.vue.d.ts +216 -139
  127. package/bin/types/utils/JsViewVueWidget/JsvSwiper3D/Indicator.vue.d.ts +7 -6
  128. package/bin/types/utils/JsViewVueWidget/JsvSwiper3D/JsvSwiper.vue.d.ts +101 -96
  129. package/bin/types/utils/JsViewVueWidget/JsvTextBox.vue.d.ts +89 -74
  130. package/bin/types/utils/JsViewVueWidget/JsvTextureAnim/JsvTextureAnim.vue.d.ts +21 -20
  131. package/bin/types/utils/JsViewVueWidget/JsvTouchModeSwitcher.vue.d.ts +43 -70
  132. package/bin/types/utils/JsViewVueWidget/JsvVideo.vue.d.ts +6 -5
  133. package/bin/types/utils/JsViewVueWidget/JsvVisibleSensor/JsvVisibleSensor.vue.d.ts +62 -82
  134. package/bin/types/utils/JsViewVueWidget/JsvVisibleSensor/index.d.ts +95 -74
  135. package/bin/types/utils/JsViewVueWidget/TypesDiv/JsvPosterDiv.vue.d.ts +51 -0
  136. package/bin/types/utils/JsViewVueWidget/TypesDiv/JsvPosterImage.vue.d.ts +105 -0
  137. package/bin/types/utils/JsViewVueWidget/TypesDiv/JsvSmartDiv.vue.d.ts +51 -0
  138. package/bin/types/utils/JsViewVueWidget/TypesDiv/JsvSmartImage.vue.d.ts +105 -0
  139. package/bin/types/utils/JsViewVueWidget/index.d.ts +5 -3
  140. package/package.json +2 -2
  141. package/tools/jsview-vue-build.mjs +13 -9
  142. package/tsconfig.json +2 -2
  143. package/utils/JsViewEngineWidget/JsvFocus/JsvFocusBlock.vue +32 -16
  144. package/utils/JsViewEngineWidget/JsvFocus/JsvFocusHub.ts +24 -2
  145. package/utils/JsViewEngineWidget/MetroWidget/Const.ts +5 -0
  146. package/utils/JsViewEngineWidget/MetroWidget/ListWidget.vue +183 -89
  147. package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +269 -122
  148. package/utils/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.js +989 -357
  149. package/utils/JsViewEngineWidget/MetroWidget/PageUpdater.ts +41 -23
  150. package/utils/JsViewEngineWidget/MetroWidget/RenderItem.ts +138 -41
  151. package/utils/JsViewEngineWidget/MetroWidget/TaskManager.ts +1 -0
  152. package/utils/JsViewEngineWidget/MetroWidget/Utils.ts +6 -0
  153. package/utils/JsViewEngineWidget/MetroWidget/WidgetRectInfo.ts +2 -1
  154. package/utils/JsViewEngineWidget/RectUtils.js +1 -1
  155. package/utils/JsViewEngineWidget/SpatialNavigator/SpatialNavProvider.vue +50 -0
  156. package/utils/JsViewEngineWidget/SpatialNavigator/SpatialNavigationAlgorithm.ts +260 -0
  157. package/utils/JsViewEngineWidget/SpatialNavigator/SpatialNavigationNode.ts +32 -0
  158. package/utils/JsViewEngineWidget/SpatialNavigator/SpatialNavigator.ts +236 -0
  159. package/utils/JsViewEngineWidget/TemplateParser/CommonMetroTemplate.ts +342 -174
  160. package/utils/JsViewEngineWidget/TemplateParser/ListMetroTemplate.ts +101 -27
  161. package/utils/JsViewEngineWidget/TemplateParser/MetroTemplate.ts +12 -5
  162. package/utils/JsViewEngineWidget/TemplateParser/TemplateItemAdder.ts +109 -41
  163. package/utils/JsViewEngineWidget/WidgetCommon.ts +17 -7
  164. package/utils/JsViewEngineWidget/index.ts +7 -2
  165. package/utils/JsViewPlugin/JsvLatex/BrowserDomBuilder.js +46 -46
  166. package/utils/JsViewPlugin/JsvLatex/BrowserJsvLatex.vue +54 -41
  167. package/utils/JsViewPlugin/JsvLatex/GetVersion.js +65 -0
  168. package/utils/JsViewPlugin/JsvLatex/JsvLatex.vue +54 -12
  169. package/utils/JsViewPlugin/JsvLatex/JsvLatexBridgeProxy.js +10 -0
  170. package/utils/JsViewPlugin/JsvLatex/JsvLatexProxy.vue +15 -2
  171. package/utils/JsViewPlugin/JsvLatex/PluginLoader.js +63 -31
  172. package/utils/JsViewPlugin/JsvLatex/version.mjs +26 -13
  173. package/utils/JsViewPlugin/JsvPlayer/GetVersion.js +2 -1
  174. package/utils/JsViewPlugin/JsvPlayer/JsvMedia.js +402 -23
  175. package/utils/JsViewPlugin/JsvPlayer/JsvMediaBrowserInterface.js +100 -0
  176. package/utils/JsViewPlugin/JsvPlayer/JsvPlayer.vue +363 -468
  177. package/utils/JsViewPlugin/JsvPlayer/{BrowserJsvPlayer.vue → JsvPlayerBrowser-wasm.vue} +60 -10
  178. package/utils/JsViewPlugin/JsvPlayer/JsvPlayerBrowser.vue +511 -0
  179. package/utils/JsViewPlugin/JsvPlayer/index-0.9.js +52 -10
  180. package/utils/JsViewPlugin/JsvPlayer/index.js +58 -9
  181. package/utils/JsViewPlugin/JsvPlayer/package.json +8 -0
  182. package/utils/JsViewVueTools/BlobApi.ts +55 -0
  183. package/utils/JsViewVueTools/FeatureActive.ts +3 -0
  184. package/utils/JsViewVueTools/ForgeHandles.ts +3 -0
  185. package/utils/JsViewVueTools/JsvInteractionMode.js +16 -0
  186. package/utils/JsViewVueTools/JsvPreDownloader.ts +2 -2
  187. package/utils/JsViewVueTools/JsvRuntimeBridge.js +25 -18
  188. package/utils/JsViewVueTools/JsvTextTools.ts +9 -1
  189. package/utils/JsViewVueTools/JsvTextureStore/BitPalette/BitPalette.ts +180 -0
  190. package/utils/JsViewVueTools/JsvTextureStore/CanvasTexture/CommandList.ts +1 -0
  191. package/utils/JsViewVueTools/JsvTextureStore/CanvasTexture/DrawHelper.ts +304 -0
  192. package/utils/JsViewVueTools/JsvTextureStore/CanvasTexture/Path.ts +38 -0
  193. package/utils/JsViewVueTools/JsvTextureStore/CapturedTexture/CapturedTexture.ts +16 -1
  194. package/utils/JsViewVueTools/JsvTextureStore/JsvTextureStore.ts +154 -69
  195. package/utils/JsViewVueTools/JsvTextureStore/Store.ts +1 -1
  196. package/utils/JsViewVueTools/JsvTextureStore/TextureBuilder.ts +92 -0
  197. package/utils/JsViewVueTools/JsvTextureStore/index.js +2 -0
  198. package/utils/JsViewVueTools/index.js +3 -1
  199. package/utils/JsViewVueWidget/JsvApic/JsvApic2/JsvApic2.vue +111 -86
  200. package/utils/JsViewVueWidget/JsvClipDiv/JsvClipDiv.vue +1 -1
  201. package/utils/JsViewVueWidget/JsvDragBox/JsvDragBox.vue +11 -2
  202. package/utils/JsViewVueWidget/JsvDriftScope/JsvDriftScope.vue +1 -1
  203. package/utils/JsViewVueWidget/JsvEnableRenderBreak.vue +6 -0
  204. package/utils/JsViewVueWidget/JsvFlexCell/JsvFlexDiv.vue +11 -5
  205. package/utils/JsViewVueWidget/JsvFlexCell/JsvScreenFlex.vue +3 -1
  206. package/utils/JsViewVueWidget/JsvFragShaderView/JsvFragShaderView.vue +23 -11
  207. package/utils/JsViewVueWidget/JsvFreeMoveActor/ActorControl.ts +242 -25
  208. package/utils/JsViewVueWidget/JsvFreeMoveActor/{FreeMoveActor.vue → JsvFreeMoveActor.vue} +1 -1
  209. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetAction.ts +11 -5
  210. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetCondition.ts +118 -6
  211. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetState.ts +56 -14
  212. package/utils/JsViewVueWidget/JsvFreeMoveActor/index.js +2 -1
  213. package/utils/JsViewVueWidget/JsvInput/EditViewOperator.ts +11 -2
  214. package/utils/JsViewVueWidget/JsvInput/JsvInput.vue +30 -2
  215. package/utils/JsViewVueWidget/JsvLine/JsvLine.vue +24 -7
  216. package/utils/JsViewVueWidget/JsvMarquee.vue +1 -1
  217. package/utils/JsViewVueWidget/JsvNativeSharedDiv.vue +12 -10
  218. package/utils/JsViewVueWidget/JsvNinePatch.vue +13 -8
  219. package/utils/JsViewVueWidget/JsvPieChart.vue +93 -70
  220. package/utils/JsViewVueWidget/JsvPreload/JsvPreload.vue +32 -29
  221. package/utils/JsViewVueWidget/JsvQrcode/JsvQrcode.vue +2 -1
  222. package/utils/JsViewVueWidget/JsvScrollBox/JsvScrollBox.vue +25 -3
  223. package/utils/JsViewVueWidget/JsvScrollBox/JsvScrollFollow.vue +0 -3
  224. package/utils/JsViewVueWidget/JsvSector.vue +66 -28
  225. package/utils/JsViewVueWidget/JsvTextBox.vue +30 -1
  226. package/utils/JsViewVueWidget/JsvTouchModeSwitcher.vue +56 -14
  227. package/utils/JsViewVueWidget/JsvVisibleSensor/JsvVisibleSensor.vue +8 -6
  228. package/utils/JsViewVueWidget/TypesDiv/JsvPosterDiv.vue +54 -0
  229. package/utils/JsViewVueWidget/TypesDiv/JsvPosterImage.vue +88 -0
  230. package/utils/JsViewVueWidget/TypesDiv/JsvSmartDiv.vue +177 -0
  231. package/utils/JsViewVueWidget/TypesDiv/JsvSmartImage.vue +267 -0
  232. package/utils/JsViewVueWidget/index.js +6 -2
  233. package/bin/browser/BrowserAudio.vue.mjs +0 -258
  234. package/bin/browser/BrowserJsvLatex.vue.mjs +0 -145
  235. package/bin/types/utils/JsViewPlugin/JsvLatex/version.d.ts +0 -10
  236. package/bin/types/utils/JsViewVueTools/JsvTextureStore/DominantColor/GetDominantColor.d.ts +0 -7
  237. package/bin/types/utils/JsViewVueWidget/JsvFreeMoveActor/FreeMoveActor.vue.d.ts +0 -78
  238. package/bin/types/utils/JsViewVueWidget/JsvPosterDiv.vue.d.ts +0 -63
  239. package/bin/types/utils/JsViewVueWidget/JsvPosterImage.vue.d.ts +0 -78
  240. package/utils/JsViewPlugin/JsvLatex/version.js +0 -24
  241. package/utils/JsViewVueTools/JsvTextureStore/DominantColor/GetDominantColor.ts +0 -36
  242. package/utils/JsViewVueWidget/JsvPosterDiv.vue +0 -56
  243. package/utils/JsViewVueWidget/JsvPosterImage.vue +0 -105
  244. /package/utils/JsViewPlugin/JsvPlayer/{BrowserJsvPlayer-0.9.vue → JsvPlayerBrowser-0.9.vue} +0 -0
@@ -7,6 +7,11 @@ import {
7
7
  toRaw,
8
8
  nextTick,
9
9
  computed,
10
+ inject,
11
+ watch,
12
+ onActivated,
13
+ onDeactivated,
14
+ provide,
10
15
  } from "vue";
11
16
  import { Forge } from "@shijiu/jsview/dom/jsv-forge-define";
12
17
  import {
@@ -16,7 +21,7 @@ import {
16
21
  } from "../TemplateParser/index";
17
22
  import { PageUpdater } from "./PageUpdater";
18
23
  import { SingleRangeModel } from "../RangeModel";
19
- import { METRO_WIDGET_CONST } from "./Const";
24
+ import { METRO_WIDGET_CONST, ONEDGE_TYPE } from "./Const";
20
25
  import {
21
26
  EdgeDirection,
22
27
  VERTICAL,
@@ -39,19 +44,27 @@ import {
39
44
  JsvUseFeature,
40
45
  } from "../../JsViewVueTools/FeatureActive.ts";
41
46
  import { randomColor } from "./DebugTools.ts";
47
+ import {
48
+ KEY_MODE,
49
+ TOUCH_MODE,
50
+ JsvInteractionMode,
51
+ hasJsvTouchModeSwitcher,
52
+ } from "../../JsViewVueTools/JsvInteractionMode";
53
+ import { getId } from "./Utils";
54
+ import { MW_CONTEXT_NAME } from "./Utils";
55
+ import { SPATIAL_NAV_PROVIDER_NAME } from "../SpatialNavigator/SpatialNavigator";
42
56
 
43
57
  const TAG = "MetroWidget";
44
58
  const LONGPRESS_TIMEOUT = 600;
45
59
  const DATA_ID_KEY = "jsvKey";
46
60
 
47
- let metroWidgetTokenGen = 1;
48
-
49
61
  const _getMetroTemplate = function (
50
62
  widgetRectInfo,
51
63
  direction,
52
64
  support_history_path,
53
65
  layout_type,
54
- mode
66
+ type,
67
+ errorLogger
55
68
  ) {
56
69
  let page_size;
57
70
  let line_max;
@@ -63,14 +76,15 @@ const _getMetroTemplate = function (
63
76
  page_size = widgetRectInfo.contentWidth;
64
77
  }
65
78
  let metroWidget;
66
- switch (mode) {
79
+ switch (type) {
67
80
  case "list":
68
81
  metroWidget = new ListMetroTemplate(
69
82
  direction,
70
83
  line_max,
71
84
  page_size,
72
85
  layout_type,
73
- support_history_path
86
+ support_history_path,
87
+ errorLogger
74
88
  );
75
89
  break;
76
90
  default:
@@ -79,15 +93,69 @@ const _getMetroTemplate = function (
79
93
  line_max,
80
94
  page_size,
81
95
  layout_type,
82
- support_history_path
96
+ support_history_path,
97
+ errorLogger
83
98
  );
84
99
  break;
85
100
  }
86
101
  return metroWidget;
87
102
  };
88
103
 
89
- const TOUCH_MODE = 1; //触控模式
90
- const FOCUS_MODE = 2; //按键模式
104
+ const TouchState = {
105
+ IDLE: 0,
106
+ TAP: 1,
107
+ DRAG: 2,
108
+ FLING: 3,
109
+ };
110
+
111
+ class TouchStateMgr {
112
+ constructor(name) {
113
+ this._name = name;
114
+ this._touchState = TouchState.IDLE;
115
+ this._touchCount = 0;
116
+ }
117
+ touchStart(touchCount) {
118
+ this._touchState = TouchState.TAP;
119
+ this._touchCount = touchCount;
120
+ }
121
+ touchEnd(touchCount) {
122
+ if (touchCount == this._touchCount) {
123
+ this._touchState = TouchState.IDLE;
124
+ }
125
+ }
126
+ flingStart(touchCount) {
127
+ if (touchCount == this._touchCount) {
128
+ this._touchState = TouchState.FLING;
129
+ }
130
+ }
131
+ flingEnd(touchCount) {
132
+ if (touchCount == this._touchCount) {
133
+ this._touchState = TouchState.IDLE;
134
+ }
135
+ }
136
+ dragStart(touchCount) {
137
+ if (touchCount == this._touchCount) {
138
+ this._touchState = TouchState.DRAG;
139
+ }
140
+ }
141
+ dragEnd(touchCount) {
142
+ if (touchCount == this._touchCount) {
143
+ this._touchState = TouchState.IDLE;
144
+ }
145
+ }
146
+ duringFling() {
147
+ return this._touchState == TouchState.FLING;
148
+ }
149
+ duringTouch() {
150
+ return this._touchState != TouchState.IDLE;
151
+ }
152
+ getTouchState() {
153
+ return this._touchState;
154
+ }
155
+ getTouchCount() {
156
+ return this._touchCount;
157
+ }
158
+ }
91
159
 
92
160
  export const setup = (
93
161
  props,
@@ -101,40 +169,56 @@ export const setup = (
101
169
  pageUpdateToken,
102
170
  touchDiv,
103
171
  touchDivSize,
172
+ rootDiv,
104
173
  templateMode
105
174
  ) => {
175
+ const errorLogger = (...args) => {
176
+ console.error(...args, `name=${props.name}`);
177
+ };
106
178
  if (props.itemConfig) {
107
- console.error(TAG, "prop: itemCofig will be deprecated soon.");
179
+ errorLogger(TAG, "prop: itemCofig will be deprecated soon.");
180
+ }
181
+
182
+ function debugLog(...args) {
183
+ console.debug(
184
+ `%cccht name:${props.name} %c`,
185
+ "background-color: #e6ffe6",
186
+ "",
187
+ ...args
188
+ );
108
189
  }
109
190
 
191
+ const metroWidgetId = getId();
192
+ const spatialNavigator = inject(SPATIAL_NAV_PROVIDER_NAME, undefined);
193
+ const parentMetroWidget = inject(MW_CONTEXT_NAME, undefined);
194
+
110
195
  let widgetRectInfo = new WidgetRectInfo(
111
196
  props.width,
112
197
  props.height,
113
- props.padding
198
+ props.padding,
199
+ errorLogger
114
200
  );
115
201
  let metroTemplate = _getMetroTemplate(
116
202
  widgetRectInfo,
117
203
  props.direction,
118
204
  props.supportHistoryPath,
119
205
  props.layoutType,
120
- templateMode
206
+ templateMode,
207
+ errorLogger
121
208
  );
122
209
 
123
- const TouchState = {
124
- IDLE: 0,
125
- TAP: 1,
126
- DRAG: 2,
127
- FLING: 3,
128
- };
210
+ let innerEnableRenderBreak = props.enableItemRenderBreak;
211
+ const touchEnable = computed(() => {
212
+ return props.touchFlag > 0 && hasJsvTouchModeSwitcher();
213
+ });
129
214
 
130
215
  let innerKeepTraceRange = 0;
131
216
  if (typeof props.keepTraceRange == "number" && props.keepTraceRange > 0) {
132
217
  innerKeepTraceRange = props.keepTraceRange;
133
218
  } else {
134
- if (props.touchFlag > 0) {
219
+ if (touchEnable.value) {
135
220
  // 激活引擎功能的支持
136
221
  JsvUseFeature("MetroWidget", FeatureNames.TouchReceiver);
137
-
138
222
  //触控默认3屏
139
223
  innerKeepTraceRange = 3;
140
224
  } else {
@@ -143,63 +227,49 @@ export const setup = (
143
227
  }
144
228
  }
145
229
 
146
- const modeForExport = ref(FOCUS_MODE);
147
- const mode = {
148
- _mode: FOCUS_MODE,
149
- _touchState: TouchState.IDLE,
150
- _touchCount: 0, // 触控流流程ID,解决fling等事件晚于新的touchDown时引起的混乱问题
151
-
152
- _duringTouch: false,
153
- _duringFling: false,
154
- touchStart(touchCount) {
155
- this._mode = TOUCH_MODE;
156
- modeForExport.value = TOUCH_MODE;
157
- this._touchState = TouchState.TAP;
158
- this._touchCount = touchCount;
159
- },
160
- touchEnd(touchCount) {
161
- if (touchCount == this._touchCount) {
162
- this._touchState = TouchState.IDLE;
163
- }
164
- },
165
- flingStart(touchCount) {
166
- if (touchCount == this._touchCount) {
167
- this._touchState = TouchState.FLING;
230
+ const onInteractionModeChange = (newMode, oldMode) => {
231
+ if (newMode === KEY_MODE) {
232
+ if (touchStateMgr.duringFling()) {
233
+ return;
168
234
  }
169
- },
170
- flingEnd(touchCount) {
171
- if (touchCount == this._touchCount) {
172
- this._touchState = TouchState.IDLE;
235
+ if (focusWhenInTouch) {
236
+ isFocus.value = true;
173
237
  }
174
- },
175
- dragStart(touchCount) {
176
- if (touchCount == this._touchCount) {
177
- this._touchState = TouchState.DRAG;
238
+ const focusItem = _getVisibleFocusableItem();
239
+ if (focusItem) {
240
+ const preFocusItem = getItemById(focusId);
241
+ _changeFocusId(focusItem.id, false);
242
+ if (preFocusItem && preFocusItem.id !== focusItem.id) {
243
+ onItemBlur(preFocusItem);
244
+ }
245
+ onItemFocus(focusItem);
178
246
  }
179
- },
180
- dragEnd(touchCount) {},
181
- keyDown() {
182
- this._mode = FOCUS_MODE;
183
- modeForExport.value = FOCUS_MODE;
184
- this._touchState = TouchState.IDLE;
185
- },
186
- duringFling() {
187
- return this._touchState == TouchState.FLING;
188
- },
189
- duringTouch() {
190
- return this._touchState != TouchState.IDLE;
191
- },
192
- getMode() {
193
- return this._mode;
194
- },
195
- getTouchState() {
196
- return this._touchState;
197
- },
198
- getTouchCount() {
199
- return this._touchCount;
200
- },
247
+ } else if (newMode === TOUCH_MODE) {
248
+ //进入触控模式, 触发onBlur (onBlur中会有各种副作用, 先不触发)
249
+ // onItemBlur(getItemById(focusId));
250
+ } else {
251
+ console.error("unknown interaction mode", newMode);
252
+ }
201
253
  };
254
+ let unwatchInteractionMode = watch(
255
+ JsvInteractionMode,
256
+ onInteractionModeChange
257
+ );
202
258
 
259
+ onActivated(() => {
260
+ if (unwatchInteractionMode) {
261
+ unwatchInteractionMode();
262
+ }
263
+ unwatchInteractionMode = watch(JsvInteractionMode, onInteractionModeChange);
264
+ });
265
+
266
+ onDeactivated(() => {
267
+ unwatchInteractionMode?.();
268
+ unwatchInteractionMode = null;
269
+ isFocus.value = false;
270
+ });
271
+
272
+ const touchStateMgr = new TouchStateMgr(props.name);
203
273
  let innerData = [];
204
274
  let dataList = [];
205
275
  let dataKeyList = [];
@@ -209,7 +279,8 @@ export const setup = (
209
279
  let focusId = 0;
210
280
  let preFocusId = -1;
211
281
  let preEdgeRect = null;
212
- let isFocus = false;
282
+ let isFocus = ref(false);
283
+ let focusWhenInTouch = false;
213
284
  let vertical = props.direction == VERTICAL;
214
285
  let templateItemAdder = null;
215
286
  let permanentItemList = [];
@@ -227,23 +298,39 @@ export const setup = (
227
298
  let freeMoveSlideGapTop = 0;
228
299
  let freeMoveSlideGapLeft = 0;
229
300
 
301
+ //使用fbo加速
302
+ let rootNativeViewId = -1;
303
+ if (props.renderAcc) {
304
+ const metroWidgetBox = new Forge.MetroWidgetBoxView();
305
+ metroWidgetBox.SetEnable(true);
306
+ rootNativeViewId = Forge.sViewStore.add(
307
+ new Forge.ViewInfo(metroWidgetBox, null)
308
+ );
309
+ }
310
+
230
311
  const DEFAULT_ANIMATION_DURATION = 200;
231
312
 
232
313
  //rect {left: number, top: number, width: number, height: number }
233
- const rectVisibleState = (rect) => {
314
+ const rectVisibleState = (rect, rectStart, rectEnd) => {
234
315
  if (!rect) {
235
316
  return 0;
236
317
  }
318
+ if (typeof rectStart == "undefined") {
319
+ rectStart = visibleInfo.startWithPadding;
320
+ }
321
+ if (typeof rectEnd == "undefined") {
322
+ rectEnd = visibleInfo.endWithPadding;
323
+ }
237
324
  let pos_key = vertical ? "top" : "left";
238
325
  let size_key = vertical ? "height" : "width";
239
326
  if (
240
- rect[pos_key] + rect[size_key] - 1 < visibleInfo.start ||
241
- rect[pos_key] > visibleInfo.end
327
+ rect[pos_key] + rect[size_key] - 1 < rectStart ||
328
+ rect[pos_key] > rectEnd
242
329
  ) {
243
330
  return 0; // 完全不可见
244
331
  } else if (
245
- rect[pos_key] < visibleInfo.start ||
246
- rect[pos_key] + rect[size_key] - 1 > visibleInfo.end
332
+ rect[pos_key] < rectStart ||
333
+ rect[pos_key] + rect[size_key] - 1 > rectEnd
247
334
  ) {
248
335
  return 1; // 部分可见
249
336
  } else {
@@ -251,6 +338,15 @@ export const setup = (
251
338
  }
252
339
  };
253
340
 
341
+ //判断是否是大于widget尺寸的item
342
+ const isLargeItem = (itemRect) => {
343
+ if (vertical) {
344
+ return itemRect.height > widgetRectInfo.contentHeight;
345
+ } else {
346
+ return itemRect.width > widgetRectInfo.contentWidth;
347
+ }
348
+ };
349
+
254
350
  //tools
255
351
  const lastOfArray = (array) => {
256
352
  if (array instanceof Array && array.length > 0) {
@@ -304,6 +400,11 @@ export const setup = (
304
400
  });
305
401
  });
306
402
 
403
+ if (props.fullDisplayMode) {
404
+ const totalSize = metroTemplate.getBoundingBoxSize();
405
+ visibleInfo.range = totalSize[size_key];
406
+ }
407
+
307
408
  //更新touch的size
308
409
  updateTouchDivSize();
309
410
 
@@ -315,12 +416,11 @@ export const setup = (
315
416
  const preRect =
316
417
  getItemById(focusId)?.templateInfo?.layoutCache.getPreRect();
317
418
  if (preRect) {
419
+ //anchorPosition记录之前anchor的布局位置,而不是视口位置
318
420
  anchorInfo = {
319
421
  anchorPosition:
320
422
  preRect[pos_key] +
321
- preRect[size_key] * animInfo.anchor -
322
- 1 -
323
- visibleInfo.start,
423
+ preRect[size_key] * animInfo.anchor - 1,
324
424
  anchor: animInfo.anchor,
325
425
  };
326
426
  }
@@ -405,6 +505,11 @@ export const setup = (
405
505
  targetRect = slideTask.params.rect;
406
506
  }
407
507
  break;
508
+ case SlideTaskType.SLIDE_BY_POS_NORMALIZE:
509
+ const position = slideTask.params.position;
510
+ templateItemAdder.tryAddItemByPosition(position);
511
+ targetVisibleStart = normalizeVisibleStart(position, visibleInfo);
512
+ break;
408
513
  default:
409
514
  break;
410
515
  }
@@ -416,45 +521,48 @@ export const setup = (
416
521
  if (anchorInfo) {
417
522
  //保持anchor
418
523
  const focusItem = getItemById(focusId);
419
- let start =
420
- focusItem.templateInfo[pos_key] +
421
- focusItem.templateInfo[size_key] * anchorInfo.anchor -
422
- 1 -
423
- anchorInfo.anchorPosition;
524
+ //新旧item anchor之间的差值
525
+ let delta = focusItem.templateInfo[pos_key] +
526
+ focusItem.templateInfo[size_key] * anchorInfo.anchor -
527
+ 1 -
528
+ anchorInfo.anchorPosition;
529
+
530
+ //delta是新旧item anchor之间的差值,需要转换为视口位置
531
+ let start = visibleInfo.start + delta;
424
532
  let totalSize = metroTemplate.getBoundingBoxSize();
425
533
  start = Math.min(
426
534
  Math.max(0, start),
427
535
  totalSize[size_key] - visibleInfo.range
428
536
  );
429
537
  //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
- );
538
+ if (JsvInteractionMode.value != TOUCH_MODE) {
539
+ if (focusItem.index == 0) {
540
+ if (start > focusItem.templateInfo[pos_key]) {
541
+ start = 0;
542
+ }
543
+ } else if (
544
+ focusItem.templateInfo.index == metroTemplate.getTailItemIndex()
545
+ ) {
546
+ if (start + visibleInfo.range > focusItem.templateInfo[pos_key]) {
547
+ start = Math.max(
548
+ focusItem.templateInfo[size_key] +
549
+ focusItem.templateInfo[pos_key] -
550
+ visibleInfo.range,
551
+ 0
552
+ );
553
+ }
444
554
  }
445
555
  }
446
- targetVisibleStart = normalizeVisibleStart(
447
- start,
448
- focusItem.templateInfo,
449
- focusItem.templateInfo.index,
450
- visibleInfo
451
- );
556
+ targetVisibleStart = normalizeVisibleStart(start, visibleInfo);
557
+ slideDoAnim = resizeAnimInfo.doAnim;
452
558
  } else {
453
- targetRect = getItemById(focusId).templateInfo;
559
+ //260410fix: 触控的时候不需要做把item移动到可见位置的逻辑
560
+ if (JsvInteractionMode.value != TOUCH_MODE) {
561
+ targetRect = getItemById(focusId)?.templateInfo;
562
+ slideDoAnim = resizeAnimInfo.doAnim;
563
+ }
454
564
  }
455
- slideDoAnim = resizeAnimInfo.doAnim;
456
565
  }
457
-
458
566
  if (targetRect) {
459
567
  const v = visibleInfo.copy();
460
568
  let preInfo = null;
@@ -464,7 +572,7 @@ export const setup = (
464
572
  if (preInfo) {
465
573
  let totalSize = metroTemplate.getBoundingBoxSize();
466
574
  v.start = Math.min(
467
- Math.max(0, targetRect[pos_key] - preInfo[pos_key] + v.start),
575
+ v.start,
468
576
  Math.max(0, totalSize[size_key] - v.range)
469
577
  );
470
578
  preInfo[pos_key] += v.start - visibleInfo.start;
@@ -507,14 +615,19 @@ export const setup = (
507
615
 
508
616
  //updatePage
509
617
  let updateHandler;
618
+ let updatePageRange = {
619
+ start: visibleInfo.startWithPadding - innerKeepTraceRange * pageRange,
620
+ end: visibleInfo.endWithPadding + innerKeepTraceRange * pageRange,
621
+ };
510
622
  taskManager.run(() => {
511
623
  updateHandler = pageUpdater.update(
512
624
  metroTemplate,
513
- visibleInfo.startWithPadding - innerKeepTraceRange * pageRange,
514
- visibleInfo.endWithPadding + innerKeepTraceRange * pageRange,
625
+ updatePageRange.start,
626
+ updatePageRange.end,
515
627
  focusId,
516
628
  mergeTmp,
517
- permanentItemList
629
+ permanentItemList,
630
+ props.fullDisplayMode
518
631
  );
519
632
  return () => {
520
633
  updateHandler.recover();
@@ -553,7 +666,7 @@ export const setup = (
553
666
  });
554
667
  };
555
668
 
556
- if (renderItem.mounted.value) {
669
+ if (toRaw(renderItem.mounted).value) {
557
670
  doItemSlide(renderItem.rootDiv);
558
671
  } else {
559
672
  taskManager.run(() => {
@@ -586,6 +699,15 @@ export const setup = (
586
699
  };
587
700
  }
588
701
  executeSlide(visibleInfo.start, animInfo, updateHandler);
702
+ } else {
703
+ //不滚动的时候检查是否已经更新可视的item
704
+ const applyedRange = pageUpdater.getApplyedRange();
705
+ if (
706
+ applyedRange.start != updatePageRange.start ||
707
+ applyedRange.end != updatePageRange.end
708
+ ) {
709
+ updateHandler.apply();
710
+ }
589
711
  }
590
712
 
591
713
  //回调
@@ -609,6 +731,16 @@ export const setup = (
609
731
  };
610
732
  });
611
733
  }
734
+ if (resizeList.length > 0 && props.onSizeChange) {
735
+ taskManager.run(() => {
736
+ const handler = setTimeout(() => {
737
+ _onSizeChange();
738
+ }, 0);
739
+ return () => {
740
+ clearTimeout(handler);
741
+ };
742
+ });
743
+ }
612
744
  };
613
745
  const taskManager = new TaskManager(onAddTask);
614
746
  const animationManager = new AnimationManager();
@@ -648,6 +780,7 @@ export const setup = (
648
780
  } else {
649
781
  updateHandler.apply();
650
782
  }
783
+ _syncOnScroll();
651
784
  taskManager.run(() => {
652
785
  const handler = setTimeout(() => {
653
786
  _onScroll();
@@ -695,6 +828,18 @@ export const setup = (
695
828
  };
696
829
  };
697
830
 
831
+ const _getPostionRelativeToRoot = (index) => {
832
+ let templateInfo = getItemByIndex(index).templateInfo;
833
+ let x_offset = vertical ? 0 : -visibleInfo.start;
834
+ let y_offset = vertical ? -visibleInfo.start : 0;
835
+ return {
836
+ left: templateInfo.left + x_offset + widgetRectInfo.padding.left,
837
+ top: templateInfo.top + y_offset + widgetRectInfo.padding.top,
838
+ width: templateInfo.width,
839
+ height: templateInfo.height,
840
+ };
841
+ };
842
+
698
843
  const _getPosition = (index) => {
699
844
  let templateInfo = getItemByIndex(index).templateInfo;
700
845
  let x_offset = vertical ? 0 : -visibleInfo.start;
@@ -767,38 +912,57 @@ export const setup = (
767
912
  if (!item) {
768
913
  return;
769
914
  }
770
- if (isFocus) {
915
+ if (isFocus.value) {
771
916
  item.onClick();
772
917
  }
773
918
  };
774
919
 
775
920
  const onItemBlur = (blurItem) => {
776
921
  if (!blurItem) return;
777
- setItemZIndex(blurItem, 0, false);
778
- if (isFocus) {
922
+ if (isFocus.value) {
779
923
  blurItem.onBlur();
780
924
  }
781
925
  };
782
926
 
927
+ const onItemIgnore = (item) => {
928
+ if (!item) return;
929
+ setItemZIndex(item, 0, false);
930
+ item.onIgnore();
931
+ }
932
+
783
933
  let gazeIndex = -1;
934
+ let preGazeIndex = -1;
935
+ let callGazeAfterUpdate = false;
936
+ const onItemGaze = (item, rect) => {
937
+ if (!item || item.index == gazeIndex) { return; }
938
+ setItemZIndex(item, innerData.length, true);
939
+ preGazeIndex = gazeIndex;
940
+ gazeIndex = item.index;
941
+ if (toRaw(item.mounted).value) {
942
+ item.onGaze(rect);
943
+ } else {
944
+ callGazeAfterUpdate = true;
945
+ }
946
+ }
947
+
948
+ let topZItemIndex = -1;
784
949
  const onItemFocus = (focusItem, rect) => {
785
950
  //触控模式不触发item的onFocus
786
- if (!focusItem) return;
951
+ if (!focusItem) return false;
952
+ if (topZItemIndex != focusItem.index) {
953
+ setItemZIndex(getItemByIndex(topZItemIndex), 0, false);
954
+ }
787
955
  setItemZIndex(focusItem, innerData.length, true);
788
- if (isFocus) {
956
+ topZItemIndex = focusItem.index;
957
+ if (JsvInteractionMode.value == KEY_MODE && isFocus.value) {
789
958
  _itemOnFocusSideEffect(focusItem, rect);
959
+ if (spatialNavigator) {
960
+ spatialNavigator.setFocus(focusItem.getSpatialNavNode());
961
+ }
790
962
  }
791
963
 
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) {
964
+ if (toRaw(focusItem.mounted).value) {
965
+ if (JsvInteractionMode.value == KEY_MODE && isFocus.value) {
802
966
  focusItem.onFocus(rect);
803
967
  }
804
968
  return true;
@@ -812,7 +976,7 @@ export const setup = (
812
976
  if (!item) {
813
977
  return;
814
978
  }
815
- if (isFocus) {
979
+ if (isFocus.value) {
816
980
  item.onLongPress();
817
981
  }
818
982
  };
@@ -822,7 +986,7 @@ export const setup = (
822
986
  if (gazeIndex != gazeItem.templateInfo.index) {
823
987
  let preGazeItem = getItemByIndex(gazeIndex);
824
988
  if (preGazeItem) {
825
- preGazeItem.onIgnore();
989
+ onItemIgnore(preGazeItem);
826
990
  }
827
991
  gazeIndex = gazeItem.templateInfo.index;
828
992
  gazeItem.onGaze(null);
@@ -853,6 +1017,7 @@ export const setup = (
853
1017
  if (id == focusId || innerData.length <= 0) {
854
1018
  return;
855
1019
  }
1020
+ mRectCache.clean();
856
1021
  //有外部触发的滚动时, 取消load
857
1022
  tryCancelDelayLoad();
858
1023
  templateItemAdder.tryAddItemById(id);
@@ -861,7 +1026,9 @@ export const setup = (
861
1026
  const nextTemplateInfo = next_focus_item.templateInfo;
862
1027
  _changeFocusId(nextTemplateInfo.id);
863
1028
  const preFocusItem = getItemById(preFocusId);
1029
+ onItemIgnore(preFocusItem)
864
1030
  onItemBlur(preFocusItem);
1031
+ onItemGaze(next_focus_item, preEdgeRect);
865
1032
  onItemFocus(next_focus_item, preEdgeRect);
866
1033
  if (needSlide) {
867
1034
  slideToItem(id2Index(id), doAnim);
@@ -873,19 +1040,20 @@ export const setup = (
873
1040
  }
874
1041
  }
875
1042
 
876
- const curTemplateInfo = getItemById(focusId).templateInfo;
877
-
878
- let x_off_set = curTemplateInfo.left - nextTemplateInfo.left;
879
- let y_off_set = curTemplateInfo.top - nextTemplateInfo.top;
880
- preEdgeRect = {
881
- direction: null,
882
- rect: {
883
- x: x_off_set,
884
- y: y_off_set,
885
- width: curTemplateInfo.width,
886
- height: curTemplateInfo.height,
887
- },
888
- };
1043
+ const curTemplateInfo = getItemById(focusId)?.templateInfo;
1044
+ if (curTemplateInfo) {
1045
+ let x_off_set = curTemplateInfo.left - nextTemplateInfo.left;
1046
+ let y_off_set = curTemplateInfo.top - nextTemplateInfo.top;
1047
+ preEdgeRect = {
1048
+ direction: null,
1049
+ rect: {
1050
+ x: x_off_set,
1051
+ y: y_off_set,
1052
+ width: curTemplateInfo.width,
1053
+ height: curTemplateInfo.height,
1054
+ },
1055
+ };
1056
+ }
889
1057
  unlock?.();
890
1058
  }
891
1059
  };
@@ -950,7 +1118,7 @@ export const setup = (
950
1118
 
951
1119
  targetItem.itemConfig.focusZIndex = f;
952
1120
  targetItem.itemConfig.normalZIndex = n;
953
- const focused = isFocus && focusId == index2Id(index);
1121
+ const focused = isFocus.value && focusId == index2Id(index);
954
1122
  setItemZIndex(targetItem, focused ? f : n, focused);
955
1123
  }
956
1124
  };
@@ -960,6 +1128,9 @@ export const setup = (
960
1128
  doAnim,
961
1129
  updateParam = { mergeTmp: false }
962
1130
  ) => {
1131
+ if (props.fullDisplayMode) {
1132
+ return;
1133
+ }
963
1134
  if (
964
1135
  slideLock ||
965
1136
  position == (vertical ? slideDivTop.value : slideDivLeft.value)
@@ -986,6 +1157,9 @@ export const setup = (
986
1157
  preItem = undefined,
987
1158
  force = false
988
1159
  ) => {
1160
+ if (props.fullDisplayMode) {
1161
+ return;
1162
+ }
989
1163
  taskManager.addTask(
990
1164
  TaskType.SLIDE,
991
1165
  {
@@ -1006,6 +1180,9 @@ export const setup = (
1006
1180
  slideToDivInner(div, doAnim);
1007
1181
  };
1008
1182
  const slideToDivInner = (div, doAnim, direction = undefined) => {
1183
+ if (props.fullDisplayMode) {
1184
+ return;
1185
+ }
1009
1186
  if (div) {
1010
1187
  taskManager.addTask(
1011
1188
  TaskType.SLIDE,
@@ -1019,6 +1196,9 @@ export const setup = (
1019
1196
  }
1020
1197
  };
1021
1198
  const slideToRectInner = (rect, doAnim, direction, force) => {
1199
+ if (props.fullDisplayMode) {
1200
+ return;
1201
+ }
1022
1202
  if (
1023
1203
  rect &&
1024
1204
  typeof rect.left == "number" &&
@@ -1038,6 +1218,18 @@ export const setup = (
1038
1218
  );
1039
1219
  }
1040
1220
  };
1221
+
1222
+ const slideToNormalize = (position, doAnim) => {
1223
+ if (props.fullDisplayMode) {
1224
+ return;
1225
+ }
1226
+ taskManager.addTask(
1227
+ TaskType.SLIDE,
1228
+ { position, doAnim },
1229
+ SlideTaskType.SLIDE_BY_POS_NORMALIZE
1230
+ );
1231
+ };
1232
+
1041
1233
  const slideToRect = (rect, doAnim, direction = undefined) => {
1042
1234
  slideToRectInner(rect, doAnim, direction, false);
1043
1235
  };
@@ -1066,26 +1258,23 @@ export const setup = (
1066
1258
  const refreshData = (forceUpdate, slideToFocus = "auto") => {
1067
1259
  //由于data不支持reactive, 因此数据的更新只通过provideData
1068
1260
  if (!props.provideData) {
1069
- console.error("refreshData: provideData is null.");
1261
+ errorLogger("refreshData: provideData is null.");
1070
1262
  return;
1071
1263
  }
1072
1264
  try {
1073
1265
  let newData = toRaw(safeProvideData()).concat();
1074
1266
  if (newData instanceof Array) {
1075
1267
  let maxSameIndex = -1;
1076
- let layoutChange = false;
1268
+ let layoutChange = 0; //0: 不需要更新布局, 1: 需要更新布局, 2: 仅删除数据
1077
1269
  let onlyDataChangeList = [];
1270
+ let preGazeId = index2Id(gazeIndex);
1078
1271
  let targetFocusId = focusId;
1272
+ let targetGazeIndex = gazeIndex;
1079
1273
  let curFocusItemChanged = true;
1080
1274
  if (newData.length == 0) {
1081
- layoutChange = true;
1082
- targetFocusId = -1;
1275
+ layoutChange = 1;
1276
+ cleanFocusStatus();
1083
1277
  } else {
1084
- if (focusId < 0) {
1085
- targetFocusId = 0;
1086
- } else if (focusId >= newData.length) {
1087
- targetFocusId = newData.length - 1;
1088
- }
1089
1278
  if (!forceUpdate) {
1090
1279
  const curFocusIndex = id2Index(focusId);
1091
1280
  for (let i = 0; i < dataList.length; ++i) {
@@ -1108,12 +1297,13 @@ export const setup = (
1108
1297
  } else {
1109
1298
  const newMeasureItem = props.measures(newItem);
1110
1299
  const oldMeasureItem = props.measures(oldItem);
1111
- layoutChange = ifLayoutChange(
1300
+ const changed = ifLayoutChange(
1112
1301
  props.layoutType,
1113
1302
  oldMeasureItem,
1114
1303
  newMeasureItem
1115
1304
  );
1116
- if (layoutChange) {
1305
+ if (changed) {
1306
+ layoutChange = 1;
1117
1307
  break;
1118
1308
  } else {
1119
1309
  if (i < innerData.length) {
@@ -1129,10 +1319,11 @@ export const setup = (
1129
1319
  } else {
1130
1320
  if (i >= newData.length) {
1131
1321
  //item减少需要布局改变
1132
- layoutChange = true;
1322
+ layoutChange = 2;
1133
1323
  break;
1134
1324
  } else {
1135
1325
  //数据中存在undefined item
1326
+ errorLogger("undefined item in data list.");
1136
1327
  throw new Error("undefined item in data list.", i, newData);
1137
1328
  }
1138
1329
  }
@@ -1140,14 +1331,13 @@ export const setup = (
1140
1331
  }
1141
1332
  }
1142
1333
 
1143
- // 刷新数据时, 重置gazeIndex
1144
- if (forceUpdate || curFocusItemChanged || targetFocusId != focusId) {
1145
- gazeIndex = -1;
1146
- }
1334
+ //判断是否需要重新onGaze
1335
+ let needReOnGaze = false;
1147
1336
  //更新template
1337
+ const oldDataCount = dataList.length;
1148
1338
  dataList = newData;
1149
1339
  dataKeyList = dataList.map((i) => i[DATA_ID_KEY]);
1150
- if (forceUpdate || layoutChange) {
1340
+ if (forceUpdate || layoutChange == 1) {
1151
1341
  //需要更新布局
1152
1342
  pageUpdateToken.value++;
1153
1343
  //数据更改
@@ -1157,7 +1347,8 @@ export const setup = (
1157
1347
  props.direction,
1158
1348
  props.supportHistoryPath,
1159
1349
  props.layoutType,
1160
- templateMode
1350
+ templateMode,
1351
+ errorLogger
1161
1352
  );
1162
1353
  innerData = [];
1163
1354
  templateItemAdder = new TemplateItemAdder(
@@ -1167,116 +1358,179 @@ export const setup = (
1167
1358
  pageRange,
1168
1359
  _onTemplateItemAdd,
1169
1360
  props.name,
1170
- _onTemplateAddDone
1361
+ getOnTemplateAddDone(true),
1362
+ errorLogger
1171
1363
  );
1172
- if (props.onScroll || props.touchFlag > 0) {
1173
- templateItemAdder.tryAddItemByIndex(dataList.length - 1);
1364
+ if (props.onScroll || touchEnable.value || props.fullDisplayMode) {
1365
+ templateItemAdder.tryAddItemByIndex(dataList.length - 1, getOnTemplateAddDone(false));
1174
1366
  } else {
1175
- templateItemAdder.tryAddItemById(targetFocusId);
1367
+ //加到旧数据的个数,保险一点
1368
+ templateItemAdder.tryAddItemByIndex(Math.min(dataList.length, oldDataCount), getOnTemplateAddDone(false));
1176
1369
  }
1370
+ needReOnGaze = true;
1371
+ } else if (layoutChange == 2) {
1372
+ //仅删除
1373
+ templateItemAdder.removeItemTo(dataList.length);
1374
+ innerData.splice(dataList.length);
1177
1375
  } else {
1178
1376
  templateItemAdder.updateData(newData);
1179
1377
  if (maxSameIndex < newData.length - 1) {
1180
1378
  //追加数据
1181
- if (props.onScroll || props.touchFlag > 0) {
1182
- templateItemAdder.tryAddItemByIndex(dataList.length - 1);
1379
+ if (props.onScroll || touchEnable.value || props.fullDisplayMode) {
1380
+ templateItemAdder.tryAddItemByIndex(dataList.length - 1, getOnTemplateAddDone(false));
1183
1381
  } else {
1184
- templateItemAdder.tryAddItemById(targetFocusId);
1382
+ templateItemAdder.tryAddItemByIndex(Math.min(dataList.length, oldDataCount), getOnTemplateAddDone(false));
1185
1383
  }
1186
1384
  }
1385
+ }
1386
+ //更新focudId 和 gazeIndex
1387
+ let lastFocusableItemId = metroTemplate.idsMap.length - 1;
1187
1388
 
1188
- //仅用户数据变更
1189
- if (onlyDataChangeList.length > 0) {
1190
- for (let i of onlyDataChangeList) {
1191
- if (i.index < innerData.length) {
1192
- innerData[i.index].updateCustomData(
1193
- i.data,
1194
- _getItemConfigFromMeasursObj(i.measureObj)
1195
- );
1196
- innerData[i.index].enableTap = i.measureObj.enableTap ?? false;
1197
- } else {
1198
- //之后的数据未布局, 尚未添加到innerData中
1199
- break;
1389
+ if (lastFocusableItemId < 0) {
1390
+ targetFocusId = -1;
1391
+ targetGazeIndex = -1;
1392
+ } else {
1393
+ targetFocusId = Math.max(0, Math.min(lastFocusableItemId, focusId));
1394
+ targetGazeIndex = id2Index(Math.max(0, Math.min(lastFocusableItemId, preGazeId)));
1395
+ }
1396
+
1397
+ //仅用户数据变更
1398
+ if (onlyDataChangeList.length > 0) {
1399
+ for (let i of onlyDataChangeList) {
1400
+ if (i.index < innerData.length) {
1401
+ if (i.index == gazeIndex) {
1402
+ needReOnGaze = true;
1200
1403
  }
1404
+ innerData[i.index].updateCustomData(
1405
+ i.data,
1406
+ _getItemConfigFromMeasursObj(i.measureObj)
1407
+ );
1408
+ innerData[i.index].enableTap = i.measureObj.enableTap ?? false;
1409
+ } else {
1410
+ //之后的数据未布局, 尚未添加到innerData中
1411
+ break;
1201
1412
  }
1202
1413
  }
1203
1414
  }
1415
+
1416
+ //数据更新,清理缓存的范围信息,避免旧的范围与新的有冲突
1417
+ pageUpdater.cleanCache();
1204
1418
  //更新可视
1205
1419
  const updater = pageUpdater.update(
1206
1420
  metroTemplate,
1207
1421
  visibleInfo.startWithPadding - innerKeepTraceRange * pageRange,
1208
1422
  visibleInfo.endWithPadding + innerKeepTraceRange * pageRange,
1209
- focusId,
1423
+ index2Id(targetGazeIndex),
1210
1424
  false,
1211
- permanentItemList
1425
+ permanentItemList,
1426
+ props.fullDisplayMode
1212
1427
  );
1213
1428
  updater.apply();
1429
+ if (!renderData.value.some((i) => i.templateInfo.index == gazeIndex)) {
1430
+ needReOnGaze = false;
1431
+ }
1214
1432
 
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);
1433
+ let preVisibleStart = visibleInfo.start;
1434
+
1435
+ if (targetGazeIndex != gazeIndex || layoutChange == 2) {
1436
+ //仅在删除数据的时候更新, 其他情况都保留之前的滚动信息
1437
+ //由于template add done 回调里会更新box, 需要在template重新创建前, 重置所有的滚动信息
1438
+ visibleInfo = visibleInfo.copy();
1439
+ visibleInfo.start = 0;
1440
+ visibleInfo._startMax = 0;
1441
+ slideDivLeft.value = 0;
1442
+ slideDivTop.value = 0;
1443
+ }
1444
+
1445
+ let needSlide = false;
1446
+ let targetRect = mRectCache.getCurRect() ?? mRectCache.getPreRect();
1447
+ if (targetGazeIndex != gazeIndex) {
1448
+ needSlide = true;
1449
+ } else if (slideToFocus == "enable") {
1450
+ needSlide = true;
1451
+ } else if (slideToFocus == "disable") {
1452
+ needSlide = false;
1453
+ } else if (layoutChange == 2) {
1454
+ needSlide = true;
1221
1455
  } else {
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 {
1456
+ //保持原有焦点的位置
1457
+ if (JsvInteractionMode.value == KEY_MODE) {
1233
1458
  if (targetRect) {
1234
- needSlide = rectVisibleState(targetRect) !== 0;
1459
+ needSlide = rectVisibleState(targetRect) !== 2;
1235
1460
  } else {
1236
1461
  needSlide =
1237
- rectVisibleState(getItemById(focusId)?.templateInfo) !== 0;
1462
+ rectVisibleState(getItemByIndex(targetGazeIndex)?.templateInfo) !==
1463
+ 2;
1238
1464
  }
1465
+ } else {
1466
+ //touch模式下,不需要滑动
1239
1467
  }
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
- }
1468
+ }
1469
+ if (targetFocusId != focusId) {
1470
+ //重置所有的滚动信息
1471
+ _changeFocusId(targetFocusId, false);
1472
+ }
1248
1473
 
1249
- if (targetFocusId != focusId) {
1250
- //重置所有的滚动信息
1251
- _changeFocusId(targetFocusId, false);
1474
+ const gazeItem = getItemByIndex(targetGazeIndex);
1475
+ const focusItem = getItemById(focusId);
1476
+ if (gazeItem) {
1477
+ //数据刷新时, 重置preEdgeRect, 否则再嵌套模式下, 会使用上一次的preEdgeRect, 导致子又findNearestByRect
1478
+ preEdgeRect = null;
1479
+ if (needSlide) {
1480
+ if (layoutChange == 2) {
1481
+ slideToNormalize(preVisibleStart, false);
1482
+ } else if (targetRect) {
1483
+ slideToRectInner(targetRect, false, 0, true);
1484
+ } else if (
1485
+ focusItem && focusItem.itemConfig.itemSlide ==
1486
+ METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS
1487
+ ) {
1488
+ //只有这个item是控制滚动的才slide, 其他如嵌套时不需要slide
1489
+ slideToItemInner(targetGazeIndex, false, 0, 0, true);
1490
+ }
1252
1491
  }
1492
+ } else {
1493
+ slideToInner(0, false);
1494
+ preEdgeRect = null;
1495
+ mRectCache.clean();
1496
+ }
1253
1497
 
1254
- const focusItem = getItemById(focusId);
1498
+ //与交互模式相关的处理
1499
+ if (JsvInteractionMode.value == TOUCH_MODE) {
1500
+ //TODO touch模式的refresh还是有问题,
1501
+ // 1. 点击删除item, 会触发onDragStart, 这里onDragStart正好更新了visibleInfo.start导致可以运行, 但这里还是要正确更新visibleInfo.start
1502
+ // let divPos = vertical ? slideDivTop.value + freeMoveSlideGapTop : slideDivLeft.value + freeMoveSlideGapLeft;
1503
+ // visibleInfo.start = getVisibleStart(data);
1504
+
1505
+ updateTouchBoxCondition();
1506
+ if (gazeIndex != targetGazeIndex) {
1507
+ gazeIndex = targetGazeIndex;
1508
+ }
1509
+ if (needReOnGaze) {
1510
+ getItemByIndex(gazeIndex)?.onGaze(null);
1511
+ }
1512
+ } else {
1513
+ if (gazeItem) {
1514
+ onItemGaze(gazeItem, null);
1515
+ }
1255
1516
  if (focusItem) {
1256
- //数据刷新时, 重置preEdgeRect, 否则再嵌套模式下, 会使用上一次的preEdgeRect, 导致子又findNearestByRect
1257
- preEdgeRect = null;
1258
1517
  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
1518
  }
1275
1519
  }
1276
1520
  }
1277
1521
  } catch (e) {
1278
1522
  console.log(TAG, "refresh error", e);
1279
1523
  }
1524
+
1525
+ //refresh完成后, 重置renderBreak
1526
+ if (props.enableItemRenderBreak !== innerEnableRenderBreak) {
1527
+ nextTick(() => {
1528
+ innerEnableRenderBreak = props.enableItemRenderBreak;
1529
+ window.JsView?.setRenderBreakEnable?.(true);
1530
+ vRenderBreakChanged = false;
1531
+ });
1532
+ }
1533
+ _onSizeChange();
1280
1534
  };
1281
1535
 
1282
1536
  const getVisibleItems = () => {
@@ -1323,7 +1577,7 @@ export const setup = (
1323
1577
  ) {
1324
1578
  _moveToNext(0, 1);
1325
1579
  } else {
1326
- console.error(TAG, "moveFocus direction is invalid.", direction);
1580
+ errorLogger(TAG, "moveFocus direction is invalid.", direction);
1327
1581
  }
1328
1582
  };
1329
1583
 
@@ -1362,6 +1616,99 @@ export const setup = (
1362
1616
  }
1363
1617
  };
1364
1618
 
1619
+ let vRenderBreakChanged = false;
1620
+ const tmpDisableRenderBreak = () => {
1621
+ if (props.enableItemRenderBreak) {
1622
+ innerEnableRenderBreak = false;
1623
+ window.JsView?.setRenderBreakEnable?.(false);
1624
+ vRenderBreakChanged = true;
1625
+ }
1626
+ };
1627
+
1628
+ const getCurrentVisibleRange = () => {
1629
+ return {
1630
+ leftTop: {
1631
+ x: props.direction == VERTICAL ? 0 : visibleInfo.startWithPadding,
1632
+ y: props.direction == VERTICAL ? visibleInfo.startWithPadding : 0,
1633
+ },
1634
+ rightBottom: {
1635
+ x:
1636
+ props.direction == VERTICAL
1637
+ ? props.width
1638
+ : visibleInfo.endWithPadding,
1639
+ y:
1640
+ props.direction == VERTICAL
1641
+ ? visibleInfo.endWithPadding
1642
+ : props.height,
1643
+ },
1644
+ };
1645
+ };
1646
+
1647
+ //获取指定区间内可视item的树(MetroWidget嵌套时)
1648
+ const getItemVisibleState = (leftTop, rightBottom) => {
1649
+ //传过来的区域已经是真实区域了,不需要再减去padding
1650
+ const rangeStart =
1651
+ props.direction == VERTICAL
1652
+ ? leftTop.y
1653
+ : leftTop.x;
1654
+ const rangeEnd =
1655
+ props.direction == VERTICAL
1656
+ ? rightBottom.y
1657
+ : rightBottom.x;
1658
+ const [startIndex, endIndex] = metroTemplate.getVisibleItemList(
1659
+ rangeStart,
1660
+ rangeEnd,
1661
+ gazeIndex
1662
+ );
1663
+ const result = [];
1664
+ for (let index = startIndex; index <= endIndex; index++) {
1665
+ const item = getItemByIndex(index);
1666
+ if (item) {
1667
+ const s = rectVisibleState(item.templateInfo, rangeStart, rangeEnd);
1668
+ if (s == 0) {
1669
+ //getVisibleItemList返回的区间内可能还有不可见的item
1670
+ continue;
1671
+ }
1672
+ //rangeStart和rangeEnd转化为相对与item的相对位置
1673
+ const itemLeftTop = {
1674
+ x: item.templateInfo.left + widgetRectInfo.padding.left,
1675
+ y: item.templateInfo.top + widgetRectInfo.padding.top,
1676
+ };
1677
+ const newLeftTop = {
1678
+ x: leftTop.x - itemLeftTop.x,
1679
+ y: leftTop.y - itemLeftTop.y,
1680
+ };
1681
+ const newRightBottom = {
1682
+ x: rightBottom.x - itemLeftTop.x,
1683
+ y: rightBottom.y - itemLeftTop.y,
1684
+ };
1685
+ const itemVisibleState = item.onGetItemVisibleState(
1686
+ newLeftTop,
1687
+ newRightBottom
1688
+ );
1689
+ let info = {
1690
+ name: props.name,
1691
+ index: index,
1692
+ visibleState: s == 1 ? "partial" : "full",
1693
+ children: itemVisibleState ? itemVisibleState : [],
1694
+ widgetHandler: exportObject,
1695
+ };
1696
+ if (index == gazeIndex) {
1697
+ result.unshift(info);
1698
+ } else {
1699
+ result.push(info);
1700
+ }
1701
+ }
1702
+ }
1703
+ return result;
1704
+ };
1705
+
1706
+ const cleanFocusStatus = () => {
1707
+ preFocusId = -1;
1708
+ focusId = -1;
1709
+ gazeIndex = -1;
1710
+ };
1711
+
1365
1712
  const exportObject = {
1366
1713
  lockSlide,
1367
1714
  unlockSlide,
@@ -1386,6 +1733,11 @@ export const setup = (
1386
1733
  cancelDelayLoad: tryCancelDelayLoad,
1387
1734
  setSensorSensitivity,
1388
1735
  getItemLayoutInfo: _getTemplatePosition,
1736
+ tmpDisableRenderBreak,
1737
+ getItemVisibleState,
1738
+ getCurrentVisibleRange,
1739
+ cleanFocusStatus,
1740
+ getName: () => props.name,
1389
1741
  };
1390
1742
 
1391
1743
  const _calculateNearestItemByRect = (visibleSet, enter_rect_info) => {
@@ -1582,25 +1934,20 @@ export const setup = (
1582
1934
  };
1583
1935
 
1584
1936
  const onDispatchKeyDown = (ev) => {
1585
- if (mode.getMode() == TOUCH_MODE && !mode.duringTouch()) {
1586
- if (
1587
- ev.keyCode == 37 ||
1588
- ev.keyCode == 38 ||
1589
- ev.keyCode == 39 ||
1590
- ev.keyCode == 40
1591
- ) {
1592
- //只有在上下左右键切换为focus_mode
1593
- mode.keyDown();
1594
- //touch切换为focus的首次按键只显示焦点
1595
- const focusItem = _getVisibleFocusableItem();
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);
1603
- }
1937
+ if (
1938
+ ev.keyCode == 37 ||
1939
+ ev.keyCode == 38 ||
1940
+ ev.keyCode == 39 ||
1941
+ ev.keyCode == 40
1942
+ ) {
1943
+ //fling过程中不处理按键
1944
+ if (touchStateMgr.duringFling()) {
1945
+ window.JsView?.changeInteractionMode?.("touch", "key");
1946
+ }
1947
+
1948
+ if (JsvInteractionMode.value == TOUCH_MODE) {
1949
+ JsvInteractionMode.value = KEY_MODE;
1950
+ touchStateMgr.touchEnd(touchStateMgr.getTouchCount());
1604
1951
  return true;
1605
1952
  }
1606
1953
  }
@@ -1659,11 +2006,9 @@ export const setup = (
1659
2006
  preStartKeyDownTime = ev.timeStamp;
1660
2007
  }
1661
2008
  tryCancelDelayLoad();
1662
- if (mode.getMode() == TOUCH_MODE) {
1663
- if (mode.duringTouch()) {
1664
- //touch过程中的按键不处理
1665
- return true;
1666
- }
2009
+ if (JsvInteractionMode.value == TOUCH_MODE && touchStateMgr.duringTouch()) {
2010
+ //touch过程中的按键不处理
2011
+ return true;
1667
2012
  }
1668
2013
 
1669
2014
  if (_moveByKey(ev.keyCode)) {
@@ -1672,7 +2017,7 @@ export const setup = (
1672
2017
  if (ev.keyCode == 13) {
1673
2018
  const curFocusItem = getItemById(focusId);
1674
2019
  clickDownReceived = true;
1675
- if (curFocusItem.itemConfig.enableLongPress) {
2020
+ if (curFocusItem?.itemConfig.enableLongPress) {
1676
2021
  if (
1677
2022
  ev.repeat &&
1678
2023
  ev.timeStamp - preStartKeyDownTime > LONGPRESS_TIMEOUT &&
@@ -1707,13 +2052,21 @@ export const setup = (
1707
2052
  }
1708
2053
  }
1709
2054
 
1710
- const _onTemplateAddDone = () => {
1711
- //update slideDiv size
1712
- let preTouchW = touchDivSize.width;
1713
- let preTouchH = touchDivSize.height;
1714
- updateTouchDivSize();
1715
- if (preTouchW !== touchDivSize.width || preTouchH !== touchDivSize.height) {
1716
- updateTouchBoxCondition();
2055
+ const getOnTemplateAddDone = (needUpdateBox) => {
2056
+ return () => {
2057
+ //update slideDiv size
2058
+ let preTouchW = touchDivSize.width;
2059
+ let preTouchH = touchDivSize.height;
2060
+ updateTouchDivSize();
2061
+ if (needUpdateBox) {
2062
+ if (preTouchW !== touchDivSize.width || preTouchH !== touchDivSize.height) {
2063
+ updateTouchBoxCondition();
2064
+ }
2065
+ }
2066
+ if (props.fullDisplayMode) {
2067
+ let size_key = vertical ? "height" : "width";
2068
+ visibleInfo.range = metroTemplate.getBoundingBoxSize()[size_key];
2069
+ }
1717
2070
  }
1718
2071
  };
1719
2072
 
@@ -1744,9 +2097,39 @@ export const setup = (
1744
2097
  measuresObj.itemSlide ?? METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS,
1745
2098
  showSkeleton: measuresObj.showSkeleton ?? true,
1746
2099
  enableLongPress: measuresObj.enableLongPress ?? props.enableLongPress,
2100
+ bindSpatialNav: measuresObj.bindSpatialNav ?? false,
1747
2101
  };
1748
2102
  };
1749
2103
 
2104
+ const rootPositionCache = {
2105
+ cacheToken: -1,
2106
+ cacheTargetDiv: undefined,
2107
+ cacheRect: undefined,
2108
+ }
2109
+ const getItemPositionWithCache = (token, target, itemIndex) => {
2110
+ if (!target || !rootDiv.value) {
2111
+ return undefined;
2112
+ }
2113
+ let rootRect;
2114
+ if (rootPositionCache.cacheToken === token
2115
+ && rootPositionCache.cacheTargetDiv === target
2116
+ && rootPositionCache.cacheRect) {
2117
+ rootRect = rootPositionCache.cacheRect;
2118
+ } else {
2119
+ rootRect = rootDiv.value.jsvGetRelativePosition(target);
2120
+ rootPositionCache.cacheToken = token;
2121
+ rootPositionCache.cacheTargetDiv = target;
2122
+ rootPositionCache.cacheRect = rootRect;
2123
+ }
2124
+ const itemRect = _getPostionRelativeToRoot(itemIndex);
2125
+ return {
2126
+ left: rootRect.left + itemRect.left,
2127
+ top: rootRect.top + itemRect.top,
2128
+ width: itemRect.width,
2129
+ height: itemRect.height,
2130
+ };
2131
+ }
2132
+
1750
2133
  const _onTemplateItemAdd = (customerData, templateItem, measuresObj) => {
1751
2134
  let itemConfig = _getItemConfigFromMeasursObj(measuresObj);
1752
2135
 
@@ -1764,6 +2147,12 @@ export const setup = (
1764
2147
  renderStyle,
1765
2148
  itemConfig,
1766
2149
  () => {
2150
+ if (callGazeAfterUpdate && item.index == gazeIndex) {
2151
+ nextTick(() => {
2152
+ item.onGaze(preEdgeRect);
2153
+ });
2154
+ callGazeAfterUpdate = false;
2155
+ }
1767
2156
  if (callFocusAfterUpdate && item.id === focusId) {
1768
2157
  nextTick(() => {
1769
2158
  onItemFocus(item, preEdgeRect);
@@ -1784,28 +2173,53 @@ export const setup = (
1784
2173
  },
1785
2174
  {
1786
2175
  onTap: onItemTap,
1787
- }
2176
+ getMwChain: () => {
2177
+ return metroWidgetChain;
2178
+ },
2179
+ name: props.name,
2180
+ getItemPositionWithCache,
2181
+ },
2182
+ props.renderAcc,
2183
+ innerEnableRenderBreak
1788
2184
  );
1789
2185
  item.enableTap = measuresObj.enableTap ?? false;
1790
2186
  // 占位图布局
1791
2187
  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
- }
2188
+ let l, t, w, h, logoW, logoH;
2189
+ l =
2190
+ typeof measuresObj.placeHolderLayout?.left == "number"
2191
+ ? measuresObj.placeHolderLayout.left
2192
+ : 0;
2193
+ t =
2194
+ typeof measuresObj.placeHolderLayout?.top == "number"
2195
+ ? measuresObj.placeHolderLayout.top
2196
+ : 0;
2197
+ w =
2198
+ typeof measuresObj.placeHolderLayout?.width == "number"
2199
+ ? measuresObj.placeHolderLayout.width
2200
+ : item.renderStyle.width - (props.placeHolderSetting.gap ?? 0);
2201
+ h =
2202
+ typeof measuresObj.placeHolderLayout?.height == "number"
2203
+ ? measuresObj.placeHolderLayout.height
2204
+ : item.renderStyle.height - (props.placeHolderSetting.gap ?? 0);
2205
+ logoW =
2206
+ typeof measuresObj.placeHolderLayout?.logoWidth == "number"
2207
+ ? measuresObj.placeHolderLayout.logoWidth
2208
+ : props.placeHolderSetting.logoWidth ?? 0;
2209
+ logoH =
2210
+ typeof measuresObj.placeHolderLayout?.logoHeight == "number"
2211
+ ? measuresObj.placeHolderLayout.logoHeight
2212
+ : props.placeHolderSetting.logoHeight ?? 0;
2213
+ item.placeHolderLayout = {
2214
+ left: l,
2215
+ top: t,
2216
+ width: w,
2217
+ height: h,
2218
+ logoWidth: logoW,
2219
+ logoHeight: logoH,
2220
+ };
1807
2221
  }
1808
-
2222
+
1809
2223
  innerData.push(item);
1810
2224
  if (item.itemConfig.permanent) {
1811
2225
  permanentItemList.push({
@@ -1909,6 +2323,26 @@ export const setup = (
1909
2323
  }
1910
2324
  };
1911
2325
 
2326
+ const _innerOnEdge = (rect) => {
2327
+ if (props.onEdge) {
2328
+ if (typeof props.onEdge === "string") {
2329
+ if (props.onEdge === ONEDGE_TYPE.SPATIAL_NAV) {
2330
+ if (spatialNavigator) {
2331
+ spatialNavigator.moveTo(rect.direction);
2332
+ } else {
2333
+ console.warn("MetroWidget: onEdge is spatialNav, but spatialNavigator is not set", props.name);
2334
+ }
2335
+ } else {
2336
+ console.warn("MetroWidget: onEdge string is not valid", props.name, props.onEdge);
2337
+ }
2338
+ } else if (typeof props.onEdge === "function") {
2339
+ props.onEdge(rect);
2340
+ } else {
2341
+ console.warn("MetroWidget: onEdge is not a function nor a string", props.name);
2342
+ }
2343
+ }
2344
+ }
2345
+
1912
2346
  const _moveToNext = (
1913
2347
  horizontal_direction,
1914
2348
  vertical_direction,
@@ -1929,7 +2363,7 @@ export const setup = (
1929
2363
  console.warn(TAG, "moveToNext error");
1930
2364
  }
1931
2365
  if (direction) {
1932
- props.onEdge?.({
2366
+ _innerOnEdge({
1933
2367
  direction: direction,
1934
2368
  rect: {
1935
2369
  x: 0,
@@ -1983,7 +2417,9 @@ export const setup = (
1983
2417
  },
1984
2418
  };
1985
2419
  }
2420
+ onItemIgnore(preFocusItem)
1986
2421
  onItemBlur(preFocusItem);
2422
+ onItemGaze(next_focus_item, preEdgeRect);
1987
2423
  onItemFocus(next_focus_item, preEdgeRect);
1988
2424
 
1989
2425
  if (
@@ -2003,7 +2439,8 @@ export const setup = (
2003
2439
  visibleInfo.endWithPadding + innerKeepTraceRange * pageRange,
2004
2440
  next_focus_item.id,
2005
2441
  false,
2006
- permanentItemList
2442
+ permanentItemList,
2443
+ props.fullDisplayMode
2007
2444
  );
2008
2445
  //不做滚动时,保证获焦的item创建. 为了避免提前隐藏, 使用applyTmp
2009
2446
  updater.applyTmp();
@@ -2043,7 +2480,7 @@ export const setup = (
2043
2480
  };
2044
2481
  }
2045
2482
 
2046
- props.onEdge?.({
2483
+ _innerOnEdge({
2047
2484
  direction: edge,
2048
2485
  rect: rect,
2049
2486
  childEdgeInfo: item_edge_rect,
@@ -2054,7 +2491,7 @@ export const setup = (
2054
2491
  }
2055
2492
  };
2056
2493
 
2057
- const normalizeVisibleStart = (origin, targetRect, index, _visibleInfo) => {
2494
+ const normalizeVisibleStart = (origin, _visibleInfo) => {
2058
2495
  let pos_key = vertical ? "top" : "left";
2059
2496
  let size_key = vertical ? "height" : "width";
2060
2497
  let visibleStart = origin;
@@ -2097,7 +2534,7 @@ export const setup = (
2097
2534
  preInfo = null
2098
2535
  ) => {
2099
2536
  if (!targetRect) {
2100
- console.error("MetroWidget: _calculateVisibleStart target item is null");
2537
+ errorLogger("MetroWidget: _calculateVisibleStart target item is null");
2101
2538
  return 0;
2102
2539
  }
2103
2540
  const curRect = {
@@ -2154,7 +2591,7 @@ export const setup = (
2154
2591
  case SlideSetting.Type.WHOLE_PAGE:
2155
2592
  if (!templateInfo || typeof templateInfo.pageHeadIndex == "undefined") {
2156
2593
  //TODO 子控制滚动时whole page滚动
2157
- console.error(
2594
+ errorLogger(
2158
2595
  "child controlled whole page slide type is not supported."
2159
2596
  );
2160
2597
  } else {
@@ -2262,18 +2699,13 @@ export const setup = (
2262
2699
  }
2263
2700
  break;
2264
2701
  default:
2265
- console.error(
2702
+ errorLogger(
2266
2703
  "MetroWidget: undefined slide type",
2267
2704
  innerSlideSetting.Type
2268
2705
  );
2269
2706
  }
2270
2707
 
2271
- new_visible_start = normalizeVisibleStart(
2272
- new_visible_start,
2273
- targetRect,
2274
- templateInfo?.index,
2275
- vInfo
2276
- );
2708
+ new_visible_start = normalizeVisibleStart(new_visible_start, vInfo);
2277
2709
  return Math.round(new_visible_start);
2278
2710
  };
2279
2711
 
@@ -2304,38 +2736,43 @@ export const setup = (
2304
2736
  };
2305
2737
 
2306
2738
  const focusBlockOnFocus = (params) => {
2307
- isFocus = true;
2308
- if (innerData.length === 0) {
2309
- console.log(`MetroWidget: ${props.name} get focus while data is empty.`);
2739
+ if (JsvInteractionMode.value == TOUCH_MODE) {
2740
+ focusWhenInTouch = true;
2310
2741
  return;
2311
2742
  }
2312
-
2313
- let focus_id = index2Id(gazeIndex);
2314
- focus_id =
2315
- typeof enterFocusId !== "undefined" &&
2316
- enterFocusId >= 0 &&
2317
- enterFocusId < metroTemplate.size
2318
- ? enterFocusId
2743
+ isFocus.value = true;
2744
+
2745
+ if (innerData.length !== 0) {
2746
+ let focus_id = focusId;
2747
+ focus_id =
2748
+ typeof enterFocusId !== "undefined" &&
2749
+ enterFocusId >= 0 &&
2750
+ enterFocusId < metroTemplate.size
2751
+ ? enterFocusId
2752
+ : focus_id;
2753
+ focus_id = _ifValidEnterRect(enterFocusRect)
2754
+ ? _calculateNearestItemByRect(pageUpdater.getRange(), enterFocusRect)
2319
2755
  : focus_id;
2320
- focus_id = _ifValidEnterRect(enterFocusRect)
2321
- ? _calculateNearestItemByRect(pageUpdater.getRange(), enterFocusRect)
2322
- : focus_id;
2323
- preEdgeRect = enterFocusRect;
2324
- _changeFocusId(focus_id, false);
2325
- enterFocusId = -1;
2326
- enterFocusRect = null;
2327
- firstOnItemFocusCalled = onItemFocus(getItemById(focusId), preEdgeRect);
2756
+ preEdgeRect = enterFocusRect;
2757
+ _changeFocusId(focus_id, false);
2758
+ enterFocusId = -1;
2759
+ enterFocusRect = null;
2760
+ firstOnItemFocusCalled = onItemFocus(getItemById(focusId), preEdgeRect);
2761
+ } else {
2762
+ console.log(`MetroWidget: ${props.name} get focus while data is empty.`);
2763
+ }
2328
2764
  props.onFocus?.();
2329
2765
  };
2330
2766
 
2331
2767
  const focusBlockOnBlur = () => {
2768
+ focusWhenInTouch = false;
2332
2769
  enterFocusId = -1;
2333
2770
  enterFocusRect = null;
2334
2771
  preEdgeRect = null;
2335
2772
  preFocusId = focusId;
2336
2773
  onItemBlur(getItemById(preFocusId));
2337
2774
  props.onBlur?.();
2338
- isFocus = false;
2775
+ isFocus.value = false;
2339
2776
  mRectCache.clean();
2340
2777
  };
2341
2778
 
@@ -2348,11 +2785,44 @@ export const setup = (
2348
2785
  let newArray = tmpArray.map((item) => {
2349
2786
  return getItemByIndex(item);
2350
2787
  });
2351
- const newItemList = newArray.filter((i) => {
2352
- return !renderData.value?.includes(i);
2353
- });
2788
+ //新进的item
2789
+ newArray
2790
+ .filter((i) => {
2791
+ return !renderData.value?.includes(i);
2792
+ })
2793
+ .forEach((i) => {
2794
+ i.onInRenderRange();
2795
+ i.renderBreak = innerEnableRenderBreak;
2796
+ });
2797
+ //退出的item
2798
+ renderData.value
2799
+ .filter((i) => {
2800
+ return !newArray.includes(i);
2801
+ })
2802
+ .forEach((i) => {
2803
+ i.onOutOfRenderRange();
2804
+ if (spatialNavigator) {
2805
+ spatialNavigator.unregisterNode(i.getSpatialNavNode());
2806
+ }
2807
+ });
2808
+
2809
+ //注册spatial navigator
2810
+ if (spatialNavigator) {
2811
+ for (let item of newArray) {
2812
+ const visibleState = rectVisibleState(item.templateInfo);
2813
+ const n = item.getSpatialNavNode();
2814
+ if (visibleState == 2 || visibleState == 1) {
2815
+ if (n) {
2816
+ spatialNavigator.registerNode(n);
2817
+ }
2818
+ } else {
2819
+ spatialNavigator.unregisterNode(n);
2820
+ }
2821
+ }
2822
+ }
2823
+
2354
2824
  renderData.value = newArray;
2355
- if (props.enableItemRenderBreak) {
2825
+ if (innerEnableRenderBreak) {
2356
2826
  itemRender.value = false;
2357
2827
  const f = () => {
2358
2828
  // 关闭强制TriggerManualBlock,改为vue内部通过dom的任务数来确定是否执行打断
@@ -2367,25 +2837,67 @@ export const setup = (
2367
2837
 
2368
2838
  const _getVisibleFocusableItem = () => {
2369
2839
  let item = getItemByIndex(gazeIndex);
2370
- if (rectVisibleState(item.templateInfo) == 2) {
2371
- return item;
2840
+ if (item) {
2841
+ let itemVisibility = rectVisibleState(item.templateInfo);
2842
+ let isLarge = isLargeItem(item.templateInfo);
2843
+ if (itemVisibility == 2) {
2844
+ return item;
2845
+ }
2372
2846
  }
2847
+
2373
2848
  item = getItemById(focusId);
2374
- if (rectVisibleState(focusItem.templateInfo) == 2) {
2375
- return focusItem;
2849
+ if (item) {
2850
+ let itemVisibility = rectVisibleState(item.templateInfo);
2851
+ let isLarge = isLargeItem(item.templateInfo);
2852
+ if (itemVisibility == 2) {
2853
+ return item;
2854
+ }
2376
2855
  }
2856
+
2377
2857
  //遍历renderList, 找到第一个可见的 focusable item
2858
+ let resultItem = null;
2378
2859
  for (let item of renderData.value) {
2860
+ let itemVisibility = rectVisibleState(item.templateInfo);
2861
+ let isLarge = isLargeItem(item.templateInfo);
2379
2862
  if (
2380
2863
  item.templateInfo.focusable &&
2381
- rectVisibleState(item.templateInfo) == 2
2864
+ (itemVisibility == 2 || (itemVisibility == 1 && isLarge))
2382
2865
  ) {
2383
- return item;
2866
+ resultItem = item;
2867
+ break;
2384
2868
  }
2385
2869
  }
2870
+ if (resultItem == null) {
2871
+ //找到占空间最大的部分可视item;
2872
+ }
2386
2873
  return null;
2387
2874
  };
2388
2875
 
2876
+ let preSize = 0;
2877
+ const _onSizeChange = () => {
2878
+ if (props.fullDisplayMode) {
2879
+ nextTick(() => {
2880
+ let size = 0;
2881
+ if (innerData.length > 0) {
2882
+ const lastTemplateInfo =
2883
+ innerData[innerData.length - 1]?.templateInfo;
2884
+ if (vertical) {
2885
+ size = lastTemplateInfo.top + lastTemplateInfo.height - 1;
2886
+ } else {
2887
+ size = lastTemplateInfo.left + lastTemplateInfo.width - 1;
2888
+ }
2889
+ }
2890
+ if (size != preSize) {
2891
+ preSize = size;
2892
+ props.onSizeChange?.({
2893
+ width: vertical ? props.width : size,
2894
+ height: vertical ? size : props.height,
2895
+ });
2896
+ }
2897
+ });
2898
+ }
2899
+ };
2900
+
2389
2901
  const _onScroll = () => {
2390
2902
  if (props.onScroll) {
2391
2903
  const lastTemplateInfo = getItemByIndex(
@@ -2402,6 +2914,22 @@ export const setup = (
2402
2914
  props.onScroll(visibleInfo.start, visibleInfo.range, totalWidth);
2403
2915
  }
2404
2916
  };
2917
+ const _syncOnScroll = () => {
2918
+ if (props.syncOnScroll) {
2919
+ const lastTemplateInfo = getItemByIndex(
2920
+ metroTemplate.getTailItemIndex()
2921
+ )?.templateInfo;
2922
+ let totalWidth = 0;
2923
+ if (lastTemplateInfo) {
2924
+ if (vertical) {
2925
+ totalWidth = lastTemplateInfo.top + lastTemplateInfo.height - 1;
2926
+ } else {
2927
+ totalWidth = lastTemplateInfo.left + lastTemplateInfo.width - 1;
2928
+ }
2929
+ }
2930
+ props.syncOnScroll(visibleInfo.start, visibleInfo.range, totalWidth);
2931
+ }
2932
+ }
2405
2933
 
2406
2934
  //touch setting
2407
2935
  let actorController = null;
@@ -2523,17 +3051,23 @@ export const setup = (
2523
3051
  mergeTouchSlideToSlideDiv(touchCount);
2524
3052
  //由于movement的监听是有帧数间隔的, 所以结束时需要再调用一次onScroll
2525
3053
  _onScroll();
3054
+ _syncOnScroll();
2526
3055
  }
2527
3056
 
2528
3057
  const onTouchDown = (data, customData, nexusCustomData) => {
3058
+ const curPos = vertical ? slideDivTop.value : slideDivLeft.value;
3059
+ let needMerge = -visibleInfo.start != curPos;
3060
+ if (needMerge) {
3061
+ mergeTouchSlideToSlideDiv(touchRecorder.touchCount);
3062
+ }
3063
+
2529
3064
  touchRecorder.reset();
2530
3065
  let touchCount = getTouchCount(nexusCustomData);
2531
3066
  touchRecorder.setTouchCount(touchCount);
2532
3067
  updateTouchBoxCondition();
2533
3068
 
2534
- mode.touchStart(touchCount);
2535
- // console.log("touchtest", `${props.name} animId:${debugAnimId} viewId:${debugViewId}`,
2536
- // "onTouchDown", data, customData, nexusCustomData)
3069
+ JsvInteractionMode.value = TOUCH_MODE;
3070
+ touchStateMgr.touchStart(touchCount);
2537
3071
 
2538
3072
  // 运动方向锁定机制
2539
3073
  // 当MetroWidget在某一方向拖动后,讲另一方向的移动进行锁定
@@ -2569,9 +3103,6 @@ export const setup = (
2569
3103
  ]),
2570
3104
  ]);
2571
3105
 
2572
- //blur item
2573
- // onItemBlur(getItemById(focusId));
2574
-
2575
3106
  templateItemAdder.tryAddItemByPosition(visibleInfo.end + visibleInfo.range);
2576
3107
 
2577
3108
  const updater = pageUpdater.update(
@@ -2580,7 +3111,8 @@ export const setup = (
2580
3111
  visibleInfo.endWithPadding + innerKeepTraceRange * pageRange,
2581
3112
  0,
2582
3113
  false,
2583
- permanentItemList
3114
+ permanentItemList,
3115
+ props.fullDisplayMode
2584
3116
  );
2585
3117
  updater.apply();
2586
3118
 
@@ -2612,18 +3144,20 @@ export const setup = (
2612
3144
  );
2613
3145
  return reachConditionList;
2614
3146
  });
3147
+
3148
+ props.onTouchFocus?.();
2615
3149
  };
2616
3150
 
2617
3151
  const onTouchRelease = (touchCount) => {
2618
- if (mode.getTouchState() == TouchState.TAP) {
3152
+ if (touchStateMgr.getTouchState() == TouchState.TAP) {
2619
3153
  //只点击, 没有移动或者fling
2620
3154
  updateRenderItems(false, false);
2621
- mode.touchEnd(touchCount);
3155
+ touchStateMgr.touchEnd(touchCount);
2622
3156
  } else {
2623
- if (touchRecorder.moved && !mode.duringFling()) {
3157
+ if (touchRecorder.moved && !touchStateMgr.duringFling()) {
2624
3158
  onTouchActionDone(touchRecorder.touchCount);
2625
3159
  updateRenderItems(false, false);
2626
- mode.touchEnd(touchCount);
3160
+ touchStateMgr.touchEnd(touchCount);
2627
3161
  }
2628
3162
  }
2629
3163
  actorController.run((cmds) => [
@@ -2632,21 +3166,26 @@ export const setup = (
2632
3166
  ]);
2633
3167
  };
2634
3168
 
2635
- const exportOnTouchRelease = props.touchFlag > 0 ? onTouchRelease : undefined;
3169
+ const exportOnTouchRelease = touchEnable.value ? onTouchRelease : undefined;
2636
3170
 
2637
3171
  const onDragStart = (data, customData, nexusCustomData) => {
2638
3172
  let touchCount = getTouchCount(nexusCustomData);
2639
3173
  touchRecorder.move();
2640
- if (!(mode.getTouchCount() == touchCount && mode.duringFling())) {
3174
+ if (
3175
+ !(
3176
+ touchStateMgr.getTouchCount() == touchCount &&
3177
+ touchStateMgr.duringFling()
3178
+ )
3179
+ ) {
2641
3180
  //dragStart event may be triggered after fling event because of sending it when startMove condition is satisfied
2642
- mode.dragStart(touchCount);
3181
+ touchStateMgr.dragStart(touchCount);
2643
3182
  }
2644
3183
  visibleInfo.start = getVisibleStart(data);
2645
3184
  };
2646
3185
 
2647
3186
  const onDragEnd = (data, customData, nexusCustomData) => {
2648
3187
  let touchCount = getTouchCount(nexusCustomData);
2649
- mode.dragEnd(touchCount);
3188
+ touchStateMgr.dragEnd(touchCount);
2650
3189
  visibleInfo.start = getVisibleStart(data);
2651
3190
  actorController.run((cmds) => [
2652
3191
  cmds.state().removeConditionByGroup(reachAnchorGroup),
@@ -2656,7 +3195,7 @@ export const setup = (
2656
3195
  const onFlingStart = (data, customData, nexusCustomData) => {
2657
3196
  let touchCount = getTouchCount(nexusCustomData);
2658
3197
  touchRecorder.move();
2659
- mode.flingStart(touchCount);
3198
+ touchStateMgr.flingStart(touchCount);
2660
3199
  visibleInfo.start = getVisibleStart(data);
2661
3200
  updateRenderItems(true, true);
2662
3201
  };
@@ -2670,12 +3209,12 @@ export const setup = (
2670
3209
  const onFlingEnd = (data, customData, nexusCustomData) => {
2671
3210
  visibleInfo.start = getVisibleStart(data);
2672
3211
  //记录拖拽的距离
2673
- if (mode.duringFling()) {
3212
+ if (touchStateMgr.duringFling()) {
2674
3213
  let touchCount = getTouchCount(nexusCustomData);
2675
3214
  onTouchActionDone(touchCount);
2676
3215
  updateRenderItems(false, false);
2677
- mode.flingEnd(touchCount);
2678
- mode.touchEnd(touchCount);
3216
+ touchStateMgr.flingEnd(touchCount);
3217
+ touchStateMgr.touchEnd(touchCount);
2679
3218
  }
2680
3219
  };
2681
3220
 
@@ -2684,6 +3223,16 @@ export const setup = (
2684
3223
  visibleInfo.start = getVisibleStart(data);
2685
3224
  };
2686
3225
 
3226
+ const onFlingCancel = (data, customData, nexusCustomData) => {
3227
+ visibleInfo.start = getVisibleStart(data);
3228
+ if (touchStateMgr.duringFling()) {
3229
+ let touchCount = getTouchCount(nexusCustomData);
3230
+ onTouchActionDone(touchCount);
3231
+ updateRenderItems(false, false);
3232
+ touchStateMgr.flingEnd(touchCount);
3233
+ }
3234
+ };
3235
+
2687
3236
  const getTouchWall = () => {
2688
3237
  const boxSize = metroTemplate.getBoundingBoxSize();
2689
3238
  let wall = {
@@ -2692,6 +3241,9 @@ export const setup = (
2692
3241
  right: 0,
2693
3242
  bottom: 0,
2694
3243
  };
3244
+ if (props.fullDisplayMode) {
3245
+ return wall;
3246
+ }
2695
3247
  if (vertical) {
2696
3248
  wall.top =
2697
3249
  -boxSize.height +
@@ -2727,16 +3279,16 @@ export const setup = (
2727
3279
  visibleInfo.endWithPadding + innerKeepTraceRange * pageRange,
2728
3280
  0,
2729
3281
  true,
2730
- permanentItemList
3282
+ permanentItemList,
3283
+ props.fullDisplayMode
2731
3284
  );
2732
3285
  applyTmp ? updater.applyTmp() : updater.apply();
2733
3286
  };
2734
3287
 
2735
3288
  const updateTouchBoxCondition = () => {
2736
- if (mode.getMode() != TOUCH_MODE) return;
3289
+ if (JsvInteractionMode.value != TOUCH_MODE) return;
2737
3290
  if (actorController != null) {
2738
3291
  const walls = getTouchWall();
2739
-
2740
3292
  //更新wall设置
2741
3293
  actorController.run((cmds) => [
2742
3294
  cmds.state().removeConditionByGroup(wallConditionGroup),
@@ -2763,8 +3315,6 @@ export const setup = (
2763
3315
  },
2764
3316
  };
2765
3317
 
2766
- const metroWidgetToken = metroWidgetTokenGen++;
2767
-
2768
3318
  let orderTouchSlideCallbacks;
2769
3319
  const SliderEditFuncReOrderWrap = (callback, addHeader = false) => {
2770
3320
  return (...args) => {
@@ -2839,6 +3389,10 @@ export const setup = (
2839
3389
  .condition(undefined, true)
2840
3390
  .onFlingDrop()
2841
3391
  .then([SliderEditFuncReOrderWrap(onFlingDrop)]),
3392
+ cmds
3393
+ .condition(undefined, true)
3394
+ .onFlingCancel()
3395
+ .then([SliderEditFuncReOrderWrap(onFlingCancel)]),
2842
3396
  cmds
2843
3397
  .condition(undefined, true)
2844
3398
  .onTouchRelease()
@@ -2854,7 +3408,35 @@ export const setup = (
2854
3408
  }
2855
3409
  };
2856
3410
 
2857
- function cleanTouch() {
3411
+ const onMouseWheelScrollProgress = (data) => {
3412
+ visibleInfo.start = getVisibleStart(data);
3413
+ updateRenderItems(true, true);
3414
+ mergeTouchSlideToSlideDiv();
3415
+ };
3416
+
3417
+ const DEFAULT_MOUSE_CONFIG = {
3418
+ wheelRate: 10,
3419
+ }
3420
+ let mouseInited = false;
3421
+ const initMouse = () => {
3422
+ mouseInited = true;
3423
+ const divView = touchDiv.value.jsvGetProxyView();
3424
+ if (!actorController) {
3425
+ actorController = new ActorControl();
3426
+ actorController.bindForgeView(divView, true);
3427
+ }
3428
+ // 1: hover, 2: scroll, 目前只打开scroll
3429
+ divView.HoverEnables(2);
3430
+ divView.SetMouseWheelRate(props.mouseConfig?.wheelRate ?? DEFAULT_MOUSE_CONFIG.wheelRate);
3431
+ actorController.run((cmds) => [
3432
+ cmds
3433
+ .condition(undefined, true)
3434
+ .onMouseWheelScrollProgress()
3435
+ .then([onMouseWheelScrollProgress]),
3436
+ ]);
3437
+ };
3438
+
3439
+ function cleanFreeMoveConditions() {
2858
3440
  actorController.run((cmds) => [
2859
3441
  cmds.state().clearAllConditions(),
2860
3442
  cmds.state().touchLockSwitch(false, vertical ? 1 : 2),
@@ -2895,9 +3477,10 @@ export const setup = (
2895
3477
  pageRange,
2896
3478
  _onTemplateItemAdd,
2897
3479
  props.name,
2898
- _onTemplateAddDone
3480
+ getOnTemplateAddDone(true),
3481
+ errorLogger
2899
3482
  );
2900
- if (props.onScroll) {
3483
+ if (props.onScroll || props.fullDisplayMode) {
2901
3484
  templateItemAdder.tryAddItemByIndex(dataList.length - 1);
2902
3485
  } else {
2903
3486
  templateItemAdder.tryAddItem(null, 2);
@@ -2935,12 +3518,13 @@ export const setup = (
2935
3518
  initVisibleInfo.endWithPadding,
2936
3519
  0,
2937
3520
  false,
2938
- permanentItemList
3521
+ permanentItemList,
3522
+ props.fullDisplayMode
2939
3523
  );
2940
3524
  initUpdater.apply();
2941
3525
  //触控时, 延时加载剩余屏
2942
3526
  let delayLoadHandler = -1;
2943
- if (props.touchFlag > 0) {
3527
+ if (touchEnable.value) {
2944
3528
  delayLoadHandler = setTimeout(() => {
2945
3529
  const updateHandler = pageUpdater.update(
2946
3530
  metroTemplate,
@@ -2948,7 +3532,8 @@ export const setup = (
2948
3532
  initVisibleInfo.endWithPadding + innerKeepTraceRange * pageRange,
2949
3533
  focusId,
2950
3534
  false,
2951
- permanentItemList
3535
+ permanentItemList,
3536
+ props.fullDisplayMode
2952
3537
  );
2953
3538
  updateHandler.apply();
2954
3539
  }, 200);
@@ -2963,28 +3548,74 @@ export const setup = (
2963
3548
  if (!firstOnItemFocusCalled) {
2964
3549
  firstOnItemFocusCalled = onItemFocus(getItemById(focusId), preEdgeRect);
2965
3550
  }
3551
+ //第一次ongaze
3552
+ onItemGaze(getItemById(focusId), preEdgeRect);
2966
3553
 
2967
3554
  if (props.enableItemRenderBreak) {
2968
3555
  nextTick(() => {
2969
3556
  itemRender.value = true;
2970
3557
  });
2971
3558
  }
2972
- if (props.touchFlag === 1) {
3559
+ if (touchEnable.value) {
2973
3560
  initTouch();
2974
3561
  }
3562
+ if (props.mouseFlag > 0) {
3563
+ initMouse();
3564
+ }
3565
+ _onSizeChange();
2975
3566
  });
2976
3567
 
2977
3568
  onUpdated(() => {});
2978
3569
 
2979
3570
  onBeforeUnmount(() => {
3571
+ if (vRenderBreakChanged) {
3572
+ window.JsView?.setRenderBreakEnable?.(true);
3573
+ }
2980
3574
  taskManager.cancelAllTask();
2981
3575
  tryCancelDelayLoad();
2982
3576
  mounted = false;
2983
3577
  if (touchInited) {
2984
- cleanTouch();
3578
+ cleanFreeMoveConditions();
3579
+ }
3580
+ if (rootNativeViewId != -1) {
3581
+ Forge.sViewStore.remove(rootNativeViewId);
3582
+ }
3583
+ if (spatialNavigator) {
3584
+ renderData.value.forEach((item) => {
3585
+ spatialNavigator.unregisterNode(item.getSpatialNavNode());
3586
+ });
2985
3587
  }
2986
3588
  });
2987
3589
 
3590
+ //spatial navigator相关
3591
+ //作为子MetroWidget时的index
3592
+ let selfChildIndex = undefined;
3593
+ function getSelfChildIndex () {
3594
+ if (!parentMetroWidget) { return undefined; }
3595
+ if (!rootDiv.value) {
3596
+ console.warn("getSelfChildIndex before mounted.")
3597
+ return undefined;
3598
+ }
3599
+ if (selfChildIndex !== undefined) { return selfChildIndex; }
3600
+ let n = rootDiv.value;
3601
+ while(n) {
3602
+ if (n.getAttribute("__metrowidget-index") !== undefined) {
3603
+ selfChildIndex = parseInt(n.getAttribute("__metrowidget-index"));
3604
+ break;
3605
+ }
3606
+ n = n.parentNode;
3607
+ }
3608
+ return selfChildIndex;
3609
+ };
3610
+ const provideObj = {
3611
+ id: metroWidgetId,
3612
+ divRef: rootDiv,
3613
+ handler: exportObject,
3614
+ getSelfChildIndex,
3615
+ }
3616
+ const metroWidgetChain = parentMetroWidget ? [...parentMetroWidget, provideObj] : [provideObj];
3617
+ provide(MW_CONTEXT_NAME, metroWidgetChain);
3618
+
2988
3619
  return {
2989
3620
  widgetRectInfo,
2990
3621
  focusBlockOnFocus,
@@ -2998,7 +3629,8 @@ export const setup = (
2998
3629
  onTouchDown,
2999
3630
  onTouchRelease: exportOnTouchRelease,
3000
3631
  currentFocusIndex,
3001
- modeForExport,
3002
3632
  onDispatchKeyDown,
3633
+ isFocus,
3634
+ rootNativeViewId,
3003
3635
  };
3004
3636
  };