@geode/opengeodeweb-front 10.34.0-rc.9 → 10.34.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 (282) hide show
  1. package/{server → .build/server}/utils/app_config.js +10 -9
  2. package/{server → .build/server}/utils/cleanup.js +31 -17
  3. package/{server → .build/server}/utils/cloud.js +1 -4
  4. package/{server → .build/server}/utils/microservices.js +21 -9
  5. package/{server → .build/server}/utils/path.js +4 -4
  6. package/{server → .build/server}/utils/scripts.js +9 -9
  7. package/.build/server/utils/server_config.js +51 -0
  8. package/.build/server/utils/stream.js +6 -0
  9. package/{server → .build/server}/utils/ws_client.js +18 -3
  10. package/{shared → .build/shared}/scripts.js +10 -10
  11. package/.build/shared/utils/call_raw.js +31 -0
  12. package/{shared → .build/shared}/utils/call_schema.js +2 -2
  13. package/.build/shared/utils/fetch_raw.js +52 -0
  14. package/{shared → .build/shared}/utils/fetch_schema.js +2 -2
  15. package/{shared → .build/shared}/utils/file.js +3 -1
  16. package/{shared → .build/shared}/utils/response_handlers/load.js +10 -7
  17. package/{shared → .build/shared}/utils/validate_schema.js +1 -1
  18. package/app/components/ActionButton.vue +6 -6
  19. package/app/components/CameraManager/List.vue +5 -5
  20. package/app/components/CameraManager/Saver.vue +3 -5
  21. package/app/components/CameraManager.vue +6 -4
  22. package/app/components/CameraOrientation.vue +12 -12
  23. package/app/components/ClippingPlaneCard.vue +4 -2
  24. package/app/components/ClippingPlanes.vue +8 -8
  25. package/app/components/CrsSelector.vue +9 -10
  26. package/app/components/DeleteDialog.vue +4 -2
  27. package/app/components/DragAndDrop.vue +10 -12
  28. package/app/components/DragAndDropInternal/DragAndDropInline.vue +4 -2
  29. package/app/components/ExtensionSelector.vue +4 -4
  30. package/app/components/FeedBack/ErrorBanner.vue +3 -1
  31. package/app/components/FeedBack/Snackers.vue +4 -3
  32. package/app/components/FileSelector.vue +10 -8
  33. package/app/components/FileUploader.vue +11 -11
  34. package/app/components/GlassCard.vue +1 -1
  35. package/app/components/HybridRenderingView.vue +7 -5
  36. package/app/components/HybridViewerTooltip.vue +7 -7
  37. package/app/components/Launcher.vue +1 -1
  38. package/app/components/Loading/EcoMessages.vue +9 -3
  39. package/app/components/Loading.vue +2 -2
  40. package/app/components/MissingFilesSelector.vue +12 -10
  41. package/app/components/ObjectSelector.vue +10 -9
  42. package/app/components/PackagesVersions.vue +6 -5
  43. package/app/components/Recaptcha.vue +3 -3
  44. package/app/components/RemoteRenderingView.vue +6 -7
  45. package/app/components/Ruler.vue +3 -3
  46. package/app/components/Screenshot.vue +6 -6
  47. package/app/components/SearchBar.vue +4 -2
  48. package/app/components/ShrinkFilter.vue +7 -7
  49. package/app/components/Step.vue +6 -5
  50. package/app/components/Stepper.vue +4 -3
  51. package/app/components/ToolPanel.vue +6 -3
  52. package/app/components/ViewToolbar.vue +25 -28
  53. package/app/components/Viewer/ContextMenu/CenterButton.vue +7 -5
  54. package/app/components/Viewer/ContextMenu/CircularItems.vue +3 -3
  55. package/app/components/Viewer/ContextMenu/ContextMenu.vue +22 -19
  56. package/app/components/Viewer/ContextMenu/ContextMenuItem.vue +10 -8
  57. package/app/components/Viewer/ContextMenu/InfoCard.vue +11 -12
  58. package/app/components/Viewer/EdgedCurve/SpecificEdgesOptions.vue +13 -17
  59. package/app/components/Viewer/Generic/Mesh/CellsOptions.vue +11 -15
  60. package/app/components/Viewer/Generic/Mesh/EdgesOptions.vue +12 -16
  61. package/app/components/Viewer/Generic/Mesh/PointsOptions.vue +8 -12
  62. package/app/components/Viewer/Generic/Mesh/PolygonsOptions.vue +11 -15
  63. package/app/components/Viewer/Generic/Mesh/PolyhedraOptions.vue +11 -15
  64. package/app/components/Viewer/Generic/Model/BlocksOptions.vue +67 -38
  65. package/app/components/Viewer/Generic/Model/CornersOptions.vue +53 -23
  66. package/app/components/Viewer/Generic/Model/EdgesOptions.vue +1 -3
  67. package/app/components/Viewer/Generic/Model/LinesOptions.vue +67 -38
  68. package/app/components/Viewer/Generic/Model/ModelStyleCard.vue +31 -15
  69. package/app/components/Viewer/Generic/Model/ModelStyleOptions.vue +2 -3
  70. package/app/components/Viewer/Generic/Model/PointsOptions.vue +6 -6
  71. package/app/components/Viewer/Generic/Model/SurfacesOptions.vue +69 -38
  72. package/app/components/Viewer/ObjectTree/Base/CommonTreeView.vue +64 -46
  73. package/app/components/Viewer/ObjectTree/Base/Controls.vue +5 -5
  74. package/app/components/Viewer/ObjectTree/Base/ItemLabel.vue +13 -9
  75. package/app/components/Viewer/ObjectTree/Base/StickyHeader.vue +5 -5
  76. package/app/components/Viewer/ObjectTree/Base/TreeRow.vue +10 -10
  77. package/app/components/Viewer/ObjectTree/Box.vue +6 -4
  78. package/app/components/Viewer/ObjectTree/Layout.vue +23 -21
  79. package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +14 -14
  80. package/app/components/Viewer/ObjectTree/Views/{ModelCollections.vue → ModelTree.vue} +59 -24
  81. package/app/components/Viewer/Options/AttributeColorBar.vue +4 -2
  82. package/app/components/Viewer/Options/AttributeRangeSelector.vue +4 -2
  83. package/app/components/Viewer/Options/AttributeSelector.vue +7 -9
  84. package/app/components/Viewer/Options/ColorMapList.vue +15 -13
  85. package/app/components/Viewer/Options/ColorMapPicker.vue +4 -4
  86. package/app/components/Viewer/Options/ColorPicker.vue +223 -41
  87. package/app/components/Viewer/Options/ColoringTypeSelector.vue +16 -16
  88. package/app/components/Viewer/Options/ColormapQuickPicker.vue +7 -5
  89. package/app/components/Viewer/Options/OptionsSection.vue +1 -1
  90. package/app/components/Viewer/Options/TextureItem.vue +8 -6
  91. package/app/components/Viewer/Options/TexturesSelector.vue +1 -1
  92. package/app/components/Viewer/OverlappingObjectsPicker.vue +8 -9
  93. package/app/components/Viewer/PointSet/SpecificPointsOptions.vue +2 -6
  94. package/app/components/Viewer/Solid/SpecificPolyhedraOptions.vue +12 -16
  95. package/app/components/Viewer/Surface/PolygonsOptions.vue +12 -16
  96. package/app/components/Viewer/Ui.vue +2 -2
  97. package/app/components/Wrapper.vue +1 -4
  98. package/app/components/ZScaling.vue +5 -3
  99. package/app/components/csv-preview/CsvPreviewer.vue +38 -37
  100. package/app/components/csv-preview/CsvSettings.vue +6 -4
  101. package/app/components/csv-preview/CsvTable.vue +1 -1
  102. package/app/composables/batch_style.ts +5 -6
  103. package/app/composables/clipping_planes_widget.ts +73 -181
  104. package/app/composables/clipping_planes_widget_entries.ts +189 -0
  105. package/app/composables/copy_to_clipboard.ts +7 -0
  106. package/app/composables/global_attribute_style.ts +163 -83
  107. package/app/composables/hover_highlight.ts +46 -14
  108. package/app/composables/model_collections.ts +26 -13
  109. package/app/composables/model_components.ts +26 -13
  110. package/app/composables/project_manager.ts +76 -19
  111. package/app/composables/responsive_middle_truncate.ts +13 -13
  112. package/app/composables/stepper_tree.ts +34 -11
  113. package/app/composables/tree_filter.ts +66 -44
  114. package/app/composables/tree_keyboard_nav.ts +25 -11
  115. package/app/composables/tree_scroll.ts +44 -14
  116. package/app/composables/use_adaptive_styles.ts +66 -23
  117. package/app/composables/use_overlapping_picker.ts +66 -16
  118. package/app/composables/use_quick_colormap.ts +16 -5
  119. package/app/composables/virtual_tree.ts +75 -43
  120. package/app/composables/vtk_implicit_plane_widget.d.ts +2 -0
  121. package/app/plugins/auto_store_register.ts +2 -7
  122. package/app/plugins/click_outside_ignore_snackbars.client.ts +39 -0
  123. package/app/stores/app.ts +57 -192
  124. package/app/stores/app_helpers/extension.ts +179 -0
  125. package/app/stores/back.ts +37 -21
  126. package/app/stores/camera_manager.ts +22 -20
  127. package/app/stores/cloud.ts +17 -13
  128. package/app/stores/data.ts +88 -47
  129. package/app/stores/data_helpers/collections.ts +36 -38
  130. package/app/stores/data_helpers/mesh.ts +45 -36
  131. package/app/stores/data_style.ts +50 -28
  132. package/app/stores/feedback.ts +6 -6
  133. package/app/stores/hybrid_viewer.ts +41 -52
  134. package/app/stores/infra.ts +39 -37
  135. package/app/stores/menu.ts +23 -14
  136. package/app/stores/treeview.ts +72 -42
  137. package/app/stores/viewer.ts +39 -27
  138. package/app/utils/attributes.ts +3 -3
  139. package/app/utils/clipping_planes.ts +111 -14
  140. package/app/utils/color_picker.ts +57 -0
  141. package/app/utils/colormap.ts +58 -35
  142. package/app/utils/default_styles/index.ts +2 -2
  143. package/app/utils/default_styles/meshes.ts +107 -13
  144. package/app/utils/default_styles/models.ts +83 -14
  145. package/app/utils/extension.ts +47 -20
  146. package/app/utils/import_workflow.ts +21 -13
  147. package/app/utils/name_cleaner.ts +1 -1
  148. package/app/utils/string.ts +1 -1
  149. package/app/utils/treeview.ts +2 -2
  150. package/internal/database/base_database.ts +7 -3
  151. package/internal/database/database.ts +36 -26
  152. package/internal/database/extended_database.ts +1 -1
  153. package/internal/stores/data_style/mesh/cells/cell.ts +70 -34
  154. package/internal/stores/data_style/mesh/cells/color.ts +12 -6
  155. package/internal/stores/data_style/mesh/cells/common.ts +18 -8
  156. package/internal/stores/data_style/mesh/cells/index.ts +122 -42
  157. package/internal/stores/data_style/mesh/cells/textures.ts +12 -6
  158. package/internal/stores/data_style/mesh/cells/vertex.ts +75 -34
  159. package/internal/stores/data_style/mesh/cells/visibility.ts +15 -4
  160. package/internal/stores/data_style/mesh/edges/color.ts +12 -6
  161. package/internal/stores/data_style/mesh/edges/common.ts +14 -6
  162. package/internal/stores/data_style/mesh/edges/edge.ts +71 -39
  163. package/internal/stores/data_style/mesh/edges/index.ts +117 -42
  164. package/internal/stores/data_style/mesh/edges/vertex.ts +76 -39
  165. package/internal/stores/data_style/mesh/edges/visibility.ts +15 -4
  166. package/internal/stores/data_style/mesh/edges/width.ts +12 -4
  167. package/internal/stores/data_style/mesh/index.ts +30 -11
  168. package/internal/stores/data_style/mesh/points/color.ts +12 -6
  169. package/internal/stores/data_style/mesh/points/common.ts +21 -8
  170. package/internal/stores/data_style/mesh/points/index.ts +101 -50
  171. package/internal/stores/data_style/mesh/points/size.ts +12 -4
  172. package/internal/stores/data_style/mesh/points/vertex.ts +75 -34
  173. package/internal/stores/data_style/mesh/points/visibility.ts +17 -7
  174. package/internal/stores/data_style/mesh/polygons/color.ts +12 -6
  175. package/internal/stores/data_style/mesh/polygons/common.ts +23 -6
  176. package/internal/stores/data_style/mesh/polygons/index.ts +130 -70
  177. package/internal/stores/data_style/mesh/polygons/polygon.ts +77 -43
  178. package/internal/stores/data_style/mesh/polygons/textures.ts +12 -6
  179. package/internal/stores/data_style/mesh/polygons/vertex.ts +79 -39
  180. package/internal/stores/data_style/mesh/polygons/visibility.ts +16 -6
  181. package/internal/stores/data_style/mesh/polyhedra/color.ts +12 -6
  182. package/internal/stores/data_style/mesh/polyhedra/common.ts +14 -6
  183. package/internal/stores/data_style/mesh/polyhedra/index.ts +115 -56
  184. package/internal/stores/data_style/mesh/polyhedra/polyhedron.ts +80 -39
  185. package/internal/stores/data_style/mesh/polyhedra/vertex.ts +79 -39
  186. package/internal/stores/data_style/mesh/polyhedra/visibility.ts +16 -6
  187. package/internal/stores/data_style/model/blocks/color.ts +43 -13
  188. package/internal/stores/data_style/model/blocks/common.ts +21 -6
  189. package/internal/stores/data_style/model/blocks/index.ts +89 -59
  190. package/internal/stores/data_style/model/blocks/polyhedron.ts +101 -44
  191. package/internal/stores/data_style/model/blocks/vertex.ts +107 -42
  192. package/internal/stores/data_style/model/blocks/visibility.ts +17 -4
  193. package/internal/stores/data_style/model/color.ts +171 -83
  194. package/internal/stores/data_style/model/common.ts +70 -21
  195. package/internal/stores/data_style/model/corners/color.ts +43 -11
  196. package/internal/stores/data_style/model/corners/common.ts +25 -6
  197. package/internal/stores/data_style/model/corners/index.ts +66 -41
  198. package/internal/stores/data_style/model/corners/vertex.ts +105 -74
  199. package/internal/stores/data_style/model/corners/visibility.ts +19 -4
  200. package/internal/stores/data_style/model/edges/common.ts +12 -4
  201. package/internal/stores/data_style/model/edges/index.ts +2 -1
  202. package/internal/stores/data_style/model/edges/visibility.ts +24 -7
  203. package/internal/stores/data_style/model/index.ts +24 -11
  204. package/internal/stores/data_style/model/lines/color.ts +41 -11
  205. package/internal/stores/data_style/model/lines/common.ts +17 -6
  206. package/internal/stores/data_style/model/lines/edge.ts +105 -42
  207. package/internal/stores/data_style/model/lines/index.ts +86 -59
  208. package/internal/stores/data_style/model/lines/vertex.ts +105 -42
  209. package/internal/stores/data_style/model/lines/visibility.ts +17 -4
  210. package/internal/stores/data_style/model/points/common.ts +8 -4
  211. package/internal/stores/data_style/model/points/index.ts +10 -3
  212. package/internal/stores/data_style/model/points/size.ts +12 -4
  213. package/internal/stores/data_style/model/points/visibility.ts +16 -6
  214. package/internal/stores/data_style/model/selection.ts +80 -58
  215. package/internal/stores/data_style/model/surfaces/color.ts +41 -11
  216. package/internal/stores/data_style/model/surfaces/common.ts +23 -6
  217. package/internal/stores/data_style/model/surfaces/index.ts +89 -59
  218. package/internal/stores/data_style/model/surfaces/polygon.ts +107 -67
  219. package/internal/stores/data_style/model/surfaces/vertex.ts +111 -67
  220. package/internal/stores/data_style/model/surfaces/visibility.ts +18 -5
  221. package/internal/stores/data_style/model/visibility.ts +82 -20
  222. package/internal/stores/data_style/state.ts +77 -65
  223. package/internal/stores/hybrid_viewer/brightness.ts +49 -31
  224. package/internal/stores/hybrid_viewer/camera.ts +191 -177
  225. package/internal/stores/hybrid_viewer/camera_animation.ts +11 -10
  226. package/internal/stores/hybrid_viewer/core.ts +64 -0
  227. package/internal/stores/hybrid_viewer/filters.ts +10 -16
  228. package/internal/stores/hybrid_viewer/highlight.ts +91 -130
  229. package/internal/stores/hybrid_viewer/ruler.ts +24 -15
  230. package/internal/stores/hybrid_viewer/scene.ts +96 -117
  231. package/internal/stores/hybrid_viewer/viewport.ts +74 -65
  232. package/internal/stores/hybrid_viewer/vtk_types.ts +13 -29
  233. package/internal/utils/api_fetch.ts +54 -23
  234. package/internal/utils/upload_file.ts +74 -53
  235. package/internal/utils/viewer_call.ts +22 -13
  236. package/internal/utils/ws_client.ts +24 -13
  237. package/nuxt.config.ts +58 -1
  238. package/package.json +20 -8
  239. package/server/api/cloud/extensions/run.post.ts +6 -10
  240. package/server/api/local/app/project_folder_path.post.ts +4 -4
  241. package/server/api/local/app/run_back.post.ts +5 -7
  242. package/server/api/local/app/run_viewer.post.ts +5 -7
  243. package/server/api/local/extensions/kill.post.ts +4 -3
  244. package/server/api/local/extensions/run.post.ts +7 -10
  245. package/server/api/local/extensions/upload.put.ts +44 -54
  246. package/server/api/microservice/app/get_is_app_ready.get.ts +4 -5
  247. package/server/api/microservice/app/set_app_base_url.post.ts +5 -6
  248. package/server/api/microservice/app/set_back_base_url.post.ts +5 -6
  249. package/server/api/microservice/app/set_is_app_ready.post.ts +5 -6
  250. package/server/api/microservice/app/set_viewer_base_url.post.ts +5 -6
  251. package/server/api/microservice/extensions/download.post.ts +5 -4
  252. package/server/api/serverless/run_cloud.post.ts +53 -11
  253. package/server/utils/app_config.ts +29 -22
  254. package/server/utils/cleanup.ts +60 -30
  255. package/server/utils/cloud.ts +9 -8
  256. package/server/utils/extension.ts +23 -9
  257. package/server/utils/microservices.ts +33 -24
  258. package/server/utils/path.ts +4 -4
  259. package/server/utils/scripts.ts +26 -23
  260. package/server/utils/server.ts +2 -2
  261. package/server/utils/server_config.ts +41 -27
  262. package/server/utils/stream.ts +6 -0
  263. package/server/utils/ws_client.ts +42 -8
  264. package/shared/scripts.ts +15 -10
  265. package/shared/utils/call_raw.ts +23 -16
  266. package/shared/utils/call_schema.ts +5 -8
  267. package/shared/utils/fetch_raw.ts +87 -47
  268. package/shared/utils/fetch_schema.ts +6 -9
  269. package/shared/utils/file.ts +8 -2
  270. package/shared/utils/response_handlers/load.ts +26 -11
  271. package/shared/utils/types.ts +9 -9
  272. package/shared/utils/validate_schema.ts +1 -1
  273. package/app/components/Viewer/ObjectTree/Views/ModelComponents.vue +0 -276
  274. package/server/types/vendor.d.ts +0 -64
  275. package/server/utils/server_config.js +0 -43
  276. package/shared/utils/call_raw.js +0 -30
  277. package/shared/utils/fetch_raw.js +0 -40
  278. /package/{opengeodeweb_front_schemas.js → .build/opengeodeweb_front_schemas.js} +0 -0
  279. /package/{server → .build/server}/utils/server.js +0 -0
  280. /package/{shared → .build/shared}/app_mode.js +0 -0
  281. /package/{shared → .build/shared}/utils/parse_boolean.js +0 -0
  282. /package/{shared → .build/shared}/utils/types.js +0 -0
@@ -8,7 +8,7 @@ import { useViewerStore } from "@ogw_front/stores/viewer";
8
8
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json";
9
9
 
10
10
  // The four per-component-type style composables (Surface/Line/Block/Corner) each expose a different, large set of methods (color, visibility, per-attribute-kind getters/setters...). This module only cares about looking a handful of them up dynamically by name, so a precise structural type for componentStyleFunctions isn't worth modelling here; `any` keeps the dynamic dispatch table honest about that.
11
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ // oxlint-disable-next-line no-explicit-any
12
12
  type ComponentStyleFunctions = Record<"Surface" | "Line" | "Block" | "Corner", any>;
13
13
 
14
14
  interface ModelComponent {
@@ -16,8 +16,21 @@ interface ModelComponent {
16
16
  type: string;
17
17
  }
18
18
 
19
+ async function callComponentStyleFunction(
20
+ // oxlint-disable-next-line no-explicit-any
21
+ target: any,
22
+ method: string,
23
+ ...args: unknown[]
24
+ ): Promise<unknown> {
25
+ // oxlint-disable-next-line no-unsafe-call, no-unsafe-member-access, no-unsafe-argument, no-unsafe-assignment -- ComponentStyleFunctions is deliberately dynamically typed; see comment above.
26
+ const result = await target[method](...args);
27
+ return result;
28
+ }
29
+
19
30
  const model_schemas = viewer_schemas.opengeodeweb_viewer.model;
20
- async function getModelComponentsMap(modelId: string) {
31
+ async function getModelComponentsMap(
32
+ modelId: string,
33
+ ): Promise<{ allComponents: ModelComponent[]; componentsMap: Record<string, ModelComponent> }> {
21
34
  const dataStore = useDataStore();
22
35
  const results = await Promise.all(
23
36
  MESH_COMPONENT_TYPES.map(async (type) => {
@@ -42,7 +55,7 @@ async function dispatchToComponentTypes(
42
55
  action: string,
43
56
  { componentStyleFunctions }: { componentStyleFunctions: ComponentStyleFunctions },
44
57
  ...args: unknown[]
45
- ) {
58
+ ): Promise<unknown[]> {
46
59
  const { componentsMap } = await getModelComponentsMap(modelId);
47
60
  const idsByComponent: { Block: string[]; Surface: string[]; Line: string[]; Corner: string[] } = {
48
61
  Block: [],
@@ -52,15 +65,17 @@ async function dispatchToComponentTypes(
52
65
  };
53
66
  for (const id of componentIds) {
54
67
  const type = componentsMap[id]?.type;
55
- if (type && type in idsByComponent) {
56
- (idsByComponent as Record<string, string[]>)[type]!.push(id);
68
+ if (type !== undefined && type in idsByComponent) {
69
+ (idsByComponent as Record<string, string[]>)[type]?.push(id);
57
70
  }
58
71
  }
59
72
  const promises: Promise<unknown>[] = [];
60
73
  if (action === "Visibility") {
61
74
  if (idsByComponent.Block.length > 0) {
62
75
  promises.push(
63
- componentStyleFunctions.Block.setModelBlocksVisibility(
76
+ callComponentStyleFunction(
77
+ componentStyleFunctions.Block,
78
+ "setModelBlocksVisibility",
64
79
  modelId,
65
80
  idsByComponent.Block,
66
81
  ...args,
@@ -69,7 +84,9 @@ async function dispatchToComponentTypes(
69
84
  }
70
85
  if (idsByComponent.Surface.length > 0) {
71
86
  promises.push(
72
- componentStyleFunctions.Surface.setModelSurfacesVisibility(
87
+ callComponentStyleFunction(
88
+ componentStyleFunctions.Surface,
89
+ "setModelSurfacesVisibility",
73
90
  modelId,
74
91
  idsByComponent.Surface,
75
92
  ...args,
@@ -78,12 +95,20 @@ async function dispatchToComponentTypes(
78
95
  }
79
96
  if (idsByComponent.Line.length > 0) {
80
97
  promises.push(
81
- componentStyleFunctions.Line.setModelLinesVisibility(modelId, idsByComponent.Line, ...args),
98
+ callComponentStyleFunction(
99
+ componentStyleFunctions.Line,
100
+ "setModelLinesVisibility",
101
+ modelId,
102
+ idsByComponent.Line,
103
+ ...args,
104
+ ),
82
105
  );
83
106
  }
84
107
  if (idsByComponent.Corner.length > 0) {
85
108
  promises.push(
86
- componentStyleFunctions.Corner.setModelCornersVisibility(
109
+ callComponentStyleFunction(
110
+ componentStyleFunctions.Corner,
111
+ "setModelCornersVisibility",
87
112
  modelId,
88
113
  idsByComponent.Corner,
89
114
  ...args,
@@ -93,12 +118,20 @@ async function dispatchToComponentTypes(
93
118
  } else if (action === "Color") {
94
119
  if (idsByComponent.Block.length > 0) {
95
120
  promises.push(
96
- componentStyleFunctions.Block.setModelBlocksColor(modelId, idsByComponent.Block, ...args),
121
+ callComponentStyleFunction(
122
+ componentStyleFunctions.Block,
123
+ "setModelBlocksColor",
124
+ modelId,
125
+ idsByComponent.Block,
126
+ ...args,
127
+ ),
97
128
  );
98
129
  }
99
130
  if (idsByComponent.Surface.length > 0) {
100
131
  promises.push(
101
- componentStyleFunctions.Surface.setModelSurfacesColor(
132
+ callComponentStyleFunction(
133
+ componentStyleFunctions.Surface,
134
+ "setModelSurfacesColor",
102
135
  modelId,
103
136
  idsByComponent.Surface,
104
137
  ...args,
@@ -107,12 +140,20 @@ async function dispatchToComponentTypes(
107
140
  }
108
141
  if (idsByComponent.Line.length > 0) {
109
142
  promises.push(
110
- componentStyleFunctions.Line.setModelLinesColor(modelId, idsByComponent.Line, ...args),
143
+ callComponentStyleFunction(
144
+ componentStyleFunctions.Line,
145
+ "setModelLinesColor",
146
+ modelId,
147
+ idsByComponent.Line,
148
+ ...args,
149
+ ),
111
150
  );
112
151
  }
113
152
  if (idsByComponent.Corner.length > 0) {
114
153
  promises.push(
115
- componentStyleFunctions.Corner.setModelCornersColor(
154
+ callComponentStyleFunction(
155
+ componentStyleFunctions.Corner,
156
+ "setModelCornersColor",
116
157
  modelId,
117
158
  idsByComponent.Corner,
118
159
  ...args,
@@ -122,8 +163,27 @@ async function dispatchToComponentTypes(
122
163
  }
123
164
  return Promise.all(promises);
124
165
  }
166
+ interface UseModelVisibilityStyleReturn {
167
+ modelVisibility: (modelId: string) => boolean | undefined;
168
+ setModelVisibility: (modelId: string, visibility: boolean) => Promise<unknown>;
169
+ setModelComponentsVisibility: (
170
+ modelId: string,
171
+ componentIds: string[],
172
+ visibility: boolean,
173
+ ) => Promise<unknown[]>;
174
+ setModelComponentTypeVisibility: (
175
+ modelId: string,
176
+ componentType: string,
177
+ visibility: boolean,
178
+ ) => Promise<void>;
179
+ modelComponentVisibility: (modelId: string, componentId: string) => boolean;
180
+ modelComponentTypeVisibility: (modelId: string, componentType: string) => boolean;
181
+ }
182
+
125
183
  // oxlint-disable-next-line max-lines-per-function
126
- function useModelVisibilityStyle(componentStyleFunctions: ComponentStyleFunctions) {
184
+ function useModelVisibilityStyle(
185
+ componentStyleFunctions: ComponentStyleFunctions,
186
+ ): UseModelVisibilityStyleReturn {
127
187
  const dataStore = useDataStore();
128
188
  const dataStyleState = useDataStyleState();
129
189
  const hybridViewerStore = useHybridViewerStore();
@@ -132,20 +192,20 @@ function useModelVisibilityStyle(componentStyleFunctions: ComponentStyleFunction
132
192
  function modelVisibility(modelId: string): boolean | undefined {
133
193
  return dataStyleState.getStyle(modelId).visibility;
134
194
  }
135
- function setModelVisibility(modelId: string, visibility: boolean) {
195
+ async function setModelVisibility(modelId: string, visibility: boolean): Promise<unknown> {
136
196
  const schema = model_schemas.visibility;
137
197
  const params = {
138
198
  id: modelId,
139
199
  visibility,
140
200
  };
141
- return viewerStore.request(
201
+ const result = await viewerStore.request(
142
202
  {
143
203
  schema,
144
204
  params,
145
205
  },
146
206
  {
147
207
  response_function: async () => {
148
- await hybridViewerStore.setVisibility(modelId, visibility);
208
+ hybridViewerStore.setVisibility(modelId, visibility);
149
209
  await dataStyleState.mutateStyle(modelId, {
150
210
  visibility,
151
211
  });
@@ -156,12 +216,13 @@ function useModelVisibilityStyle(componentStyleFunctions: ComponentStyleFunction
156
216
  },
157
217
  },
158
218
  );
219
+ return result;
159
220
  }
160
221
  async function setModelComponentTypeVisibility(
161
222
  modelId: string,
162
223
  componentType: string,
163
224
  visibility: boolean,
164
- ) {
225
+ ): Promise<void> {
165
226
  await modelCommonStyle.mutateModelComponentTypeStyle(modelId, componentType, {
166
227
  visibility,
167
228
  });
@@ -183,7 +244,7 @@ function useModelVisibilityStyle(componentStyleFunctions: ComponentStyleFunction
183
244
  modelId: string,
184
245
  componentIds: string[],
185
246
  visibility: boolean,
186
- ) {
247
+ ): Promise<unknown[]> {
187
248
  const typeIds = componentIds.filter((id) => MESH_COMPONENT_TYPES.includes(id));
188
249
  const individualIds = componentIds.filter((id) => !MESH_COMPONENT_TYPES.includes(id));
189
250
  const promises: Promise<unknown>[] = [];
@@ -203,7 +264,8 @@ function useModelVisibilityStyle(componentStyleFunctions: ComponentStyleFunction
203
264
  ),
204
265
  );
205
266
  }
206
- return await Promise.all(promises);
267
+ const results = await Promise.all(promises);
268
+ return results;
207
269
  }
208
270
  function modelComponentVisibility(modelId: string, componentId: string): boolean {
209
271
  const selection = useModelSelection(modelId, dataStyleState);
@@ -1,17 +1,14 @@
1
- // Not auto-fixable (eslint's sort-imports core rule has no autofixer) and this file's import order doesn't match its syntax-kind-then-alphabetical requirement - left as-is rather than manually reordered across the codebase for a purely cosmetic rule.
2
- // oxlint-disable eslint/sort-imports
3
1
  import type {
4
2
  ModelComponentStyle,
5
3
  ModelComponentTypeStyle,
6
4
  ObjectStyle,
7
5
  StyleValues,
8
6
  } from "./types";
9
- import { database } from "@ogw_internal/database/database";
7
+ import type { Observable as RxObservable } from "rxjs";
8
+ import { getTable } from "@ogw_internal/database/database";
10
9
  import { liveQuery } from "dexie";
11
10
  import merge from "lodash/merge";
12
11
  import { useObservable } from "@vueuse/rxjs";
13
- import type { Ref } from "vue";
14
- import type { Observable as RxObservable } from "rxjs";
15
12
 
16
13
  interface SharedState {
17
14
  styles: Ref<Record<string, ObjectStyle>>;
@@ -25,11 +22,14 @@ interface SharedState {
25
22
  ) => void;
26
23
  bulkUpdateComponentStyleCache: (
27
24
  modelId: string,
28
- componentStyleUpdates: { id_component: string; values: StyleValues }[],
25
+ componentStyleUpdates: readonly {
26
+ readonly id_component: string;
27
+ readonly values: StyleValues;
28
+ }[],
29
29
  ) => void;
30
30
  bulkUpdateComponentStylesCache: (
31
31
  modelId: string,
32
- componentIds: string[],
32
+ componentIds: readonly string[],
33
33
  styleValues: StyleValues,
34
34
  ) => void;
35
35
  updateModelComponentTypeStyleCache: (
@@ -48,32 +48,37 @@ function getSharedState(): SharedState {
48
48
  return sharedState;
49
49
  }
50
50
 
51
- const dataStyleTable = database.data_style!;
52
- const modelComponentDataStyleTable = database.model_component_datastyle!;
53
- const modelComponentTypeDataStyleTable = database.model_component_type_datastyle!;
51
+ const dataStyleTable = getTable<ObjectStyle>("data_style");
52
+ const modelComponentDataStyleTable = getTable<ModelComponentStyle>("model_component_datastyle");
53
+ const modelComponentTypeDataStyleTable = getTable<ModelComponentTypeStyle>(
54
+ "model_component_type_datastyle",
55
+ );
54
56
 
55
57
  // Dexie's `liveQuery` returns Dexie's own `Observable` type, structurally distinct
56
58
  // From rxjs's `Observable` that `useObservable` (from @vueuse/rxjs) expects, even
57
59
  // Though they're interoperable at runtime (both are plain subscribe-based streams).
60
+ const dataStyleLiveQuery = liveQuery(async () => {
61
+ const objectStyles = await dataStyleTable.toArray();
62
+ const stylesByObjectId: Record<string, ObjectStyle> = {};
63
+ for (const objectStyle of objectStyles) {
64
+ stylesByObjectId[objectStyle.id] = objectStyle;
65
+ }
66
+ return stylesByObjectId;
67
+ });
68
+
58
69
  const styles = useObservable<Record<string, ObjectStyle>, Record<string, ObjectStyle>>(
59
- liveQuery(async () => {
60
- const objectStyles = (await dataStyleTable.toArray()) as ObjectStyle[];
61
- const stylesByObjectId: Record<string, ObjectStyle> = {};
62
- for (const objectStyle of objectStyles) {
63
- stylesByObjectId[objectStyle.id] = objectStyle;
64
- }
65
- return stylesByObjectId;
66
- }) as unknown as RxObservable<Record<string, ObjectStyle>>,
70
+ // oxlint-disable-next-line no-unsafe-type-assertion
71
+ dataStyleLiveQuery as unknown as RxObservable<Record<string, ObjectStyle>>,
67
72
  { initialValue: {} },
68
73
  ) as Ref<Record<string, ObjectStyle>>;
69
74
 
70
75
  const modelComponentTypeStyles = ref<Record<string, ModelComponentTypeStyle>>({});
71
76
  const componentStyles = ref<Record<string, ModelComponentStyle>>({});
72
77
 
73
- async function loadFromDatabase() {
78
+ async function loadFromDatabase(): Promise<void> {
74
79
  const [fetchedTypeStyles, fetchedComponentStyles] = await Promise.all([
75
- modelComponentTypeDataStyleTable.toArray() as unknown as Promise<ModelComponentTypeStyle[]>,
76
- modelComponentDataStyleTable.toArray() as unknown as Promise<ModelComponentStyle[]>,
80
+ modelComponentTypeDataStyleTable.toArray(),
81
+ modelComponentDataStyleTable.toArray(),
77
82
  ]);
78
83
  const typeStylesMap: Record<string, ModelComponentTypeStyle> = {};
79
84
  for (const typeStyle of fetchedTypeStyles) {
@@ -90,44 +95,43 @@ function getSharedState(): SharedState {
90
95
  componentStyles.value = componentStylesMap;
91
96
  }
92
97
 
93
- loadFromDatabase();
98
+ void loadFromDatabase();
94
99
 
95
100
  function updateComponentStyleCache(
96
101
  modelId: string,
97
102
  componentId: string,
98
103
  styleValues: StyleValues,
99
- ) {
104
+ ): void {
100
105
  const cacheKey = `${modelId}_${componentId}`;
101
106
  const existingStyle = componentStyles.value[cacheKey];
102
- if (existingStyle) {
103
- merge(existingStyle, styleValues);
104
- } else {
107
+ if (existingStyle === undefined) {
105
108
  componentStyles.value[cacheKey] = merge(
106
109
  { id_model: modelId, id_component: componentId },
107
110
  styleValues,
108
111
  );
112
+ } else {
113
+ merge(existingStyle, styleValues);
109
114
  }
110
115
  }
111
116
 
112
117
  function bulkUpdateComponentStyleCache(
113
118
  modelId: string,
114
- componentStyleUpdates: { id_component: string; values: StyleValues }[],
115
- ) {
119
+ componentStyleUpdates: readonly {
120
+ readonly id_component: string;
121
+ readonly values: StyleValues;
122
+ }[],
123
+ ): void {
116
124
  const updatedComponentStyles = { ...componentStyles.value };
117
125
  for (const { id_component: componentId, values: styleValues } of componentStyleUpdates) {
118
126
  const cacheKey = `${modelId}_${componentId}`;
119
127
  const existingStyle = updatedComponentStyles[cacheKey];
120
- if (existingStyle) {
121
- updatedComponentStyles[cacheKey] = merge(
122
- {},
123
- existingStyle,
124
- styleValues,
125
- ) as ModelComponentStyle;
126
- } else {
128
+ if (existingStyle === undefined) {
127
129
  updatedComponentStyles[cacheKey] = merge(
128
130
  { id_model: modelId, id_component: componentId },
129
131
  styleValues,
130
132
  );
133
+ } else {
134
+ updatedComponentStyles[cacheKey] = merge({}, existingStyle, styleValues);
131
135
  }
132
136
  }
133
137
  componentStyles.value = updatedComponentStyles;
@@ -135,24 +139,20 @@ function getSharedState(): SharedState {
135
139
 
136
140
  function bulkUpdateComponentStylesCache(
137
141
  modelId: string,
138
- componentIds: string[],
142
+ componentIds: readonly string[],
139
143
  styleValues: StyleValues,
140
- ) {
144
+ ): void {
141
145
  const updatedComponentStyles = { ...componentStyles.value };
142
146
  for (const componentId of componentIds) {
143
147
  const cacheKey = `${modelId}_${componentId}`;
144
148
  const existingStyle = updatedComponentStyles[cacheKey];
145
- if (existingStyle) {
146
- updatedComponentStyles[cacheKey] = merge(
147
- {},
148
- existingStyle,
149
- styleValues,
150
- ) as ModelComponentStyle;
151
- } else {
149
+ if (existingStyle === undefined) {
152
150
  updatedComponentStyles[cacheKey] = merge(
153
151
  { id_model: modelId, id_component: componentId },
154
152
  styleValues,
155
153
  );
154
+ } else {
155
+ updatedComponentStyles[cacheKey] = merge({}, existingStyle, styleValues);
156
156
  }
157
157
  }
158
158
  componentStyles.value = updatedComponentStyles;
@@ -162,18 +162,14 @@ function getSharedState(): SharedState {
162
162
  modelId: string,
163
163
  componentType: string,
164
164
  styleValues: StyleValues,
165
- ) {
165
+ ): void {
166
166
  const cacheKey = `${modelId}_${componentType}`;
167
- if (!modelComponentTypeStyles.value[cacheKey]) {
168
- modelComponentTypeStyles.value[cacheKey] = { id_model: modelId, type: componentType };
169
- }
167
+ modelComponentTypeStyles.value[cacheKey] ??= { id_model: modelId, type: componentType };
170
168
  merge(modelComponentTypeStyles.value[cacheKey], styleValues);
171
169
  }
172
170
 
173
- function updateStyleCache(objectId: string, styleValues: StyleValues) {
174
- if (!styles.value[objectId]) {
175
- styles.value[objectId] = { id: objectId };
176
- }
171
+ function updateStyleCache(objectId: string, styleValues: StyleValues): void {
172
+ styles.value[objectId] ??= { id: objectId };
177
173
  merge(styles.value[objectId], styleValues);
178
174
  }
179
175
 
@@ -192,18 +188,30 @@ function getSharedState(): SharedState {
192
188
  return sharedState;
193
189
  }
194
190
 
191
+ interface DataStyleStateApi extends SharedState {
192
+ getStyle: (objectId: string) => ObjectStyle;
193
+ getComponentStyle: (modelId: string, componentId: string) => ModelComponentStyle;
194
+ getModelComponentTypeStyle: (modelId: string, componentType: string) => ModelComponentTypeStyle;
195
+ mutateStyle: (objectId: string, styleValues: StyleValues) => Promise<string>;
196
+ objectVisibility: ComputedRef<(objectId: string) => boolean | undefined>;
197
+ selectedObjects: ComputedRef<string[]>;
198
+ clear: () => Promise<void>;
199
+ }
200
+
195
201
  // oxlint-disable-next-line max-lines-per-function
196
- export function useDataStyleState() {
197
- const dataStyleTable = database.data_style!;
198
- const modelComponentDataStyleTable = database.model_component_datastyle!;
199
- const modelComponentTypeDataStyleTable = database.model_component_type_datastyle!;
202
+ export function useDataStyleState(): DataStyleStateApi {
203
+ const dataStyleTable = getTable<ObjectStyle>("data_style");
204
+ const modelComponentDataStyleTable = getTable<ModelComponentStyle>("model_component_datastyle");
205
+ const modelComponentTypeDataStyleTable = getTable<ModelComponentTypeStyle>(
206
+ "model_component_type_datastyle",
207
+ );
200
208
 
201
209
  const state = getSharedState();
202
210
  const { styles, modelComponentTypeStyles, componentStyles } = state;
203
211
 
204
212
  const objectVisibility = computed(() => (objectId: string): boolean | undefined => {
205
213
  const style = styles.value[objectId];
206
- if (style) {
214
+ if (style !== undefined) {
207
215
  return style.visibility;
208
216
  }
209
217
  return false;
@@ -220,19 +228,26 @@ export function useDataStyleState() {
220
228
  });
221
229
 
222
230
  function getStyle(objectId: string): ObjectStyle {
223
- return { ...toRaw(styles.value[objectId]) } as ObjectStyle;
231
+ const style = styles.value[objectId];
232
+ if (style === undefined) {
233
+ return { id: objectId };
234
+ }
235
+ return { ...toRaw(style) };
224
236
  }
225
237
 
226
- function mutateStyle(objectId: string, styleValues: StyleValues) {
238
+ async function mutateStyle(objectId: string, styleValues: StyleValues): Promise<string> {
227
239
  state.updateStyleCache(objectId, styleValues);
228
240
  const currentStyle = getStyle(objectId);
229
241
  merge(currentStyle, styleValues);
230
- return dataStyleTable.put(structuredClone({ ...toRaw(currentStyle), id: objectId }));
242
+ const savedId = await dataStyleTable.put(
243
+ structuredClone({ ...toRaw(currentStyle), id: objectId }),
244
+ );
245
+ return savedId;
231
246
  }
232
247
 
233
248
  function getComponentStyle(modelId: string, componentId: string): ModelComponentStyle {
234
249
  const cacheKey = `${modelId}_${componentId}`;
235
- return merge({ coloring: {} }, componentStyles.value[cacheKey]) as ModelComponentStyle;
250
+ return merge({ coloring: {} }, componentStyles.value[cacheKey]);
236
251
  }
237
252
 
238
253
  function getModelComponentTypeStyle(
@@ -240,10 +255,7 @@ export function useDataStyleState() {
240
255
  componentType: string,
241
256
  ): ModelComponentTypeStyle {
242
257
  const cacheKey = `${modelId}_${componentType}`;
243
- return merge(
244
- { coloring: {} },
245
- modelComponentTypeStyles.value[cacheKey],
246
- ) as ModelComponentTypeStyle;
258
+ return merge({ coloring: {} }, modelComponentTypeStyles.value[cacheKey]);
247
259
  }
248
260
 
249
261
  async function clear(): Promise<void> {
@@ -1,9 +1,5 @@
1
- // Not auto-fixable (eslint's sort-imports core rule has no autofixer) and this file's import order doesn't match its syntax-kind-then-alphabetical requirement - left as-is rather than manually reordered across the codebase for a purely cosmetic rule.
2
- // oxlint-disable eslint/sort-imports
3
1
  import { BACKGROUND_GREY_VALUE, RGB_MAX } from "./constants";
4
- import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
5
- import type { Ref } from "vue";
6
- import type { HybridViewerStorePublic } from "./vtk_types";
2
+ import { useHybridViewerCore } from "./core";
7
3
 
8
4
  const RGBA_CHANNELS = 4;
9
5
  const SAMPLE_SIZE = 10;
@@ -25,7 +21,14 @@ interface BrightnessOptions {
25
21
  offscreenCanvas: HTMLCanvasElement | undefined;
26
22
  }
27
23
 
28
- function mapRect(rect: Rect, latestImage: DrawableImage, canvasRect: DOMRect) {
24
+ interface RelativeRect {
25
+ relX: number;
26
+ relY: number;
27
+ relW: number;
28
+ relH: number;
29
+ }
30
+
31
+ function mapRect(rect: Rect, latestImage: DrawableImage, canvasRect: DOMRect): RelativeRect {
29
32
  const scaleX = latestImage.width / canvasRect.width;
30
33
  const scaleY = latestImage.height / canvasRect.height;
31
34
  return {
@@ -35,46 +38,61 @@ function mapRect(rect: Rect, latestImage: DrawableImage, canvasRect: DOMRect) {
35
38
  relH: rect.height * scaleY,
36
39
  };
37
40
  }
41
+
42
+ function sampleMinBrightness(
43
+ ctx: CanvasRenderingContext2D,
44
+ image: DrawableImage,
45
+ relRect: RelativeRect,
46
+ ): number {
47
+ ctx.drawImage(
48
+ image,
49
+ Math.max(0, relRect.relX),
50
+ Math.max(0, relRect.relY),
51
+ Math.min(image.width, relRect.relW),
52
+ Math.min(image.height, relRect.relH),
53
+ 0,
54
+ 0,
55
+ SAMPLE_SIZE,
56
+ SAMPLE_SIZE,
57
+ );
58
+ const { data } = ctx.getImageData(0, 0, SAMPLE_SIZE, SAMPLE_SIZE);
59
+ let minBrightness = 1;
60
+ for (let i = 0; i < TOTAL_CHANNELS; i += RGBA_CHANNELS) {
61
+ const brightness = ((data[i] ?? 0) + (data[i + 1] ?? 0) + (data[i + 2] ?? 0)) / (3 * RGB_MAX);
62
+ if (brightness < minBrightness) {
63
+ minBrightness = brightness;
64
+ }
65
+ }
66
+ return minBrightness;
67
+ }
68
+
38
69
  function computeAverageBrightness(rect: Rect, options: BrightnessOptions): number {
39
70
  const { latestImage, offscreenCtx, offscreenCanvas } = options;
40
- const { genericRenderWindow } = useHybridViewerStore() as unknown as HybridViewerStorePublic;
71
+ const { genericRenderWindow } = useHybridViewerCore();
41
72
  if (!latestImage || !offscreenCtx || !offscreenCanvas || !genericRenderWindow.value) {
42
73
  return BACKGROUND_GREY_VALUE / RGB_MAX;
43
74
  }
44
- const canvas = genericRenderWindow.value.getApiSpecificRenderWindow().getCanvas();
45
- if (!canvas) {
75
+ // oxlint-disable-next-line no-unsafe-assignment -- vtk.js has no types for getApiSpecificRenderWindow(); narrowed below.
76
+ const webGLRenderWindow = genericRenderWindow.value.getApiSpecificRenderWindow();
77
+ // oxlint-disable-next-line no-unsafe-type-assertion -- trusted vtk.js OpenGL render window API boundary.
78
+ const apiSpecificRenderWindow = webGLRenderWindow as unknown as {
79
+ getCanvas: () => HTMLCanvasElement | null | undefined;
80
+ };
81
+ const canvas = apiSpecificRenderWindow.getCanvas();
82
+ if (canvas === undefined || canvas === null) {
46
83
  return BACKGROUND_GREY_VALUE / RGB_MAX;
47
84
  }
48
85
  if (rect.width <= 0 || rect.height <= 0) {
49
86
  return BACKGROUND_GREY_VALUE / RGB_MAX;
50
87
  }
51
- const { relX, relY, relW, relH } = mapRect(rect, latestImage, canvas.getBoundingClientRect());
52
- if (relW <= 0 || relH <= 0) {
88
+ const relRect = mapRect(rect, latestImage, canvas.getBoundingClientRect());
89
+ if (relRect.relW <= 0 || relRect.relH <= 0) {
53
90
  return BACKGROUND_GREY_VALUE / RGB_MAX;
54
91
  }
55
92
  offscreenCanvas.width = SAMPLE_SIZE;
56
93
  offscreenCanvas.height = SAMPLE_SIZE;
57
94
  try {
58
- offscreenCtx.drawImage(
59
- latestImage,
60
- Math.max(0, relX),
61
- Math.max(0, relY),
62
- Math.min(latestImage.width, relW),
63
- Math.min(latestImage.height, relH),
64
- 0,
65
- 0,
66
- SAMPLE_SIZE,
67
- SAMPLE_SIZE,
68
- );
69
- const { data } = offscreenCtx.getImageData(0, 0, SAMPLE_SIZE, SAMPLE_SIZE);
70
- let minBrightness = 1;
71
- for (let i = 0; i < TOTAL_CHANNELS; i += RGBA_CHANNELS) {
72
- const brightness = (data[i]! + data[i + 1]! + data[i + 2]!) / (3 * RGB_MAX);
73
- if (brightness < minBrightness) {
74
- minBrightness = brightness;
75
- }
76
- }
77
- return minBrightness;
95
+ return sampleMinBrightness(offscreenCtx, latestImage, relRect);
78
96
  } catch {
79
97
  return BACKGROUND_GREY_VALUE / RGB_MAX;
80
98
  }