@ifc-lite/viewer 1.27.0 → 1.28.1
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.
- package/.turbo/turbo-build.log +35 -42
- package/CHANGELOG.md +74 -0
- package/dist/assets/{basketViewActivator-B3CdrLsb.js → basketViewActivator-Ce38DhXd.js} +8 -8
- package/dist/assets/{bcf-QeHK_Aud.js → bcf-Cv_O3JfD.js} +56 -56
- package/dist/assets/{decode-worker-CgM1iNSK.js → decode-worker-Cjign7Zh.js} +1 -1
- package/dist/assets/{deflate-B-d0SYQM.js → deflate-HbyMq59o.js} +1 -1
- package/dist/assets/drawing-2d-DW98umlt.js +257 -0
- package/dist/assets/e57-source-2wI9jkCA.js +1 -0
- package/dist/assets/{exporters-B4LbZFeT.js → exporters-BuD3XRzB.js} +1309 -1153
- package/dist/assets/geometry.worker-TH3fCCoY.js +1 -0
- package/dist/assets/{geotiff-CrVtDRFq.js → geotiff-B2HA8Bwm.js} +10 -10
- package/dist/assets/{ids-DjsGFN10.js → ids-DYUFMd5f.js} +952 -945
- package/dist/assets/{ifc-lite_bg-DsYUIHm3.wasm → ifc-lite_bg-BEA5DLmg.wasm} +0 -0
- package/dist/assets/index-E9wB0zWt.css +1 -0
- package/dist/assets/{index-COYokSKc.js → index-n5O1QJMM.js} +37877 -38126
- package/dist/assets/{index.es-CY202jA3.js → index.es-BKVIpZgL.js} +9 -9
- package/dist/assets/{jpeg-D4wOkf5h.js → jpeg-C7hjKjPX.js} +1 -1
- package/dist/assets/{jspdf.es.min-DIGb9BHN.js → jspdf.es.min-oWlFc42Y.js} +4 -4
- package/dist/assets/lens-C4p1kQ0p.js +1 -0
- package/dist/assets/{lerc-DmW0_tgf.js → lerc-BfIOGhQz.js} +1 -1
- package/dist/assets/{lzw-oWetY-d6.js → lzw-B0jRuuW5.js} +1 -1
- package/dist/assets/{native-bridge-BX8_tHXE.js → native-bridge-DpB-dtEn.js} +6 -3
- package/dist/assets/{packbits-F8Nkp4NY.js → packbits-DVvBTC39.js} +1 -1
- package/dist/assets/parser.worker-BDsWQ6rc.js +182 -0
- package/dist/assets/{pdf-Dsh3HPZB.js → pdf-dVIqI5ac.js} +10 -10
- package/dist/assets/raw-C0ZJYGmN.js +1 -0
- package/dist/assets/{sandbox-BAC3a-eN.js → sandbox-qpJlrNN0.js} +2962 -2554
- package/dist/assets/server-client-DVZ2huNS.js +719 -0
- package/dist/assets/{webimage-BLV1dgmd.js → webimage-B394g0Tw.js} +1 -1
- package/dist/assets/{xlsx-Bc2HTrjC.js → xlsx-D-oHO76J.js} +8 -8
- package/dist/assets/{zstd-C_1HxVrA.js → zstd-Bf38MwV2.js} +1 -1
- package/dist/index.html +9 -9
- package/package.json +24 -23
- package/src/App.tsx +1 -3
- package/src/components/mcp/playground-dispatcher.ts +3 -0
- package/src/components/mcp/playground-files.ts +33 -1
- package/src/components/viewer/BCFPanel.tsx +1 -16
- package/src/components/viewer/ChatPanel.tsx +11 -46
- package/src/components/viewer/CommandPalette.tsx +6 -1
- package/src/components/viewer/ComparePanel.tsx +420 -0
- package/src/components/viewer/HierarchyPanel.tsx +48 -183
- package/src/components/viewer/IDSPanel.tsx +1 -26
- package/src/components/viewer/MainToolbar.tsx +94 -187
- package/src/components/viewer/MobileToolbar.tsx +1 -9
- package/src/components/viewer/PropertiesPanel.tsx +98 -127
- package/src/components/viewer/ScriptPanel.tsx +8 -34
- package/src/components/viewer/Section2DPanel.tsx +32 -1
- package/src/components/viewer/ViewerLayout.tsx +5 -2
- package/src/components/viewer/Viewport.tsx +3 -0
- package/src/components/viewer/ViewportContainer.tsx +24 -42
- package/src/components/viewer/ViewportOverlays.tsx +1 -4
- package/src/components/viewer/hierarchy/HierarchyNode.tsx +3 -3
- package/src/components/viewer/hierarchy/ifc-icons.ts +9 -0
- package/src/components/viewer/hierarchy/treeDataBuilder.ts +87 -0
- package/src/components/viewer/hierarchy/types.ts +1 -0
- package/src/components/viewer/hierarchy/useHierarchyTree.ts +6 -2
- package/src/components/viewer/properties/MaterialTotalsPanel.tsx +283 -0
- package/src/components/viewer/useGeometryStreaming.ts +0 -2
- package/src/hooks/federationLoadGate.test.ts +12 -2
- package/src/hooks/federationLoadGate.ts +9 -2
- package/src/hooks/ingest/federationAlign.ts +488 -0
- package/src/hooks/ingest/viewerModelIngest.ts +3 -212
- package/src/hooks/useCompare.ts +0 -0
- package/src/hooks/useCompareOverlay.ts +119 -0
- package/src/hooks/useDrawingGeneration.ts +234 -14
- package/src/hooks/useIfc.ts +1 -1
- package/src/hooks/useIfcCache.ts +100 -24
- package/src/hooks/useIfcFederation.ts +42 -811
- package/src/hooks/useIfcLoader.ts +349 -1517
- package/src/hooks/useIfcServer.ts +3 -0
- package/src/hooks/useLens.ts +5 -1
- package/src/hooks/useSymbolicAnnotations.ts +70 -38
- package/src/lib/compare/buildFingerprints.ts +173 -0
- package/src/lib/compare/describeChange.ts +0 -0
- package/src/lib/compare/geometricData.test.ts +54 -0
- package/src/lib/compare/geometricData.ts +37 -0
- package/src/lib/compare/overlay.test.ts +99 -0
- package/src/lib/compare/overlay.ts +91 -0
- package/src/lib/geo/cesium-placement.ts +1 -1
- package/src/lib/geo/reproject.ts +4 -1
- package/src/lib/llm/script-edit-ops.ts +23 -0
- package/src/lib/llm/stream-client.ts +8 -1
- package/src/lib/search/result-export.ts +7 -1
- package/src/sdk/adapters/export-adapter.ts +6 -1
- package/src/services/cacheService.ts +9 -25
- package/src/services/desktop-export.ts +2 -59
- package/src/services/file-dialog.ts +8 -142
- package/src/store/constants.ts +23 -0
- package/src/store/globalId.ts +15 -13
- package/src/store/index.ts +19 -6
- package/src/store/slices/cesiumSlice.ts +8 -1
- package/src/store/slices/compareSlice.ts +96 -0
- package/src/store/slices/drawing2DSlice.ts +8 -0
- package/src/store/slices/lensSlice.ts +8 -0
- package/src/store/slices/visibilitySlice.ts +22 -1
- package/src/store/types.ts +1 -71
- package/src/utils/acquireFileBuffer.test.ts +12 -4
- package/src/utils/ifcConfig.ts +0 -12
- package/src/utils/loadingUtils.ts +32 -0
- package/src/utils/spatialHierarchy.test.ts +53 -1
- package/src/utils/spatialHierarchy.ts +42 -2
- package/src/vite-env.d.ts +2 -0
- package/vite.config.ts +6 -3
- package/DESKTOP_CONTRACT_VERSION +0 -1
- package/dist/assets/drawing-2d-C71b8Ugx.js +0 -257
- package/dist/assets/e57-source-CQHxE8n3.js +0 -1
- package/dist/assets/event-B0kAzHa-.js +0 -1
- package/dist/assets/geometry.worker-BdH-E6NB.js +0 -1
- package/dist/assets/index-ajK6D32J.css +0 -1
- package/dist/assets/lens-PYsLu_MA.js +0 -1
- package/dist/assets/parser.worker-D591Zu_-.js +0 -182
- package/dist/assets/raw-D9iw0tmc.js +0 -1
- package/dist/assets/server-client-Cjwnm7il.js +0 -706
- package/dist/assets/tauri-core-stub-D8Fa-u43.js +0 -1
- package/dist/assets/tauri-dialog-stub-r7Wksg7o.js +0 -1
- package/dist/assets/tauri-fs-stub-BdeRC7aK.js +0 -1
- package/src/components/viewer/DesktopEntitlementBanner.tsx +0 -74
- package/src/components/viewer/SettingsPage.tsx +0 -581
- package/src/hooks/ingest/resolveDataStoreOrAbort.test.ts +0 -61
- package/src/hooks/ingest/resolveDataStoreOrAbort.ts +0 -28
- package/src/hooks/ingest/watchedGeometryStream.test.ts +0 -78
- package/src/hooks/ingest/watchedGeometryStream.ts +0 -76
- package/src/lib/desktop/desktopEntitlementEvents.ts +0 -39
- package/src/lib/desktop-entitlement.ts +0 -43
- package/src/lib/desktop-product.ts +0 -130
- package/src/lib/platform.ts +0 -23
- package/src/services/desktop-cache.ts +0 -186
- package/src/services/desktop-harness.ts +0 -196
- package/src/services/desktop-logger.ts +0 -20
- package/src/services/desktop-native-metadata.ts +0 -230
- package/src/services/desktop-panel-actions.ts +0 -43
- package/src/services/desktop-preferences.ts +0 -44
- package/src/services/fs-cache.ts +0 -212
- package/src/services/tauri-core-stub.ts +0 -7
- package/src/services/tauri-dialog-stub.ts +0 -7
- package/src/services/tauri-fs-stub.ts +0 -7
- package/src/services/tauri-modules.d.ts +0 -50
- package/src/store/slices/desktopEntitlementSlice.ts +0 -86
- package/src/utils/desktopModelSnapshot.ts +0 -358
- package/src/utils/nativeSpatialDataStore.ts +0 -277
- package/src-tauri/Cargo.toml +0 -29
- package/src-tauri/build.rs +0 -7
- package/src-tauri/capabilities/default.json +0 -18
- package/src-tauri/icons/128x128.png +0 -0
- package/src-tauri/icons/128x128@2x.png +0 -0
- package/src-tauri/icons/32x32.png +0 -0
- package/src-tauri/icons/Square107x107Logo.png +0 -0
- package/src-tauri/icons/Square142x142Logo.png +0 -0
- package/src-tauri/icons/Square150x150Logo.png +0 -0
- package/src-tauri/icons/Square284x284Logo.png +0 -0
- package/src-tauri/icons/Square30x30Logo.png +0 -0
- package/src-tauri/icons/Square310x310Logo.png +0 -0
- package/src-tauri/icons/Square44x44Logo.png +0 -0
- package/src-tauri/icons/Square71x71Logo.png +0 -0
- package/src-tauri/icons/Square89x89Logo.png +0 -0
- package/src-tauri/icons/StoreLogo.png +0 -0
- package/src-tauri/icons/icon.icns +0 -0
- package/src-tauri/icons/icon.ico +0 -0
- package/src-tauri/icons/icon.png +0 -0
- package/src-tauri/src/lib.rs +0 -21
- package/src-tauri/src/main.rs +0 -10
- package/src-tauri/tauri.conf.json +0 -39
package/src/services/fs-cache.ts
DELETED
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* File system cache service for IFC files (Tauri desktop)
|
|
7
|
-
*
|
|
8
|
-
* Stores parsed IFC data and geometry in app data directory for fast subsequent loads.
|
|
9
|
-
* Uses xxhash64 of the source file as the cache key.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import * as fs from '@tauri-apps/plugin-fs';
|
|
13
|
-
import { appDataDir, join } from '@tauri-apps/api/path';
|
|
14
|
-
|
|
15
|
-
const CACHE_DIR_NAME = 'ifc-lite-cache';
|
|
16
|
-
|
|
17
|
-
let cacheDirPath: string | null = null;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Get the cache directory path, creating it if necessary
|
|
21
|
-
*/
|
|
22
|
-
async function getCacheDir(): Promise<string> {
|
|
23
|
-
if (cacheDirPath) return cacheDirPath;
|
|
24
|
-
|
|
25
|
-
const appDir = await appDataDir();
|
|
26
|
-
cacheDirPath = await join(appDir, CACHE_DIR_NAME);
|
|
27
|
-
|
|
28
|
-
// Ensure cache directory exists (writeFile does NOT auto-create parent directories)
|
|
29
|
-
await fs.mkdir(cacheDirPath, { recursive: true });
|
|
30
|
-
|
|
31
|
-
return cacheDirPath;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Get cache file path for a given key
|
|
36
|
-
*/
|
|
37
|
-
async function getCachePath(key: string): Promise<string> {
|
|
38
|
-
const dir = await getCacheDir();
|
|
39
|
-
return `${dir}/${key}.cache`;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Get metadata file path for a given key
|
|
44
|
-
*/
|
|
45
|
-
async function getMetadataPath(key: string): Promise<string> {
|
|
46
|
-
const dir = await getCacheDir();
|
|
47
|
-
return `${dir}/${key}.meta.json`;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
interface CacheMetadata {
|
|
51
|
-
fileName: string;
|
|
52
|
-
fileSize: number;
|
|
53
|
-
createdAt: number;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Get a cached model by hash key
|
|
58
|
-
*/
|
|
59
|
-
export async function getCached(key: string): Promise<ArrayBuffer | null> {
|
|
60
|
-
try {
|
|
61
|
-
const cachePath = await getCachePath(key);
|
|
62
|
-
|
|
63
|
-
if (!(await fs.exists(cachePath))) {
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const data = await fs.readFile(cachePath);
|
|
68
|
-
// Slice to actual data range - Uint8Array.buffer may contain extra bytes
|
|
69
|
-
const buffer = (data.buffer as ArrayBuffer).slice(data.byteOffset, data.byteOffset + data.byteLength);
|
|
70
|
-
|
|
71
|
-
console.log(`[FS Cache] Cache hit for key ${key} (${(buffer.byteLength / 1024 / 1024).toFixed(2)}MB)`);
|
|
72
|
-
return buffer;
|
|
73
|
-
} catch (err) {
|
|
74
|
-
console.warn('[FS Cache] Cache read failed:', err);
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Store a model in the cache
|
|
81
|
-
*/
|
|
82
|
-
export async function setCached(
|
|
83
|
-
key: string,
|
|
84
|
-
buffer: ArrayBuffer,
|
|
85
|
-
fileName: string,
|
|
86
|
-
fileSize: number
|
|
87
|
-
): Promise<void> {
|
|
88
|
-
try {
|
|
89
|
-
const cachePath = await getCachePath(key);
|
|
90
|
-
const metadataPath = await getMetadataPath(key);
|
|
91
|
-
|
|
92
|
-
const metadata: CacheMetadata = {
|
|
93
|
-
fileName,
|
|
94
|
-
fileSize,
|
|
95
|
-
createdAt: Date.now(),
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
await fs.writeFile(cachePath, new Uint8Array(buffer));
|
|
99
|
-
await fs.writeTextFile(metadataPath, JSON.stringify(metadata, null, 2));
|
|
100
|
-
|
|
101
|
-
console.log(`[FS Cache] Cached ${fileName} (${(fileSize / 1024 / 1024).toFixed(2)}MB)`);
|
|
102
|
-
} catch (err) {
|
|
103
|
-
console.warn('[FS Cache] Cache write failed:', err);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Check if a cache entry exists
|
|
109
|
-
*/
|
|
110
|
-
export async function hasCached(key: string): Promise<boolean> {
|
|
111
|
-
try {
|
|
112
|
-
const cachePath = await getCachePath(key);
|
|
113
|
-
return await fs.exists(cachePath);
|
|
114
|
-
} catch {
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Delete a cache entry
|
|
121
|
-
*/
|
|
122
|
-
export async function deleteCached(key: string): Promise<void> {
|
|
123
|
-
try {
|
|
124
|
-
const cachePath = await getCachePath(key);
|
|
125
|
-
const metadataPath = await getMetadataPath(key);
|
|
126
|
-
|
|
127
|
-
if (await fs.exists(cachePath)) {
|
|
128
|
-
await fs.remove(cachePath);
|
|
129
|
-
}
|
|
130
|
-
if (await fs.exists(metadataPath)) {
|
|
131
|
-
await fs.remove(metadataPath);
|
|
132
|
-
}
|
|
133
|
-
} catch (err) {
|
|
134
|
-
console.warn('[FS Cache] Failed to delete cache entry:', err);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Clear all cached models
|
|
140
|
-
*/
|
|
141
|
-
export async function clearCache(): Promise<void> {
|
|
142
|
-
try {
|
|
143
|
-
const dir = await getCacheDir();
|
|
144
|
-
if (!(await fs.exists(dir))) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const entries = await fs.readDir(dir);
|
|
149
|
-
for (const entry of entries) {
|
|
150
|
-
if (entry.name) {
|
|
151
|
-
await fs.remove(`${dir}/${entry.name}`);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
console.log('[FS Cache] Cache cleared');
|
|
156
|
-
} catch (err) {
|
|
157
|
-
console.warn('[FS Cache] Failed to clear cache:', err);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Get cache statistics
|
|
163
|
-
*/
|
|
164
|
-
export async function getCacheStats(): Promise<{
|
|
165
|
-
entryCount: number;
|
|
166
|
-
totalSize: number;
|
|
167
|
-
entries: Array<{ fileName: string; fileSize: number; createdAt: Date }>;
|
|
168
|
-
}> {
|
|
169
|
-
try {
|
|
170
|
-
const dir = await getCacheDir();
|
|
171
|
-
if (!(await fs.exists(dir))) {
|
|
172
|
-
return { entryCount: 0, totalSize: 0, entries: [] };
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const entries = await fs.readDir(dir);
|
|
176
|
-
const metadataFiles = entries.filter((e) => e.name?.endsWith('.meta.json'));
|
|
177
|
-
|
|
178
|
-
const stats = {
|
|
179
|
-
entryCount: 0,
|
|
180
|
-
totalSize: 0,
|
|
181
|
-
entries: [] as Array<{ fileName: string; fileSize: number; createdAt: Date }>,
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
for (const metaFile of metadataFiles) {
|
|
185
|
-
try {
|
|
186
|
-
const metaPath = `${dir}/${metaFile.name}`;
|
|
187
|
-
const metaContent = await fs.readTextFile(metaPath);
|
|
188
|
-
const metadata: CacheMetadata = JSON.parse(metaContent);
|
|
189
|
-
|
|
190
|
-
const cacheKey = metaFile.name!.replace('.meta.json', '');
|
|
191
|
-
const cachePath = await getCachePath(cacheKey);
|
|
192
|
-
|
|
193
|
-
if (await fs.exists(cachePath)) {
|
|
194
|
-
const cacheData = await fs.readFile(cachePath);
|
|
195
|
-
stats.entryCount++;
|
|
196
|
-
stats.totalSize += cacheData.byteLength;
|
|
197
|
-
stats.entries.push({
|
|
198
|
-
fileName: metadata.fileName,
|
|
199
|
-
fileSize: metadata.fileSize,
|
|
200
|
-
createdAt: new Date(metadata.createdAt),
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
} catch (err) {
|
|
204
|
-
console.warn(`[FS Cache] Failed to read metadata for ${metaFile.name}:`, err);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return stats;
|
|
209
|
-
} catch {
|
|
210
|
-
return { entryCount: 0, totalSize: 0, entries: [] };
|
|
211
|
-
}
|
|
212
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
-
|
|
5
|
-
export async function invoke(): Promise<never> {
|
|
6
|
-
throw new Error('Tauri core API is unavailable in the browser build');
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
-
|
|
5
|
-
export async function open(): Promise<null> {
|
|
6
|
-
return null;
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
-
|
|
5
|
-
export async function readFile(_path: string): Promise<Uint8Array> {
|
|
6
|
-
throw new Error('Tauri file system API is unavailable in the browser benchmark build');
|
|
7
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Ambient type declarations for Tauri-only modules.
|
|
7
|
-
* These packages are only available at runtime in desktop (Tauri) builds
|
|
8
|
-
* and are not installed in the web viewer's node_modules.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
declare module '@tauri-apps/plugin-fs' {
|
|
12
|
-
export function mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;
|
|
13
|
-
export function writeFile(path: string, data: Uint8Array): Promise<void>;
|
|
14
|
-
export function writeTextFile(path: string, data: string): Promise<void>;
|
|
15
|
-
export function readFile(path: string): Promise<Uint8Array>;
|
|
16
|
-
export function readTextFile(path: string): Promise<string>;
|
|
17
|
-
export function exists(path: string): Promise<boolean>;
|
|
18
|
-
export function remove(path: string): Promise<void>;
|
|
19
|
-
export function readDir(path: string): Promise<Array<{ name: string | null }>>;
|
|
20
|
-
export function stat(path: string): Promise<{ size: number; mtime?: number | null }>;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
declare module '@tauri-apps/api/path' {
|
|
24
|
-
export function appDataDir(): Promise<string>;
|
|
25
|
-
export function join(...paths: string[]): Promise<string>;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
declare module '@tauri-apps/api/core' {
|
|
29
|
-
/**
|
|
30
|
-
* Tauri's IPC entry point. Generic by command name.
|
|
31
|
-
*/
|
|
32
|
-
export function invoke<T = unknown>(cmd: string, args?: Record<string, unknown>): Promise<T>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
declare module '@tauri-apps/plugin-dialog' {
|
|
36
|
-
export interface OpenDialogOptions {
|
|
37
|
-
title?: string;
|
|
38
|
-
multiple?: boolean;
|
|
39
|
-
directory?: boolean;
|
|
40
|
-
defaultPath?: string;
|
|
41
|
-
filters?: Array<{ name: string; extensions: string[] }>;
|
|
42
|
-
}
|
|
43
|
-
export interface SaveDialogOptions {
|
|
44
|
-
title?: string;
|
|
45
|
-
defaultPath?: string;
|
|
46
|
-
filters?: Array<{ name: string; extensions: string[] }>;
|
|
47
|
-
}
|
|
48
|
-
export function open(options?: OpenDialogOptions): Promise<string | string[] | null>;
|
|
49
|
-
export function save(options?: SaveDialogOptions): Promise<string | null>;
|
|
50
|
-
}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
-
|
|
5
|
-
import type { StateCreator } from 'zustand';
|
|
6
|
-
import {
|
|
7
|
-
getDefaultDesktopEntitlement,
|
|
8
|
-
type DesktopEntitlement,
|
|
9
|
-
type DesktopEntitlementSource,
|
|
10
|
-
type DesktopEntitlementStatus,
|
|
11
|
-
} from '@/lib/desktop-product';
|
|
12
|
-
|
|
13
|
-
const STORAGE_KEY = 'ifc-lite:desktop-entitlement:v1';
|
|
14
|
-
|
|
15
|
-
function sanitizeTimestamp(value: unknown): number | null {
|
|
16
|
-
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function parseStoredEntitlement(raw: string | null): DesktopEntitlement {
|
|
20
|
-
if (!raw) {
|
|
21
|
-
return getDefaultDesktopEntitlement();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
const parsed = JSON.parse(raw) as Partial<DesktopEntitlement> | null;
|
|
26
|
-
const fallback = getDefaultDesktopEntitlement();
|
|
27
|
-
return {
|
|
28
|
-
tier: parsed?.tier === 'pro' ? 'pro' : 'free',
|
|
29
|
-
status: isEntitlementStatus(parsed?.status) ? parsed.status : fallback.status,
|
|
30
|
-
source: isEntitlementSource(parsed?.source) ? parsed.source : fallback.source,
|
|
31
|
-
userId: typeof parsed?.userId === 'string' ? parsed.userId : null,
|
|
32
|
-
validatedAt: sanitizeTimestamp(parsed?.validatedAt),
|
|
33
|
-
graceUntil: sanitizeTimestamp(parsed?.graceUntil),
|
|
34
|
-
trialEndsAt: sanitizeTimestamp(parsed?.trialEndsAt),
|
|
35
|
-
};
|
|
36
|
-
} catch {
|
|
37
|
-
return getDefaultDesktopEntitlement();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function isEntitlementStatus(value: unknown): value is DesktopEntitlementStatus {
|
|
42
|
-
return value === 'anonymous'
|
|
43
|
-
|| value === 'signed_out'
|
|
44
|
-
|| value === 'active'
|
|
45
|
-
|| value === 'trial'
|
|
46
|
-
|| value === 'expired'
|
|
47
|
-
|| value === 'grace_offline';
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function isEntitlementSource(value: unknown): value is DesktopEntitlementSource {
|
|
51
|
-
return value === 'anonymous' || value === 'clerk_claims' || value === 'cached';
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function persistEntitlement(entitlement: DesktopEntitlement): void {
|
|
55
|
-
try {
|
|
56
|
-
localStorage.setItem(STORAGE_KEY, JSON.stringify(entitlement));
|
|
57
|
-
} catch {
|
|
58
|
-
// ignore storage failures
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface DesktopEntitlementSlice {
|
|
63
|
-
desktopEntitlement: DesktopEntitlement;
|
|
64
|
-
setDesktopEntitlement: (entitlement: DesktopEntitlement) => void;
|
|
65
|
-
clearDesktopEntitlement: () => void;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export const createDesktopEntitlementSlice: StateCreator<
|
|
69
|
-
DesktopEntitlementSlice,
|
|
70
|
-
[],
|
|
71
|
-
[],
|
|
72
|
-
DesktopEntitlementSlice
|
|
73
|
-
> = (set) => ({
|
|
74
|
-
desktopEntitlement: parseStoredEntitlement(typeof localStorage === 'undefined' ? null : localStorage.getItem(STORAGE_KEY)),
|
|
75
|
-
|
|
76
|
-
setDesktopEntitlement: (desktopEntitlement) => {
|
|
77
|
-
persistEntitlement(desktopEntitlement);
|
|
78
|
-
set({ desktopEntitlement });
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
clearDesktopEntitlement: () => {
|
|
82
|
-
const next = getDefaultDesktopEntitlement();
|
|
83
|
-
persistEntitlement(next);
|
|
84
|
-
set({ desktopEntitlement: next });
|
|
85
|
-
},
|
|
86
|
-
});
|