@underpostnet/cyberia 3.3.73 → 3.3.76

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 (228) hide show
  1. package/.env.example +17 -5
  2. package/.github/workflows/coverall.cyberia.ci.yml +5 -0
  3. package/.github/workflows/docker-image.cyberia-client.ci.yml +1 -1
  4. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +1 -1
  5. package/.github/workflows/docker-image.cyberia-server.ci.yml +1 -1
  6. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +1 -1
  7. package/.github/workflows/docker-image.engine-cyberia.ci.yml +1 -1
  8. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +1 -1
  9. package/.github/workflows/publish.cyberia.ci.yml +44 -0
  10. package/AGENTS.md +61 -12
  11. package/CHANGELOG.md +126 -41
  12. package/CLI-HELP.md +19 -12
  13. package/Dockerfile +1 -1
  14. package/Dockerfile.dev +1 -1
  15. package/Dockerfile.test +2 -2
  16. package/README.md +28 -28
  17. package/bin/build.js +37 -17
  18. package/bin/cyberia.js +1247 -1373
  19. package/bin/index.js +1247 -1373
  20. package/compose.env +17 -5
  21. package/conf.js +7 -3
  22. package/deploy/cyberia-client/deploy.sh +10 -11
  23. package/deploy/cyberia-client/package.sh +0 -1
  24. package/deploy/cyberia-client/state.sh +3 -2
  25. package/deploy/cyberia-server/deploy.sh +10 -11
  26. package/deploy/cyberia-server/package.sh +0 -1
  27. package/deploy/cyberia-server/state.sh +3 -2
  28. package/deploy/dd-cyberia/deploy.sh +5 -5
  29. package/deploy/dd-cyberia/init.sh +15 -14
  30. package/deploy/dd-cyberia/package.sh +0 -1
  31. package/deploy/dd-cyberia/state.sh +2 -2
  32. package/deploy/dd-cyberia/sync-deploy.sh +139 -75
  33. package/deploy/lib/config.sh +29 -0
  34. package/deploy/lib/github-actions-logging.sh +92 -76
  35. package/deploy/lib/host.sh +27 -18
  36. package/deploy/lib/state.sh +4 -1
  37. package/deploy/pwa-microservices-template/deploy.sh +10 -8
  38. package/deploy/release/deploy.sh +0 -2
  39. package/deployment.yaml +1 -1
  40. package/docker-compose.yml +23 -17
  41. package/hardhat/package-lock.json +2 -2
  42. package/hardhat/package.json +1 -1
  43. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
  44. package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +1 -1
  45. package/manifests/deployment/dd-cyberia-development/deployment.yaml +1 -1
  46. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  47. package/manifests/deployment/mongo-express/deployment.yaml +46 -27
  48. package/manifests/deployment/mongo-express/kustomization.yaml +9 -0
  49. package/manifests/deployment/mongo-express/mongo-express-nodeport.yaml +18 -0
  50. package/manifests/deployment/mongo-express/service.yaml +16 -0
  51. package/manifests/deployment/mongo-express-no-auth/disable-mongodb-auth.yaml +16 -0
  52. package/manifests/deployment/mongo-express-no-auth/kustomization.yaml +16 -0
  53. package/package.json +19 -17
  54. package/scripts/test-monitor.sh +3 -3
  55. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +14 -9
  56. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +36 -5
  57. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +5 -0
  58. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +88 -184
  59. package/src/api/cyberia-action/cyberia-action.router.js +2 -2
  60. package/src/api/cyberia-action/cyberia-action.service.js +3 -4
  61. package/src/api/cyberia-audio/cyberia-audio.controller.js +6 -0
  62. package/src/api/cyberia-audio/cyberia-audio.model.js +61 -0
  63. package/src/api/cyberia-audio/cyberia-audio.router.js +21 -0
  64. package/src/api/cyberia-audio/cyberia-audio.service.js +220 -0
  65. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +1 -3
  66. package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +10 -19
  67. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +12 -34
  68. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +15 -32
  69. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +1 -1
  70. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +1 -1
  71. package/src/api/cyberia-entity/cyberia-entity.model.js +2 -0
  72. package/src/api/cyberia-entity/cyberia-entity.service.js +1 -1
  73. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +8 -2
  74. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +31 -20
  75. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +16 -1
  76. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +466 -3
  77. package/src/api/cyberia-instance/cyberia-fallback-capture.js +87 -51
  78. package/src/api/cyberia-instance/cyberia-fallback-world.js +21 -40
  79. package/src/api/cyberia-instance/cyberia-instance-boot.service.js +5 -5
  80. package/src/api/cyberia-instance/cyberia-instance-items.js +98 -0
  81. package/src/api/cyberia-instance/cyberia-instance-map.service.js +34 -141
  82. package/src/api/cyberia-instance/cyberia-instance.controller.js +1 -4
  83. package/src/api/cyberia-instance/cyberia-instance.model.js +0 -14
  84. package/src/api/cyberia-instance/cyberia-instance.router.js +3 -16
  85. package/src/api/cyberia-instance/cyberia-instance.service.js +3 -43
  86. package/src/api/cyberia-instance/cyberia-world-generator.js +8 -13
  87. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +49 -75
  88. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +74 -1
  89. package/src/api/cyberia-map/cyberia-map.service.js +6 -2
  90. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.controller.js +31 -0
  91. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.model.js +56 -0
  92. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.router.js +33 -0
  93. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +189 -0
  94. package/src/api/cyberia-quest/cyberia-quest.router.js +3 -3
  95. package/src/api/cyberia-quest/cyberia-quest.service.js +3 -3
  96. package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +1 -1
  97. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +403 -188
  98. package/src/api/cyberia-skill/cyberia-skill.model.js +6 -6
  99. package/src/api/file/file.ref.js +153 -0
  100. package/src/api/file/file.ref.json +11 -2
  101. package/src/api/object-layer/object-layer.model.js +47 -12
  102. package/src/api/object-layer/object-layer.router.js +10 -3
  103. package/src/api/object-layer/object-layer.service.js +113 -120
  104. package/src/cli/app.js +12 -1
  105. package/src/cli/client.js +2 -2
  106. package/src/cli/cluster.js +7 -0
  107. package/src/cli/deploy.js +4 -4
  108. package/src/cli/docker-compose.js +1 -1
  109. package/src/cli/fs-selection.js +115 -0
  110. package/src/cli/fs.js +158 -342
  111. package/src/cli/index.js +22 -10
  112. package/src/cli/repository.js +28 -0
  113. package/src/cli/run.js +71 -197
  114. package/src/cli/test.js +4 -0
  115. package/src/cli/wireguard.js +32 -31
  116. package/src/client/components/core/Docs.js +77 -100
  117. package/src/client/components/core/Modal.js +56 -1
  118. package/src/client/components/cyberia/ActionEngineCyberia.js +12 -36
  119. package/src/client/components/cyberia/EntityEngineCyberia.js +492 -121
  120. package/src/client/components/cyberia/InstanceEngineCyberia.js +129 -160
  121. package/src/client/components/cyberia/InstanceSelectionView.js +7 -1
  122. package/src/client/components/cyberia/MapEngineCyberia.js +175 -69
  123. package/src/client/components/cyberia/ObjectLayerEngine.js +1011 -97
  124. package/src/client/components/cyberia/ObjectLayerEngineModal.js +81 -155
  125. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +113 -98
  126. package/src/client/components/cyberia/SharedDefaultsCyberia.js +215 -56
  127. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +0 -34
  128. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +1 -1
  129. package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +712 -76
  130. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +0 -4
  131. package/src/client/public/cyberia-docs/ARCHITECTURE.md +15 -15
  132. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +280 -24
  133. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +51 -29
  134. package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +52 -53
  135. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +16 -11
  136. package/src/client/public/cyberia-docs/CYBERIA.md +28 -28
  137. package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +11 -5
  138. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  139. package/src/client/public/cyberia-docs/STATS-PROGRESSION.md +217 -0
  140. package/src/client/public/cyberia-docs/WHITE-PAPER.md +20 -12
  141. package/src/client/services/cyberia-audio/cyberia-audio.service.js +99 -0
  142. package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +38 -0
  143. package/src/client/services/cyberia-instance/cyberia-instance.management.js +5 -4
  144. package/src/client/services/cyberia-instance/cyberia-instance.service.js +0 -40
  145. package/src/client/services/cyberia-map/cyberia-map.management.js +5 -4
  146. package/src/client/services/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +138 -0
  147. package/src/client/services/object-layer/object-layer.management.js +6 -10
  148. package/src/client/services/object-layer/object-layer.service.js +3 -1
  149. package/src/client-builder/client-build-docs.js +52 -52
  150. package/src/client-builder/client-build.js +67 -44
  151. package/src/client-builder/client-bundle.js +347 -0
  152. package/src/db/mongo/MongoExpress.js +187 -0
  153. package/src/grpc/cyberia/grpc-server.js +5 -7
  154. package/src/index.js +1 -1
  155. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +143 -146
  156. package/src/projects/cyberia/atlas-sprite-sheet-store.js +391 -0
  157. package/src/projects/cyberia/besu-genesis-generator.js +5 -14
  158. package/src/projects/cyberia/boot-contract-fixtures.js +32 -0
  159. package/src/projects/cyberia/catalog-cyberia.js +3 -2
  160. package/src/projects/cyberia/gemini-client.js +3 -3
  161. package/src/projects/cyberia/generate-saga.js +4 -11
  162. package/src/projects/cyberia/hot-reload-trigger.js +17 -28
  163. package/src/projects/cyberia/instance-backup.js +210 -0
  164. package/src/projects/cyberia/instance-data.js +177 -257
  165. package/src/projects/cyberia/map-preview-generator.js +32 -68
  166. package/src/projects/cyberia/object-layer.js +152 -319
  167. package/src/projects/cyberia/seed-audio.js +139 -0
  168. package/src/projects/cyberia/semantic-layer-generator-skin.js +2 -8
  169. package/src/projects/cyberia/semantic-layer-generator.js +2 -18
  170. package/src/projects/cyberia/stat-balance.js +81 -0
  171. package/src/projects/cyberia/stat-commands.js +23 -0
  172. package/src/projects/cyberia/stat-contract-generator.js +101 -0
  173. package/src/runtime/cyberia-client/Dockerfile +8 -4
  174. package/src/runtime/cyberia-client/Dockerfile.dev +5 -2
  175. package/src/runtime/cyberia-server/Dockerfile +9 -2
  176. package/src/runtime/cyberia-server/Dockerfile.dev +8 -1
  177. package/src/runtime/engine-cyberia/Dockerfile +1 -1
  178. package/src/runtime/engine-cyberia/Dockerfile.dev +1 -1
  179. package/src/runtime/engine-cyberia/Dockerfile.test +2 -2
  180. package/src/runtime/engine-cyberia/compose.env +17 -5
  181. package/src/runtime/engine-cyberia/docker-compose.yml +23 -17
  182. package/src/server/build/coverage.js +113 -42
  183. package/src/server/build/package.js +55 -12
  184. package/src/server/build/testing.js +59 -9
  185. package/src/server/network/middlewares.js +8 -2
  186. package/src/server/ops/logger.js +70 -35
  187. package/src/server/runtime/conf.js +4 -2
  188. package/src/server/storage/data-query.js +16 -0
  189. package/src/server/storage/downloader.js +62 -14
  190. package/src/server/storage/zip.js +153 -0
  191. package/test/integration/app/cyberia/atlas-sprite-sheet-store.test.js +402 -0
  192. package/test/integration/app/cyberia/atlas-sprite-sheet.test.js +86 -0
  193. package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +34 -0
  194. package/test/integration/app/cyberia/cyberia-entity-type-default.test.js +842 -0
  195. package/test/integration/app/cyberia/cyberia-instance-conf-coerce.test.js +53 -0
  196. package/test/integration/app/cyberia/cyberia-instance-conf-defaults.test.js +16 -22
  197. package/test/integration/app/cyberia/cyberia-instance-items.test.js +90 -0
  198. package/test/integration/app/cyberia/cyberia-load.test.js +6 -7
  199. package/test/integration/app/cyberia/cyberia-map-audio-conf.test.js +256 -0
  200. package/test/integration/app/cyberia/cyberia-stats.test.js +150 -0
  201. package/test/integration/app/cyberia/fallback-world-capture.test.js +87 -2
  202. package/test/integration/app/cyberia/object-layer-item-selection.test.js +56 -0
  203. package/test/integration/app/cyberia/object-layer-natural-key.test.js +32 -0
  204. package/test/integration/app/cyberia/seed-audio.test.js +275 -0
  205. package/test/integration/infra/2-network/wireguard-cli.test.js +33 -9
  206. package/test/integration/infra/2-network/wireguard-edge.test.js +58 -18
  207. package/test/integration/infra/3-cluster/mongo-express-deploy.test.js +156 -0
  208. package/test/integration/infra/4-ingress/api-cross-origin.test.js +79 -0
  209. package/test/unit/client-build-docs.test.js +97 -70
  210. package/test/unit/client-bundle.test.js +313 -0
  211. package/test/unit/conf-resolution.test.js +17 -0
  212. package/test/unit/coverage-artifact.test.js +120 -29
  213. package/test/unit/cyberia/instance-backup.test.js +183 -0
  214. package/test/unit/cyberia/instance-object-layer-items.test.js +46 -0
  215. package/test/unit/cyberia/publish-workflow.test.js +22 -0
  216. package/test/unit/cyberia/stat-balance.test.js +69 -0
  217. package/test/unit/deploy-log-table.test.js +76 -5
  218. package/test/unit/downloader-integrity.test.js +98 -0
  219. package/test/unit/file-reference-registry.test.js +141 -0
  220. package/test/unit/fs-storage-paths.test.js +596 -0
  221. package/test/unit/logger-redaction.test.js +29 -0
  222. package/test/unit/package.test.js +70 -16
  223. package/test/unit/prepare-host.test.js +84 -1
  224. package/test/unit/test-tiers.test.js +27 -0
  225. package/test/unit/zip-archive.test.js +142 -0
  226. package/vitest.config.js +11 -3
  227. package/src/api/cyberia-instance/cyberia-fallback-default-items.js +0 -63
  228. package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +0 -368
@@ -173,10 +173,7 @@ class Docs {
173
173
 
174
174
  Modal.Data[ModalId].onObserverListener[ModalId] = () => {
175
175
  resizeIframe();
176
- if (type.match('coverage')) {
177
- simpleIconsRender(`.doc-icon-coverage`);
178
- simpleIconsRender(`.doc-icon-coverage-link`);
179
- }
176
+ if (type.match('coverage')) simpleIconsRender(`.doc-icon-coverage`);
180
177
  };
181
178
  Modal.Data[ModalId].onObserverListener[ModalId]();
182
179
  // The observer fires on modal mutations, not on viewport changes; a rotate
@@ -189,105 +186,87 @@ class Docs {
189
186
  closeModalRouteChangeEvent({ closedId: ModalId });
190
187
  };
191
188
  }
192
- static Data = [
193
- {
194
- type: 'repo',
195
- icon: html`<i class="fab fa-github"></i>`,
196
- text: `Last Release`,
197
- url: function () {
198
- const tokenOpts = Docs.Tokens['modal-docs'];
199
- if (tokenOpts && tokenOpts.lastReleaseUrl) return tokenOpts.lastReleaseUrl();
200
- return githubUrl(packageRepository());
201
- },
202
- },
203
- {
204
- type: 'demo',
205
- icon: html`<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 32 32">
206
- <path fill="currentColor" d="M20 2v12l10-6z" />
207
- <path
208
- fill="currentColor"
209
- d="M28 14v8H4V6h10V4H4a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h8v4H8v2h16v-2h-4v-4h8a2 2 0 0 0 2-2v-8zM18 28h-4v-4h4z"
210
- />
211
- </svg>`,
212
- text: html`Demo`,
213
- url: function () {
214
- const tokenOpts = Docs.Tokens['modal-docs'];
215
- if (tokenOpts && tokenOpts.demoUrl) return tokenOpts.demoUrl();
216
- return githubPagesUrl(packageRepository());
217
- },
218
- },
219
- {
220
- type: 'src',
221
- icon: html`<i class="fa-brands fa-osi"></i>`,
222
- text: 'Source Docs',
223
- url: function () {
224
- return `${getProxyPath()}docs/engine/${window.renderPayload.version.replace('v', '')}`;
225
- },
226
- },
227
- {
228
- type: 'api',
229
- icon: html`<i class="fa-solid fa-arrows-turn-to-dots"></i>`,
230
- text: `Api Docs`,
231
- url: function () {
232
- return `${getProxyPath()}api-docs`;
233
- },
234
- },
235
- {
236
- type: 'coverage',
189
+ // One entry per coverage report the build declared, each framed from /docs/coverage/<id>.
190
+ static coverageReports = () =>
191
+ (window.renderPayload.coverage ?? []).map(({ id, label }) => ({
192
+ type: `coverage-${id}`,
237
193
  icon: html`<img height="20" width="20" class="doc-icon-coverage" />`,
238
- text: `Coverage report`,
239
- url: function () {
240
- const tokenOpts = Docs.Tokens['modal-docs'];
241
- if (tokenOpts && tokenOpts.coverageUrl) return tokenOpts.coverageUrl();
242
- return `${getProxyPath()}docs/coverage`;
194
+ text: label,
195
+ url: () => `${getProxyPath()}docs/coverage/${id}`,
196
+ }));
197
+ static get Data() {
198
+ return [
199
+ {
200
+ type: 'repo',
201
+ external: true,
202
+ icon: html`<i class="fab fa-github"></i>`,
203
+ text: `Last Release`,
204
+ url: function () {
205
+ const tokenOpts = Docs.Tokens['modal-docs'];
206
+ if (tokenOpts && tokenOpts.lastReleaseUrl) return tokenOpts.lastReleaseUrl();
207
+ return githubUrl(packageRepository());
208
+ },
243
209
  },
244
- themeEvent: () => {
245
- if (s(`.doc-icon-coverage`)) setTimeout(() => simpleIconsRender(`.doc-icon-coverage`));
210
+ {
211
+ type: 'demo',
212
+ external: true,
213
+ icon: html`<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 32 32">
214
+ <path fill="currentColor" d="M20 2v12l10-6z" />
215
+ <path
216
+ fill="currentColor"
217
+ d="M28 14v8H4V6h10V4H4a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h8v4H8v2h16v-2h-4v-4h8a2 2 0 0 0 2-2v-8zM18 28h-4v-4h4z"
218
+ />
219
+ </svg>`,
220
+ text: html`Demo`,
221
+ url: function () {
222
+ const tokenOpts = Docs.Tokens['modal-docs'];
223
+ if (tokenOpts && tokenOpts.demoUrl) return tokenOpts.demoUrl();
224
+ return githubPagesUrl(packageRepository());
225
+ },
246
226
  },
247
- },
248
- {
249
- type: 'coverage-link',
250
- icon: html`<img height="20" width="20" class="doc-icon-coverage-link" />`,
251
- text: `Coverage`,
252
- url: function () {
253
- const tokenOpts = Docs.Tokens['modal-docs'];
254
- if (tokenOpts && tokenOpts.coverageLinkUrl) return tokenOpts.coverageLinkUrl();
255
- return coverallsUrl();
227
+ {
228
+ type: 'src',
229
+ icon: html`<i class="fa-brands fa-osi"></i>`,
230
+ text: 'Source Docs',
231
+ url: function () {
232
+ return `${getProxyPath()}docs/engine/${window.renderPayload.version.replace('v', '')}`;
233
+ },
256
234
  },
257
- themeEvent: () => {
258
- if (s(`.doc-icon-coverage-link`)) setTimeout(() => simpleIconsRender(`.doc-icon-coverage-link`));
235
+ {
236
+ type: 'api',
237
+ icon: html`<i class="fa-solid fa-arrows-turn-to-dots"></i>`,
238
+ text: `Api Docs`,
239
+ url: function () {
240
+ return `${getProxyPath()}api-docs`;
241
+ },
259
242
  },
260
- },
261
- ];
243
+ ...Docs.coverageReports(),
244
+ {
245
+ type: 'coverage-link',
246
+ external: true,
247
+ icon: html`<img height="20" width="20" class="doc-icon-coverage" />`,
248
+ text: `Coverage`,
249
+ url: function () {
250
+ const tokenOpts = Docs.Tokens['modal-docs'];
251
+ if (tokenOpts && tokenOpts.coverageLinkUrl) return tokenOpts.coverageLinkUrl();
252
+ return coverallsUrl();
253
+ },
254
+ },
255
+ ];
256
+ }
262
257
  static Tokens = {};
263
258
  static async instance(options = {}) {
264
259
  const { idModal } = options;
265
260
  Docs.Tokens[idModal] = options;
266
261
  setTimeout(() => {
267
- s(`.btn-docs-src`).onclick = async () => {
268
- setQueryPath({ path: 'docs', queryPath: 'src' });
269
- await Docs.RenderModal('src', idModal);
270
- };
271
- s(`.btn-docs-api`).onclick = async () => {
272
- setQueryPath({ path: 'docs', queryPath: 'api' });
273
- await Docs.RenderModal('api', idModal);
274
- };
275
- s(`.btn-docs-coverage`).onclick = async () => {
276
- setQueryPath({ path: 'docs', queryPath: 'coverage' });
277
- await Docs.RenderModal('coverage', idModal);
278
- };
279
- s(`.btn-docs-coverage-link`).onclick = () => {
280
- const docData = Docs.Data.find((d) => d.type === 'coverage-link');
281
- location.href = docData.url();
282
- };
283
- s(`.btn-docs-repo`).onclick = () => {
284
- const docData = Docs.Data.find((d) => d.type === 'repo');
285
- location.href = docData.url();
286
- };
287
- s(`.btn-docs-demo`).onclick = () => {
288
- const docData = Docs.Data.find((d) => d.type === 'demo');
289
- location.href = docData.url();
290
- };
262
+ // An external entry leaves the app; the rest open in a framed modal on their own route.
263
+ for (const docData of Docs.Data) {
264
+ s(`.btn-docs-${docData.type}`).onclick = async () => {
265
+ if (docData.external) return (location.href = docData.url());
266
+ setQueryPath({ path: 'docs', queryPath: docData.type });
267
+ await Docs.RenderModal(docData.type, idModal);
268
+ };
269
+ }
291
270
  listenQueryPathInstance({
292
271
  id: options.idModal,
293
272
  routeId: 'docs',
@@ -301,13 +280,11 @@ class Docs {
301
280
  },
302
281
  });
303
282
  });
304
- // Register theme events for items that have them (Docs-specific concern)
305
- for (const docData of Docs.Data) {
306
- if (docData.themeEvent) {
307
- ThemeEvents[`doc-icon-${docData.type}`] = docData.themeEvent;
308
- setTimeout(ThemeEvents[`doc-icon-${docData.type}`]);
309
- }
310
- }
283
+ // The coverage icons are tinted to the theme's text colour, so they follow theme changes.
284
+ ThemeEvents['doc-icon-coverage'] = () => {
285
+ if (s(`.doc-icon-coverage`)) setTimeout(() => simpleIconsRender(`.doc-icon-coverage`));
286
+ };
287
+ setTimeout(ThemeEvents['doc-icon-coverage']);
311
288
  // Build submenu items and populate — submenu system is owned by Modal
312
289
  Modal.subMenuPopulate('docs', await Modal.buildSubMenuItemsHtml('docs', Docs.Data, options));
313
290
 
@@ -415,6 +415,17 @@ class Modal {
415
415
  },
416
416
  { key: `slide-menu-${idModal}` },
417
417
  );
418
+ // The fixed hamburger only opens the menu: it shows while the top bar is collapsed
419
+ // and the menu is closed. An open menu (50px or full) carries its own controls and
420
+ // already pushes the views aside, so neither the button nor the title padding apply.
421
+ const syncFixedMenuButton = () => {
422
+ const fixed = s(`.main-btn-menu-top-fixed-container`);
423
+ if (!fixed) return;
424
+ const collapsed = s(`.main-body-btn-ui-close`) && s(`.main-body-btn-ui-close`).classList.contains('hide');
425
+ const active = collapsed && Modal.Data[idModal][options.mode].width === 0;
426
+ fixed.classList[active ? 'remove' : 'add']('hide');
427
+ s('body').classList[active ? 'add' : 'remove']('main-btn-menu-top-fixed-active');
428
+ };
418
429
  barConfig.buttons.menu.onClick = () => {
419
430
  Modal.Data[idModal][options.mode].width = slideMenuWidth;
420
431
  s(`.btn-menu-${idModal}`).classList.add('hide');
@@ -437,6 +448,7 @@ class Modal {
437
448
  } else {
438
449
  s(`.${idModal}`).style.left = `0px`;
439
450
  }
451
+ syncFixedMenuButton();
440
452
  Responsive.triggerChanged(`slide-menu-${idModal}`);
441
453
  };
442
454
  barConfig.buttons.close.onClick = () => {
@@ -460,11 +472,12 @@ class Modal {
460
472
  } else {
461
473
  s(`.${idModal}`).style.left = `-${originSlideMenuWidth}px`;
462
474
  }
475
+ syncFixedMenuButton();
463
476
  Responsive.triggerChanged(`slide-menu-${idModal}`);
464
477
  };
465
478
  transition += `, width 0.3s`;
466
479
 
467
- setTimeout(() => {
480
+ setTimeout(async () => {
468
481
  setTimeout(btnCloseEvent);
469
482
  append(
470
483
  'body',
@@ -517,6 +530,46 @@ class Modal {
517
530
  Modal.actionBtnCenter();
518
531
  };
519
532
 
533
+ // Fixed top-left hamburger, shown only while the top bar is collapsed
534
+ // (main-body-btn-ui-close hidden). Not needed for 'top-bottom-bar' which
535
+ // keeps its own center action button in the bottom bar.
536
+ if (
537
+ idModal === 'modal-menu' &&
538
+ options.mode !== 'slide-menu-right' &&
539
+ options.barMode !== 'top-bottom-bar'
540
+ ) {
541
+ append(
542
+ 'body',
543
+ html`
544
+ <div
545
+ class="fix main-btn-menu-top-fixed-container hide"
546
+ style="top: 0px; left: 0px; z-index: 10; height: ${originHeightTopBar}px; width: ${originHeightTopBar}px"
547
+ >
548
+ ${await BtnIcon.instance({
549
+ style: `height: 100%`,
550
+ class: `in fll main-btn-menu-top action-bar-box action-btn-center-top-fixed`,
551
+ label: html`<div class="abs center">${barConfig.buttons.menu.label}</div>`,
552
+ })}
553
+ </div>
554
+ <style>
555
+ /* View modals sit at top: 0 while the top bar is collapsed; keep their
556
+ title clear of the fixed hamburger. The padding eases at the same pace
557
+ the views slide so the title moves once, not a jump and a slide back. */
558
+ .title-main-modal {
559
+ transition: padding-left 0.3s;
560
+ }
561
+ body.main-btn-menu-top-fixed-active .title-main-modal {
562
+ padding-left: ${originHeightTopBar}px;
563
+ }
564
+ </style>
565
+ `,
566
+ );
567
+ EventsUI.onClick(`.action-btn-center-top-fixed`, (e) => {
568
+ e.preventDefault();
569
+ Modal.actionBtnCenter();
570
+ });
571
+ }
572
+
520
573
  s(`.main-body-btn-bar-custom`).onclick = () => {
521
574
  if (s(`.main-body-btn-ui-close`).classList.contains('hide')) {
522
575
  s(`.main-body-btn-ui`).click();
@@ -548,6 +601,7 @@ class Modal {
548
601
  options.heightBottomBar = 0;
549
602
  s(`.slide-menu-top-bar`).classList.add('hide');
550
603
  s(`.bottom-bar`).classList.add('hide');
604
+ syncFixedMenuButton();
551
605
  s(`.modal-menu`).style.top = '0px';
552
606
  s(`.main-body-btn-container`).style.top = '50px';
553
607
  s(`.main-body`).style.top = '0px';
@@ -563,6 +617,7 @@ class Modal {
563
617
  s(`.main-body-btn-container`).style.top = `${options.heightTopBar + 50}px`;
564
618
  s(`.slide-menu-top-bar`).classList.remove('hide');
565
619
  s(`.bottom-bar`).classList.remove('hide');
620
+ syncFixedMenuButton();
566
621
  s(`.main-body`).style.top = `${options.heightTopBar}px`;
567
622
  s(`.main-body`).style.height = `${windowGetH() - options.heightTopBar}px`;
568
623
  for (const event of Object.keys(Modal.Data[idModal].onBarUiOpen))
@@ -13,7 +13,7 @@ import { CyberiaQuestService } from '../../services/cyberia-quest/cyberia-quest.
13
13
  import { CyberiaActionService } from '../../services/cyberia-action/cyberia-action.service.js';
14
14
  import { CyberiaDialogueService } from '../../services/cyberia-dialogue/cyberia-dialogue.service.js';
15
15
  import { CyberiaSkillService } from '../../services/cyberia-skill/cyberia-skill.service.js';
16
- import { QUEST_STEPS_TYPES, getDefaultCyberiaItemById, SKILL_LOGIC_IDS } from './SharedDefaultsCyberia.js';
16
+ import { QUEST_STEPS_TYPES, SKILL_LOGIC_IDS } from './SharedDefaultsCyberia.js';
17
17
 
18
18
  const textFilter = (filter) => ({ filterType: 'text', type: 'equals', filter });
19
19
  // DropDown invokes optionData.onClick on selection, so every option (including
@@ -90,8 +90,8 @@ class ActionEngineCyberia {
90
90
  containerClass: 'inl',
91
91
  serviceProvider: async (q) => {
92
92
  const result = await ObjectLayerService.searchItemIds({ q });
93
- if (result.status === 'success' && result.data?.itemIds) {
94
- return result.data.itemIds.map((itemId) => dropdownOption(itemId));
93
+ if (result.status === 'success' && result.data?.items) {
94
+ return result.data.items.map(({ id }) => dropdownOption(id));
95
95
  }
96
96
  return [];
97
97
  },
@@ -139,40 +139,16 @@ class ActionEngineCyberia {
139
139
  if (ActionEngineCyberia.imageCache[itemId]) return;
140
140
  ActionEngineCyberia.imageCache[itemId] = { img: null, loaded: false, error: false };
141
141
 
142
- const loadImage = (type, id) => {
143
- const img = new Image();
144
- img.onload = () => {
145
- ActionEngineCyberia.imageCache[itemId].img = img;
146
- ActionEngineCyberia.imageCache[itemId].loaded = true;
147
- if (onLoad) onLoad();
148
- };
149
- img.onerror = () => {
150
- ActionEngineCyberia.imageCache[itemId].error = true;
151
- };
152
- img.src = `${getProxyPath()}assets/${type}/${id}/08/0.png`;
142
+ const img = new Image();
143
+ img.onload = () => {
144
+ ActionEngineCyberia.imageCache[itemId].img = img;
145
+ ActionEngineCyberia.imageCache[itemId].loaded = true;
146
+ if (onLoad) onLoad();
153
147
  };
154
-
155
- const sharedItem = getDefaultCyberiaItemById(itemId)?.item;
156
- if (sharedItem?.type && sharedItem?.id) {
157
- loadImage(sharedItem.type, sharedItem.id);
158
- return;
159
- }
160
-
161
- ObjectLayerService.get({
162
- limit: 1,
163
- filterModel: { 'data.item.id': { filterType: 'text', type: 'equals', filter: itemId } },
164
- })
165
- .then((res) => {
166
- const doc = res?.data?.data?.[0];
167
- if (!doc || !doc.data?.item?.type || !doc.data?.item?.id) {
168
- ActionEngineCyberia.imageCache[itemId].error = true;
169
- return;
170
- }
171
- loadImage(doc.data.item.type, doc.data.item.id);
172
- })
173
- .catch(() => {
174
- ActionEngineCyberia.imageCache[itemId].error = true;
175
- });
148
+ img.onerror = () => {
149
+ ActionEngineCyberia.imageCache[itemId].error = true;
150
+ };
151
+ img.src = `${getProxyPath()}api/atlas-sprite-sheet/idle-preview/${itemId}`;
176
152
  }
177
153
 
178
154
  static preloadMapObjectLayers(onLoad) {