@tak-ps/cloudtak 12.128.0 → 12.130.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.
@@ -1,7 +1,13 @@
1
1
  import Dexie, { type EntityTable } from 'dexie';
2
2
  import type { Feature, GroupChannel, Mission, MissionRole, MissionChange, MissionLog, Contact, Server } from '../types.ts';
3
3
  export interface DBIcon {
4
+ /** Maplibre image id, e.g. "<iconsetUid>:<icon-path-without-extension>" */
4
5
  name: string;
6
+ iconset: string;
7
+ path: string;
8
+ type2525b: string | null;
9
+ updated: string;
10
+ data: Blob;
5
11
  }
6
12
  export interface DBFeature {
7
13
  id: string;
@@ -164,9 +170,19 @@ export interface DBCache {
164
170
  key: string;
165
171
  updated: number;
166
172
  }
173
+ export interface DBSprite {
174
+ /** Sprite id, e.g. 'default' */
175
+ id: string;
176
+ updated: number;
177
+ /** MapLibre sprite layout JSON */
178
+ json: Record<string, unknown>;
179
+ /** Spritesheet PNG */
180
+ image: Blob;
181
+ }
167
182
  export type DatabaseType = Dexie & {
168
183
  icon: EntityTable<DBIcon, 'name'>;
169
184
  iconset: EntityTable<DBIconset, 'uid'>;
185
+ sprite: EntityTable<DBSprite, 'id'>;
170
186
  group: EntityTable<GroupChannel, 'name'>;
171
187
  video: EntityTable<DBVideo, 'id'>;
172
188
  filter: EntityTable<DBFilter, 'id'>;
@@ -1,4 +1,39 @@
1
+ import { type DBIcon } from './database.ts';
2
+ export interface IconHydrateResult {
3
+ /** Iconsets that were added or refreshed during the diff. */
4
+ changed: string[];
5
+ /** Iconsets that were removed locally because they no longer exist remotely. */
6
+ removed: string[];
7
+ /** True when the diff was skipped because the local cache was fresh. */
8
+ skipped: boolean;
9
+ }
1
10
  export default class Icon {
2
11
  static has(icon: string): Promise<boolean>;
3
- static populate(icons: string[]): Promise<void>;
12
+ static get(icon: string): Promise<DBIcon | undefined>;
13
+ /**
14
+ * Diff the server iconset list against Dexie and refetch icons for any
15
+ * iconsets that are new or whose `version`/`updated` differs.
16
+ *
17
+ * Behaviour:
18
+ * - When Dexie already has data and was refreshed recently the call
19
+ * returns immediately (`skipped: true`) and the diff runs in the
20
+ * background; the next call will see the updated cache marker.
21
+ * - When `force` is true the diff always runs inline.
22
+ */
23
+ static hydrate(opts: {
24
+ token: string;
25
+ force?: boolean;
26
+ }): Promise<IconHydrateResult>;
27
+ /**
28
+ * Ensure a single iconset is present in Dexie. Returns true if Dexie was
29
+ * actually updated so the caller can purge stale map images.
30
+ */
31
+ static addIconset(uid: string, opts: {
32
+ token: string;
33
+ }): Promise<boolean>;
34
+ /**
35
+ * Remove an iconset and all of its icons from Dexie. Returns true when
36
+ * something was actually removed.
37
+ */
38
+ static removeIconset(uid: string): Promise<boolean>;
4
39
  }
@@ -1,3 +1,12 @@
1
1
  export declare function getCurrentEntryBuildId(): string;
2
2
  export declare function getPageServiceWorkerBuildId(): string | null;
3
+ /**
4
+ * Called by the update banner in App.vue immediately before it posts
5
+ * `SKIP_WAITING` to the waiting worker. Sets a per-tab flag so that when
6
+ * `controllerchange` fires we know *this* tab asked for the reload and
7
+ * it is safe to auto-refresh. Other tabs on the same origin observe the
8
+ * same `controllerchange` but will show their own update prompt instead
9
+ * of silently reloading (which would lose unsaved state).
10
+ */
11
+ export declare function markUpdateRequestedByThisTab(): void;
3
12
  export declare function initServiceWorker(version: string): void;
@@ -12,9 +12,9 @@ type __VLS_ModelProps = {
12
12
  'editing': EditingBasemap;
13
13
  };
14
14
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
15
- declare var __VLS_77: {};
15
+ declare var __VLS_96: {};
16
16
  type __VLS_Slots = {} & {
17
- advanced?: (props: typeof __VLS_77) => any;
17
+ advanced?: (props: typeof __VLS_96) => any;
18
18
  };
19
19
  declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
20
20
  "change-type": () => any;
@@ -1,24 +1,68 @@
1
1
  import type { Map as MapLibreMap } from 'maplibre-gl';
2
+ import type * as Comlink from 'comlink';
3
+ import type Atlas from '../../workers/atlas.ts';
2
4
  import { type DBIconset } from '../../base/database.ts';
3
5
  export default class IconManager {
4
6
  private cache;
5
7
  private map;
8
+ private worker;
6
9
  private loggedMissingImageIds;
7
10
  private loggedErrors;
8
- constructor(map: MapLibreMap);
11
+ private inflightImage;
12
+ private fallbackBitmap;
13
+ constructor(map: MapLibreMap, worker: Comlink.Remote<Atlas>);
9
14
  private logWarnOnce;
10
15
  private logErrorOnce;
11
16
  static from(uid: string): Promise<DBIconset | undefined>;
12
- addIconset(uid: string): Promise<void>;
13
- removeIconset(uid: string): Promise<void>;
14
- static sprites(): Promise<Array<{
17
+ /**
18
+ * MapLibre style sprite descriptor. The custom iconset spritesheets are no
19
+ * longer loaded here; icons are served on demand from Dexie via
20
+ * `onStyleImageMissing`. Only the small built-in `default` sprite is loaded
21
+ * up-front because it provides the CoT-type fallbacks.
22
+ *
23
+ * The default sprite itself is also served from the Dexie cache via the
24
+ * `cloudtak-sprite://` protocol (see `registerSpriteProtocol`) so it
25
+ * survives offline reloads instead of re-downloading on every page load.
26
+ */
27
+ static defaultSprite(): Array<{
15
28
  id: string;
16
29
  url: string;
17
- }>>;
18
- updateImages(): Promise<void>;
30
+ }>;
31
+ /**
32
+ * Register the global MapLibre protocol that resolves
33
+ * `cloudtak-sprite://<id>(@2x)?.(json|png)` requests against the Dexie
34
+ * `sprite` table, falling back to the API and persisting the response so
35
+ * subsequent loads are served from disk.
36
+ */
37
+ static registerSpriteProtocol(): void;
38
+ /**
39
+ * Hydrate the local Dexie icon cache from the API.
40
+ *
41
+ * The actual network IO and base64 -> Blob decoding runs inside the Atlas
42
+ * worker (see `AtlasIcons.hydrate`); this method only handles main-thread
43
+ * concerns like purging stale MapLibre images.
44
+ */
45
+ hydrate(opts?: {
46
+ force?: boolean;
47
+ }): Promise<void>;
48
+ /**
49
+ * Ensure a single iconset is present in Dexie. Used by overlays that
50
+ * reference a specific iconset so it is available even if the user-wide
51
+ * hydrate hasn't completed yet.
52
+ */
53
+ addIconset(uid: string): Promise<void>;
54
+ removeIconset(uid: string): Promise<void>;
55
+ private applyHydrateResult;
56
+ private purgeMapImagesForIconset;
19
57
  onStyleImageMissing(e: {
20
58
  id: string;
21
59
  }): Promise<void>;
60
+ /**
61
+ * Resolve an `<iconsetUid>:<path>` image id from Dexie and register it with
62
+ * MapLibre. Falls back to a generic point icon when the icon isn't cached.
63
+ */
64
+ private loadIconsetImage;
65
+ private getFallbackBitmap;
22
66
  /**
23
67
  * Get or create a colored version of an icon
24
68
  */
@@ -0,0 +1,12 @@
1
+ import { type IconHydrateResult } from '../base/icon.ts';
2
+ import type Atlas from './atlas.ts';
3
+ export type { IconHydrateResult };
4
+ export default class AtlasIcons {
5
+ atlas: Atlas;
6
+ constructor(atlas: Atlas);
7
+ hydrate(opts?: {
8
+ force?: boolean;
9
+ }): Promise<IconHydrateResult>;
10
+ addIconset(uid: string): Promise<boolean>;
11
+ removeIconset(uid: string): Promise<boolean>;
12
+ }
@@ -3,6 +3,7 @@ import * as Comlink from 'comlink';
3
3
  import AtlasProfile from './atlas-profile.ts';
4
4
  import AtlasDatabase from './atlas-database.ts';
5
5
  import AtlasConnection from './atlas-connection.ts';
6
+ import AtlasIcons from './atlas-icons.ts';
6
7
  export default class Atlas {
7
8
  channel: BroadcastChannel;
8
9
  token: string;
@@ -11,6 +12,7 @@ export default class Atlas {
11
12
  db: AtlasDatabase & Comlink.ProxyMarked;
12
13
  conn: AtlasConnection & Comlink.ProxyMarked;
13
14
  profile: AtlasProfile & Comlink.ProxyMarked;
15
+ icons: AtlasIcons & Comlink.ProxyMarked;
14
16
  constructor();
15
17
  postMessage(msg: WorkerMessage): Promise<void>;
16
18
  init(authToken: string): Promise<void>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tak-ps/cloudtak",
3
3
  "type": "module",
4
- "version": "12.128.0",
4
+ "version": "12.130.0",
5
5
  "types": "dist/types/plugin.d.ts",
6
6
  "files": [
7
7
  "dist/types"
@@ -65,7 +65,7 @@
65
65
  "hls.js": "^1.6.5",
66
66
  "imask": "^6.0.0",
67
67
  "jsonata": "^2.0.4",
68
- "maplibre-gl": "5.23.0",
68
+ "maplibre-gl": "5.24.0",
69
69
  "milsymbol": "^3.0.2",
70
70
  "moment": "^2.29.3",
71
71
  "openapi-fetch": "^0.17.0",
@@ -112,4 +112,4 @@
112
112
  "> 1%",
113
113
  "last 2 versions"
114
114
  ]
115
- }
115
+ }