@preference-sl/pref-viewer 2.10.0-beta.15 → 2.10.0-beta.17
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/package.json +1 -1
- package/src/gltf-storage.js +147 -74
- package/src/index.js +86 -64
package/package.json
CHANGED
package/src/gltf-storage.js
CHANGED
|
@@ -1,137 +1,208 @@
|
|
|
1
|
-
//
|
|
2
|
-
export async function initDb(dbName, storeName) {
|
|
3
|
-
return new Promise((resolve, reject) => {
|
|
4
|
-
const request = indexedDB.open(dbName, 1);
|
|
1
|
+
// wwwroot/js/gltf-storage.js
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
3
|
+
// Public, inspectable namespace
|
|
4
|
+
const PC = (globalThis.PrefConfigurator ??= {});
|
|
5
|
+
PC.version = PC.version ?? "1.0.1"; // bump if your schema changes!!
|
|
6
|
+
PC.db = PC.db ?? null;
|
|
11
7
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
function _getDbOrThrow() {
|
|
9
|
+
const db = PC.db;
|
|
10
|
+
if (!db) throw new Error("Database not initialized. Call initDb(...) first.");
|
|
11
|
+
return db;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// --- internal helpers -------------------------------------------------------
|
|
15
|
+
function _openEnsuringStore(dbName, storeName) {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const open = indexedDB.open(dbName, 5);
|
|
18
|
+
|
|
19
|
+
open.onblocked = () => reject(new Error("Open blocked by another tab or worker"));
|
|
20
|
+
open.onerror = () => reject(open.error);
|
|
21
|
+
open.onsuccess = (e) => {
|
|
22
|
+
resolve(e.target.result);
|
|
23
|
+
}
|
|
24
|
+
open.onupgradeneeded = (ev) => {
|
|
25
|
+
const upgradeDb = ev.target.result;
|
|
26
|
+
const store = upgradeDb.createObjectStore(storeName, { keyPath: 'id' });
|
|
27
|
+
store.createIndex('expirationTimeStamp', 'expirationTimeStamp', { unique: false });
|
|
19
28
|
};
|
|
20
29
|
});
|
|
21
30
|
}
|
|
22
31
|
|
|
32
|
+
// --- public API -------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
// Inicializar IndexedDB y dejar el handle en PrefConfigurator.db (público)
|
|
35
|
+
export async function initDb(dbName, storeName) {
|
|
36
|
+
const db = await _openEnsuringStore(dbName, storeName);
|
|
37
|
+
// Close any previous handle to avoid versionchange blocking
|
|
38
|
+
try { PC.db?.close?.(); } catch { }
|
|
39
|
+
PC.db = db;
|
|
40
|
+
|
|
41
|
+
// If another tab upgrades, close gracefully so next call can re-init
|
|
42
|
+
db.onversionchange = () => {
|
|
43
|
+
try { db.close(); } catch { }
|
|
44
|
+
if (PC.db === db) PC.db = null;
|
|
45
|
+
console.warn("[PrefConfigurator] DB connection closed due to versionchange. Re-run initDb().");
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
23
49
|
// Guardar modelo
|
|
24
50
|
export async function saveModel(modelDataStr, storeName) {
|
|
25
51
|
return new Promise((resolve, reject) => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
52
|
+
let db;
|
|
53
|
+
try { db = _getDbOrThrow(); } catch (e) { reject(e); return; }
|
|
54
|
+
|
|
55
|
+
let modelData;
|
|
56
|
+
try { modelData = JSON.parse(modelDataStr); }
|
|
57
|
+
catch (e) { reject(new Error("saveModel: modelDataStr is not valid JSON")); return; }
|
|
31
58
|
|
|
32
59
|
const dataToStore = {
|
|
33
60
|
...modelData,
|
|
34
61
|
data: modelData.data,
|
|
35
|
-
size: modelData
|
|
36
|
-
timestamp: new Date().toISOString(),
|
|
62
|
+
size: (modelData?.data?.length ?? 0)
|
|
37
63
|
};
|
|
38
64
|
|
|
39
|
-
const
|
|
40
|
-
const store =
|
|
41
|
-
const
|
|
65
|
+
const tx = db.transaction([storeName], "readwrite");
|
|
66
|
+
const store = tx.objectStore(storeName);
|
|
67
|
+
const req = store.put(dataToStore);
|
|
42
68
|
|
|
43
|
-
|
|
44
|
-
|
|
69
|
+
req.onerror = () => reject(req.error);
|
|
70
|
+
req.onsuccess = () => resolve();
|
|
45
71
|
});
|
|
46
72
|
}
|
|
47
73
|
|
|
48
74
|
// Cargar modelo
|
|
49
75
|
export function loadModel(modelId, storeName) {
|
|
50
76
|
return new Promise((resolve, reject) => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const tx = globalThis.gltfDB.transaction([storeName], "readonly");
|
|
77
|
+
let db;
|
|
78
|
+
try { db = _getDbOrThrow(); } catch (e) { reject(e); return; }
|
|
79
|
+
|
|
80
|
+
const tx = db.transaction([storeName], "readonly");
|
|
56
81
|
const store = tx.objectStore(storeName);
|
|
57
82
|
const req = store.get(modelId);
|
|
83
|
+
|
|
58
84
|
req.onerror = () => reject(req.error);
|
|
59
85
|
req.onsuccess = () => resolve(req.result ?? null);
|
|
60
86
|
});
|
|
61
87
|
}
|
|
62
88
|
|
|
89
|
+
// Descargar archivo desde base64
|
|
63
90
|
export function downloadFileFromBytes(fileName, bytesBase64, mimeType) {
|
|
64
91
|
const link = document.createElement("a");
|
|
65
92
|
link.download = fileName;
|
|
66
93
|
link.href = `data:${mimeType};base64,${bytesBase64}`;
|
|
67
94
|
document.body.appendChild(link);
|
|
68
95
|
link.click();
|
|
69
|
-
|
|
96
|
+
link.remove();
|
|
70
97
|
}
|
|
71
98
|
|
|
72
99
|
// Obtener todos los modelos (solo metadata)
|
|
73
100
|
export async function getAllModels(storeName) {
|
|
74
101
|
return new Promise((resolve, reject) => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
102
|
+
let db;
|
|
103
|
+
try { db = _getDbOrThrow(); } catch (e) { reject(e); return; }
|
|
79
104
|
|
|
80
|
-
const
|
|
81
|
-
const store =
|
|
82
|
-
const
|
|
105
|
+
const tx = db.transaction([storeName], "readonly");
|
|
106
|
+
const store = tx.objectStore(storeName);
|
|
107
|
+
const req = store.getAll();
|
|
83
108
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const results =
|
|
109
|
+
req.onerror = () => reject(req.error);
|
|
110
|
+
req.onsuccess = () => {
|
|
111
|
+
const items = Array.isArray(req.result) ? req.result : [];
|
|
112
|
+
const results = items.map(item => ({
|
|
88
113
|
id: item.id,
|
|
89
114
|
metadata: item.metadata,
|
|
90
|
-
|
|
91
|
-
size: item.size
|
|
92
|
-
type: item.type,
|
|
115
|
+
timeStamp: item.timeStamp,
|
|
116
|
+
size: item.size
|
|
93
117
|
}));
|
|
118
|
+
// keep old behavior: return JSON string
|
|
94
119
|
resolve(JSON.stringify(results));
|
|
95
120
|
};
|
|
96
121
|
});
|
|
97
122
|
}
|
|
98
123
|
|
|
99
|
-
// Eliminar modelo
|
|
124
|
+
// Eliminar modelo por id
|
|
100
125
|
export async function deleteModel(modelId, storeName) {
|
|
101
126
|
return new Promise((resolve, reject) => {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
127
|
+
let db;
|
|
128
|
+
try { db = _getDbOrThrow(); } catch (e) { reject(e); return; }
|
|
106
129
|
|
|
107
|
-
const
|
|
108
|
-
const store =
|
|
109
|
-
const
|
|
130
|
+
const tx = db.transaction([storeName], "readwrite");
|
|
131
|
+
const store = tx.objectStore(storeName);
|
|
132
|
+
const req = store.delete(modelId);
|
|
110
133
|
|
|
111
|
-
|
|
112
|
-
|
|
134
|
+
req.onerror = () => reject(req.error);
|
|
135
|
+
req.onsuccess = () => resolve();
|
|
113
136
|
});
|
|
114
137
|
}
|
|
115
138
|
|
|
116
|
-
// Limpiar toda la
|
|
139
|
+
// Limpiar toda la store
|
|
117
140
|
export async function clearAll(storeName) {
|
|
118
141
|
return new Promise((resolve, reject) => {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
142
|
+
let db;
|
|
143
|
+
try { db = _getDbOrThrow(); } catch (e) { reject(e); return; }
|
|
144
|
+
|
|
145
|
+
const tx = db.transaction([storeName], "readwrite");
|
|
146
|
+
const store = tx.objectStore(storeName);
|
|
147
|
+
const req = store.clear();
|
|
148
|
+
|
|
149
|
+
req.onerror = () => reject(req.error);
|
|
150
|
+
req.onsuccess = () => resolve();
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Borrar modelos expirados usando el índice "expirationTimeStamp"
|
|
155
|
+
export async function cleanExpiredModels(storeName) {
|
|
156
|
+
return new Promise((resolve, reject) => {
|
|
157
|
+
let db;
|
|
158
|
+
try { db = _getDbOrThrow(); } catch (e) { reject(e); return; }
|
|
159
|
+
|
|
160
|
+
const tx = db.transaction([storeName], "readwrite");
|
|
161
|
+
const store = tx.objectStore(storeName);
|
|
162
|
+
|
|
163
|
+
const index = store.index("expirationTimeStamp");
|
|
164
|
+
const now = Date.now();
|
|
165
|
+
const range = IDBKeyRange.upperBound(now);
|
|
166
|
+
const cursorRequest = index.openCursor(range);
|
|
167
|
+
|
|
168
|
+
cursorRequest.onerror = () => reject(cursorRequest.error);
|
|
169
|
+
cursorRequest.onsuccess = (event) => {
|
|
170
|
+
const cursor = event.target.result;
|
|
171
|
+
if (cursor) {
|
|
172
|
+
cursor.delete();
|
|
173
|
+
cursor.continue();
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
tx.oncomplete = () => resolve();
|
|
178
|
+
tx.onerror = () => reject(tx.error);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
123
181
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
182
|
+
// Utilidades opcionales y visibles (por si las quieres usar en consola)
|
|
183
|
+
export function closeDb() {
|
|
184
|
+
if (PC.db) {
|
|
185
|
+
try { PC.db.close(); } catch { }
|
|
186
|
+
PC.db = null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
127
189
|
|
|
128
|
-
|
|
129
|
-
|
|
190
|
+
export function deleteDatabase(dbName) {
|
|
191
|
+
return new Promise((resolve, reject) => {
|
|
192
|
+
// Close current handle if points to this DB
|
|
193
|
+
if (PC.db && PC.db.name === dbName) {
|
|
194
|
+
try { PC.db.close(); } catch { }
|
|
195
|
+
PC.db = null;
|
|
196
|
+
}
|
|
197
|
+
const req = indexedDB.deleteDatabase(dbName);
|
|
198
|
+
req.onblocked = () => reject(new Error("Delete blocked by another tab or worker"));
|
|
199
|
+
req.onerror = () => reject(req.error);
|
|
200
|
+
req.onsuccess = () => resolve();
|
|
130
201
|
});
|
|
131
202
|
}
|
|
132
203
|
|
|
204
|
+
// Attach a frozen, public API (no private state)
|
|
133
205
|
(function attachPublicAPI(global) {
|
|
134
|
-
const root = (global.PrefConfigurator ??= {});
|
|
135
206
|
const storage = {
|
|
136
207
|
initDb,
|
|
137
208
|
saveModel,
|
|
@@ -139,10 +210,12 @@ export async function clearAll(storeName) {
|
|
|
139
210
|
getAllModels,
|
|
140
211
|
deleteModel,
|
|
141
212
|
clearAll,
|
|
213
|
+
cleanExpiredModels,
|
|
142
214
|
downloadFileFromBytes,
|
|
215
|
+
// extras
|
|
216
|
+
closeDb,
|
|
217
|
+
deleteDatabase,
|
|
143
218
|
};
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
root.storage = Object.freeze(storage);
|
|
148
|
-
})(globalThis);
|
|
219
|
+
// free to inspect PC.db in devtools
|
|
220
|
+
global.PrefConfigurator.storage = Object.freeze(storage);
|
|
221
|
+
})(globalThis);
|
package/src/index.js
CHANGED
|
@@ -60,7 +60,7 @@ class PrefViewer extends HTMLElement {
|
|
|
60
60
|
storage: null,
|
|
61
61
|
visible: false,
|
|
62
62
|
size: null,
|
|
63
|
-
|
|
63
|
+
timeStamp: null,
|
|
64
64
|
changed: false,
|
|
65
65
|
},
|
|
66
66
|
environment: {
|
|
@@ -70,7 +70,7 @@ class PrefViewer extends HTMLElement {
|
|
|
70
70
|
storage: null,
|
|
71
71
|
visible: false,
|
|
72
72
|
size: null,
|
|
73
|
-
|
|
73
|
+
timeStamp: null,
|
|
74
74
|
changed: false,
|
|
75
75
|
},
|
|
76
76
|
materials: {
|
|
@@ -80,7 +80,7 @@ class PrefViewer extends HTMLElement {
|
|
|
80
80
|
show: true,
|
|
81
81
|
visible: false,
|
|
82
82
|
size: null,
|
|
83
|
-
|
|
83
|
+
timeStamp: null,
|
|
84
84
|
changed: false,
|
|
85
85
|
},
|
|
86
86
|
},
|
|
@@ -228,7 +228,7 @@ class PrefViewer extends HTMLElement {
|
|
|
228
228
|
this.shadowRoot.append(this.#wrapper);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
#setStatusSceneLoading(
|
|
231
|
+
#setStatusSceneLoading() {
|
|
232
232
|
this.loaded = false;
|
|
233
233
|
this.loading = true;
|
|
234
234
|
if (this.hasAttribute("loaded")) {
|
|
@@ -240,14 +240,40 @@ class PrefViewer extends HTMLElement {
|
|
|
240
240
|
bubbles: true,
|
|
241
241
|
cancelable: false,
|
|
242
242
|
composed: true,
|
|
243
|
-
detail: detail,
|
|
244
243
|
})
|
|
245
244
|
);
|
|
246
245
|
}
|
|
247
246
|
|
|
248
|
-
#setStatusSceneLoaded(
|
|
247
|
+
#setStatusSceneLoaded() {
|
|
249
248
|
this.loaded = true;
|
|
250
249
|
this.loading = false;
|
|
250
|
+
|
|
251
|
+
const toLoadDetail = {
|
|
252
|
+
container_model: !!this.#data.containers.model.changed,
|
|
253
|
+
container_environment: !!this.#data.containers.environment.changed,
|
|
254
|
+
container_materials: !!this.#data.containers.materials.changed,
|
|
255
|
+
options_camera: !!this.#data.options.camera.changed,
|
|
256
|
+
options_inneWallMaterial: !!this.#data.options.materials.innerWall.changed,
|
|
257
|
+
options_outerWallMaterial: !!this.#data.options.materials.outerWall.changed,
|
|
258
|
+
options_innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed,
|
|
259
|
+
options_outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed,
|
|
260
|
+
};
|
|
261
|
+
const loadedDetail = {
|
|
262
|
+
container_model: !!this.#data.containers.model.changed?.success,
|
|
263
|
+
container_environment: !!this.#data.containers.environment.changed?.success,
|
|
264
|
+
container_materials: !!this.#data.containers.materials.changed?.success,
|
|
265
|
+
options_camera: !!this.#data.options.camera.changed?.success,
|
|
266
|
+
options_inneWallMaterial: !!this.#data.options.materials.innerWall.changed?.success,
|
|
267
|
+
options_outerWallMaterial: !!this.#data.options.materials.outerWall.changed?.success,
|
|
268
|
+
options_innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed?.success,
|
|
269
|
+
options_outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed?.success,
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const detail = {
|
|
273
|
+
tried: toLoadDetail,
|
|
274
|
+
success: loadedDetail,
|
|
275
|
+
};
|
|
276
|
+
|
|
251
277
|
if (this.hasAttribute("loading")) {
|
|
252
278
|
this.removeAttribute("loading");
|
|
253
279
|
}
|
|
@@ -262,18 +288,36 @@ class PrefViewer extends HTMLElement {
|
|
|
262
288
|
);
|
|
263
289
|
}
|
|
264
290
|
|
|
265
|
-
#setStatusOptionsLoading(
|
|
291
|
+
#setStatusOptionsLoading() {
|
|
266
292
|
this.dispatchEvent(
|
|
267
293
|
new CustomEvent("options-loading", {
|
|
268
294
|
bubbles: true,
|
|
269
295
|
cancelable: false,
|
|
270
296
|
composed: true,
|
|
271
|
-
detail: detail,
|
|
272
297
|
})
|
|
273
298
|
);
|
|
274
299
|
}
|
|
275
300
|
|
|
276
|
-
#setStatusOptionsLoaded(
|
|
301
|
+
#setStatusOptionsLoaded() {
|
|
302
|
+
|
|
303
|
+
const toLoadDetail = {
|
|
304
|
+
inneWallMaterial: !!this.#data.options.materials.innerWall.changed,
|
|
305
|
+
outerWallMaterial: !!this.#data.options.materials.outerWall.changed,
|
|
306
|
+
innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed,
|
|
307
|
+
outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed,
|
|
308
|
+
};
|
|
309
|
+
const loadedDetail = {
|
|
310
|
+
inneWallMaterial: !!this.#data.options.materials.innerWall.changed?.success,
|
|
311
|
+
outerWallMaterial: !!this.#data.options.materials.outerWall.changed?.success,
|
|
312
|
+
innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed?.success,
|
|
313
|
+
_outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed?.success,
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
const detail = {
|
|
317
|
+
tried: toLoadDetail,
|
|
318
|
+
success: loadedDetail,
|
|
319
|
+
};
|
|
320
|
+
|
|
277
321
|
this.dispatchEvent(
|
|
278
322
|
new CustomEvent("options-loaded", {
|
|
279
323
|
bubbles: true,
|
|
@@ -310,10 +354,14 @@ class PrefViewer extends HTMLElement {
|
|
|
310
354
|
return someChanged;
|
|
311
355
|
}
|
|
312
356
|
|
|
313
|
-
#storeChangedFlagsForContainer(container) {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
357
|
+
#storeChangedFlagsForContainer(container, success) {
|
|
358
|
+
if (success) {
|
|
359
|
+
container.timeStamp = container.changed.timeStamp;
|
|
360
|
+
container.size = container.changed.size;
|
|
361
|
+
} else {
|
|
362
|
+
container.source = container.changed.source;
|
|
363
|
+
}
|
|
364
|
+
container.changed.success = success;
|
|
317
365
|
}
|
|
318
366
|
|
|
319
367
|
#resetChangedFlags() {
|
|
@@ -459,8 +507,8 @@ class PrefViewer extends HTMLElement {
|
|
|
459
507
|
xhr.onload = () => {
|
|
460
508
|
if (xhr.status === 200) {
|
|
461
509
|
const size = parseInt(xhr.getResponseHeader("Content-Length"));
|
|
462
|
-
const
|
|
463
|
-
resolve([size,
|
|
510
|
+
const timeStamp = new Date(xhr.getResponseHeader("Last-Modified")).toISOString();
|
|
511
|
+
resolve([size, timeStamp]);
|
|
464
512
|
} else {
|
|
465
513
|
resolve([0, null]);
|
|
466
514
|
}
|
|
@@ -530,10 +578,10 @@ class PrefViewer extends HTMLElement {
|
|
|
530
578
|
}
|
|
531
579
|
|
|
532
580
|
const containers = [];
|
|
533
|
-
if (this.#data.containers.model.assetContainer && (this.#data.containers.model.changed || optionMaterial.changed)) {
|
|
581
|
+
if (this.#data.containers.model.assetContainer && (this.#data.containers.model.changed || this.#data.containers.materials.changed || optionMaterial.changed)) {
|
|
534
582
|
containers.push(this.#data.containers.model.assetContainer);
|
|
535
583
|
}
|
|
536
|
-
if (this.#data.containers.environment.assetContainer && (this.#data.containers.environment.changed || optionMaterial.changed)) {
|
|
584
|
+
if (this.#data.containers.environment.assetContainer && (this.#data.containers.environment.changed || this.#data.containers.materials.changed || optionMaterial.changed)) {
|
|
537
585
|
containers.push(this.#data.containers.environment.assetContainer);
|
|
538
586
|
}
|
|
539
587
|
if (containers.length === 0) {
|
|
@@ -635,10 +683,10 @@ class PrefViewer extends HTMLElement {
|
|
|
635
683
|
await this.#initStorage(storage.db, storage.table);
|
|
636
684
|
const object = await loadModel(storage.id, storage.table);
|
|
637
685
|
source = object.data;
|
|
638
|
-
if (object.
|
|
686
|
+
if (object.timeStamp === container.timeStamp) {
|
|
639
687
|
return false;
|
|
640
688
|
} else {
|
|
641
|
-
container.changed
|
|
689
|
+
Object.assign(container.changed, { timeStamp: object.timeStamp, size: object.size, success: false });
|
|
642
690
|
}
|
|
643
691
|
}
|
|
644
692
|
|
|
@@ -654,20 +702,20 @@ class PrefViewer extends HTMLElement {
|
|
|
654
702
|
type: blob.type,
|
|
655
703
|
});
|
|
656
704
|
if (!container.changed) {
|
|
657
|
-
if (container.
|
|
705
|
+
if (container.timeStamp === null && container.size === size) {
|
|
658
706
|
return false;
|
|
659
707
|
} else {
|
|
660
|
-
container.changed
|
|
708
|
+
Object.assign(container.changed, { timeStamp: null, size: size, success: false });
|
|
661
709
|
}
|
|
662
710
|
}
|
|
663
711
|
} else {
|
|
664
712
|
const extMatch = source.match(/\.(gltf|glb)(\?|#|$)/i);
|
|
665
713
|
extension = extMatch ? `.${extMatch[1].toLowerCase()}` : ".gltf";
|
|
666
714
|
const [fileSize, fileTimestamp ] = await this.#getServerFileDataHeader(source);
|
|
667
|
-
if (container.size === fileSize && container.
|
|
715
|
+
if (container.size === fileSize && container.timeStamp === fileTimestamp) {
|
|
668
716
|
return false;
|
|
669
717
|
} else {
|
|
670
|
-
container.changed
|
|
718
|
+
Object.assign(container.changed, { timeStamp: fileTimestamp, size: fileSize, success: false });
|
|
671
719
|
}
|
|
672
720
|
}
|
|
673
721
|
|
|
@@ -712,42 +760,31 @@ class PrefViewer extends HTMLElement {
|
|
|
712
760
|
|
|
713
761
|
if (modelContainer.status === "fulfilled" && modelContainer.value) {
|
|
714
762
|
this.#replaceContainer(this.#data.containers.model, modelContainer.value);
|
|
715
|
-
this.#storeChangedFlagsForContainer(this.#data.containers.model);
|
|
763
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.model, true);
|
|
716
764
|
} else {
|
|
717
765
|
this.#data.containers.model.show ? this.#addContainer(this.#data.containers.model) : this.#removeContainer(this.#data.containers.model);
|
|
766
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.model, false);
|
|
718
767
|
}
|
|
719
768
|
|
|
720
769
|
if (environmentContainer.status === "fulfilled" && environmentContainer.value) {
|
|
721
770
|
this.#replaceContainer(this.#data.containers.environment, environmentContainer.value);
|
|
722
|
-
this.#storeChangedFlagsForContainer(this.#data.containers.environment);
|
|
771
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.environment, true);
|
|
723
772
|
} else {
|
|
724
773
|
this.#data.containers.environment.show ? this.#addContainer(this.#data.containers.environment) : this.#removeContainer(this.#data.containers.environment);
|
|
774
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.environment, false);
|
|
725
775
|
}
|
|
726
776
|
|
|
727
777
|
if (materialsContainer.status === "fulfilled" && materialsContainer.value) {
|
|
728
778
|
this.#replaceContainer(this.#data.containers.materials, materialsContainer.value);
|
|
729
|
-
this.#storeChangedFlagsForContainer(this.#data.containers.materials);
|
|
779
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.materials, true);
|
|
780
|
+
} else {
|
|
781
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.materials, false);
|
|
730
782
|
}
|
|
731
783
|
|
|
732
784
|
this.#setOptionsMaterials();
|
|
733
785
|
this.#setOptionsCamera();
|
|
734
786
|
this.#setVisibilityOfWallAndFloorInModel();
|
|
735
|
-
|
|
736
|
-
const loadedDetail = {
|
|
737
|
-
model: !!this.#data.containers.model.changed?.success,
|
|
738
|
-
environment: !!this.#data.containers.environment.changed?.success,
|
|
739
|
-
materials: !!this.#data.containers.materials.changed?.success,
|
|
740
|
-
options: {
|
|
741
|
-
camera: !!this.#data.options.camera.changed?.success,
|
|
742
|
-
inneWallMaterial: !!this.#data.options.materials.innerWall.changed?.success,
|
|
743
|
-
outerWallMaterial: !!this.#data.options.materials.outerWall.changed?.success,
|
|
744
|
-
innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed?.success,
|
|
745
|
-
outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed?.success,
|
|
746
|
-
},
|
|
747
|
-
};
|
|
748
|
-
|
|
749
|
-
this.#setStatusSceneLoaded(loadedDetail);
|
|
750
|
-
|
|
787
|
+
this.#setStatusSceneLoaded();
|
|
751
788
|
this.#resetChangedFlags();
|
|
752
789
|
})
|
|
753
790
|
.catch((error) => {
|
|
@@ -772,10 +809,13 @@ class PrefViewer extends HTMLElement {
|
|
|
772
809
|
}
|
|
773
810
|
|
|
774
811
|
// Containers
|
|
812
|
+
this.#data.containers.model.changed = { storage: this.#data.containers.model.storage || null };
|
|
775
813
|
this.#data.containers.model.storage = config.model?.storage || null;
|
|
776
814
|
this.#data.containers.model.show = config.model?.visible !== undefined ? config.model.visible : this.#data.containers.model.show;
|
|
815
|
+
this.#data.containers.environment.changed = { storage: this.#data.containers.environment.storage || null };
|
|
777
816
|
this.#data.containers.environment.storage = config.scene?.storage || null;
|
|
778
817
|
this.#data.containers.environment.show = config.scene?.visible !== undefined ? config.scene.visible : this.#data.containers.environment.show;
|
|
818
|
+
this.#data.containers.materials.changed = { storage: this.#data.containers.materials.storage || null };
|
|
779
819
|
this.#data.containers.materials.storage = config.materials?.storage || null;
|
|
780
820
|
|
|
781
821
|
// Options
|
|
@@ -792,35 +832,17 @@ class PrefViewer extends HTMLElement {
|
|
|
792
832
|
return false;
|
|
793
833
|
}
|
|
794
834
|
|
|
795
|
-
|
|
796
|
-
const materialsChanged = this.#checkMaterialsChanged(options);
|
|
797
|
-
|
|
798
|
-
const loadingDetail = {
|
|
799
|
-
camera: !!this.#data.options.camera.changed,
|
|
800
|
-
inneWallMaterial: !!this.#data.options.materials.innerWall.changed,
|
|
801
|
-
outerWallMaterial: !!this.#data.options.materials.outerWall.changed,
|
|
802
|
-
innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed,
|
|
803
|
-
outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed,
|
|
804
|
-
};
|
|
805
|
-
this.#setStatusOptionsLoading(loadingDetail);
|
|
835
|
+
this.#setStatusOptionsLoading();
|
|
806
836
|
|
|
807
837
|
let someSetted = false;
|
|
808
|
-
if (
|
|
838
|
+
if (this.#checkCameraChanged(options)) {
|
|
809
839
|
someSetted = someSetted || this.#setOptionsCamera();
|
|
810
840
|
}
|
|
811
|
-
if (
|
|
841
|
+
if (this.#checkMaterialsChanged(options)) {
|
|
812
842
|
someSetted = someSetted || this.#setOptionsMaterials();
|
|
813
843
|
}
|
|
814
844
|
|
|
815
|
-
|
|
816
|
-
camera: !!this.#data.options.camera.changed?.success,
|
|
817
|
-
inneWallMaterial: !!this.#data.options.materials.innerWall.changed?.success,
|
|
818
|
-
outerWallMaterial: !!this.#data.options.materials.outerWall.changed?.success,
|
|
819
|
-
innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed?.success,
|
|
820
|
-
outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed?.success,
|
|
821
|
-
};
|
|
822
|
-
this.#setStatusOptionsLoaded(loadedDetail);
|
|
823
|
-
|
|
845
|
+
this.#setStatusOptionsLoaded();
|
|
824
846
|
this.#resetChangedFlags();
|
|
825
847
|
|
|
826
848
|
return someSetted;
|