kingkont 0.20.50 → 0.20.52
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/renderer/cloudProjects.js +91 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kingkont",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.52",
|
|
4
4
|
"description": "KingKont \u00b7 Chatium \u2014 \u043d\u043e\u0434-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0441\u0446\u0435\u043d \u0441 AI-\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 (\u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438/\u0432\u0438\u0434\u0435\u043e/\u0433\u043e\u043b\u043e\u0441/SFX/\u043c\u0443\u0437\u044b\u043a\u0430/\u0442\u0435\u043a\u0441\u0442)",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"bin": {
|
|
@@ -393,6 +393,66 @@
|
|
|
393
393
|
setCloudButtonsVisibility();
|
|
394
394
|
if (typeof window.renderTemplateOverlay === 'function') window.renderTemplateOverlay();
|
|
395
395
|
const bgBoards = Array.isArray(p.manifest?.boards) ? p.manifest.boards : [];
|
|
396
|
+
// Если в местной meta не было cdnByBoard (старая схема — meta
|
|
397
|
+
// сохранена до фичи), либо state.cloudCdnByBoard пустой — строим
|
|
398
|
+
// карту из свежего манифеста и применяем к текущей доске.
|
|
399
|
+
// Иначе картинки в web-view не находятся: state.currentBoard.urls
|
|
400
|
+
// остаётся {} → settings.js hydrate упирается в resolveBoardFile,
|
|
401
|
+
// который в web без локального файла бросает «Файл не найден».
|
|
402
|
+
// (a) Recovery cdnByBoard если в meta его не было.
|
|
403
|
+
const haveCdnMap = state.cloudCdnByBoard
|
|
404
|
+
&& Object.keys(state.cloudCdnByBoard).length > 0;
|
|
405
|
+
if (!haveCdnMap && bgBoards.length) {
|
|
406
|
+
state.cloudCdnByBoard = _buildCdnByBoard(bgBoards);
|
|
407
|
+
_applyCdnUrlsToCurrentBoard();
|
|
408
|
+
try {
|
|
409
|
+
const fresh = { ...meta, cdnByBoard: state.cloudCdnByBoard, syncedAt: Date.now() };
|
|
410
|
+
await writeCloudFile(projectId, '.kingkont-meta.json',
|
|
411
|
+
new TextEncoder().encode(JSON.stringify(fresh, null, 2)));
|
|
412
|
+
} catch {}
|
|
413
|
+
}
|
|
414
|
+
// (b) Recovery scene.json'ов независимо от (a). Старая сессия
|
|
415
|
+
// могла закешировать только часть досок в IDB (юзер не во все
|
|
416
|
+
// сцены кликал) — сайдбар тогда покажет 4 сцены вместо 5.
|
|
417
|
+
// Либо в IDB лежит «стартовый» scene.json на 0 нод. Если
|
|
418
|
+
// local-копия пустее серверной — перезаписываем.
|
|
419
|
+
let wroteAnyScene = false;
|
|
420
|
+
for (const board of bgBoards) {
|
|
421
|
+
if (!board.scene) continue;
|
|
422
|
+
const boardDir = boardKindToDir(board.kind, board.name);
|
|
423
|
+
const scenePath = joinPath(boardDir, 'scene.json');
|
|
424
|
+
let existing = null;
|
|
425
|
+
try {
|
|
426
|
+
existing = window.cloudFs
|
|
427
|
+
? await window.cloudFs.readText(projectId, scenePath).catch(() => null)
|
|
428
|
+
: await window.cloudFsShim?.readTextFile?.(projectId, scenePath).catch(() => null);
|
|
429
|
+
} catch {}
|
|
430
|
+
let needsWrite = !existing;
|
|
431
|
+
if (existing && !needsWrite) {
|
|
432
|
+
try {
|
|
433
|
+
const local = JSON.parse(existing);
|
|
434
|
+
const localN = Array.isArray(local?.nodes) ? local.nodes.length : 0;
|
|
435
|
+
const serverN = Array.isArray(board.scene?.nodes) ? board.scene.nodes.length : 0;
|
|
436
|
+
if (localN < serverN) needsWrite = true;
|
|
437
|
+
} catch { needsWrite = true; }
|
|
438
|
+
}
|
|
439
|
+
if (!needsWrite) continue;
|
|
440
|
+
try {
|
|
441
|
+
await writeCloudFile(projectId, scenePath,
|
|
442
|
+
new TextEncoder().encode(JSON.stringify(board.scene, null, 2)));
|
|
443
|
+
wroteAnyScene = true;
|
|
444
|
+
} catch {}
|
|
445
|
+
}
|
|
446
|
+
if (wroteAnyScene) {
|
|
447
|
+
try {
|
|
448
|
+
if (typeof refreshEpisodes === 'function') await refreshEpisodes();
|
|
449
|
+
if (typeof refreshLocations === 'function') await refreshLocations();
|
|
450
|
+
if (typeof refreshCharacters === 'function') await refreshCharacters();
|
|
451
|
+
} catch {}
|
|
452
|
+
}
|
|
453
|
+
if ((!haveCdnMap || wroteAnyScene) && state.currentBoard && typeof selectBoard === 'function') {
|
|
454
|
+
try { await selectBoard(state.currentBoard); } catch {}
|
|
455
|
+
}
|
|
396
456
|
await _downloadAllTexts(projectId, bgBoards).catch(() => {});
|
|
397
457
|
// Перечитываем тексты ТЕКУЩЕЙ доски (другие — при switchBoard).
|
|
398
458
|
await _refreshCurrentBoardTexts().catch(() => {});
|
|
@@ -451,28 +511,7 @@
|
|
|
451
511
|
// кешируется»). 1024px достаточно и для card-thumbnail и для
|
|
452
512
|
// полноэкранного просмотра. Маленькие thumbs (320x) — отдельной
|
|
453
513
|
// картой не требуются, scene-card сам ресайзит через CSS.
|
|
454
|
-
const cdnByBoard =
|
|
455
|
-
// R2 public bucket `pub-<id>.r2.dev` rate-limited Cloudflare'ом (503 при
|
|
456
|
-
// batch-загрузке из браузера, ~30 одновременных img-fetch'ей). Переписываем
|
|
457
|
-
// на Worker GET endpoint (Worker не лимитирован так агрессивно, +CORS).
|
|
458
|
-
// Старые manifests на чатиуме могут содержать pub-…r2.dev URL'ы — этот
|
|
459
|
-
// rewrite их чинит без серверной миграции.
|
|
460
|
-
const R2_PUB_PREFIX = 'https://pub-cd4114af9f7d44c9bf8c9442bc7dddc2.r2.dev/';
|
|
461
|
-
const R2_WORKER_GET = 'https://kingkont-r2-upload.timur-dd5.workers.dev/get/';
|
|
462
|
-
for (const board of boards) {
|
|
463
|
-
const map = {};
|
|
464
|
-
for (const [relPath, cdnUrlRaw] of Object.entries(board.files || {})) {
|
|
465
|
-
let cdnUrl = cdnUrlRaw;
|
|
466
|
-
if (cdnUrl && cdnUrl.startsWith(R2_PUB_PREFIX)) {
|
|
467
|
-
cdnUrl = R2_WORKER_GET + cdnUrl.slice(R2_PUB_PREFIX.length);
|
|
468
|
-
}
|
|
469
|
-
const thumbUrl = cdnUrl.includes('fs.chatium.ru/get/')
|
|
470
|
-
? cdnUrl.replace('/get/', '/thumbnail/') + '/1024x'
|
|
471
|
-
: cdnUrl;
|
|
472
|
-
map[relPath] = '/api/proxy?url=' + encodeURIComponent(thumbUrl);
|
|
473
|
-
}
|
|
474
|
-
cdnByBoard[board.name] = map;
|
|
475
|
-
}
|
|
514
|
+
const cdnByBoard = _buildCdnByBoard(boards);
|
|
476
515
|
// Skeleton meta + cdnByBoard (для fast cache-hit на reload).
|
|
477
516
|
await writeCloudFile(projectId, '.kingkont-meta.json',
|
|
478
517
|
new TextEncoder().encode(JSON.stringify({
|
|
@@ -634,6 +673,36 @@
|
|
|
634
673
|
if (changed) console.log('[cloudProjects] refreshed', changed, 'text-нод после фоновой загрузки');
|
|
635
674
|
}
|
|
636
675
|
|
|
676
|
+
// Построить CDN-карту {boardName: {relPath: '/api/proxy?url=...'}} из манифеста.
|
|
677
|
+
// Вынесено в helper — используется и в no-cache-ветке openCloudProject, и
|
|
678
|
+
// в фоновом fetch при cache-hit (когда местная meta была сохранена старой
|
|
679
|
+
// версией без cdnByBoard — иначе картинки в web-view не находятся).
|
|
680
|
+
// R2 public bucket `pub-<id>.r2.dev` rate-limited Cloudflare'ом (503 при
|
|
681
|
+
// batch-загрузке из браузера, ~30 одновременных img-fetch'ей). Переписываем
|
|
682
|
+
// на Worker GET endpoint (Worker не лимитирован так агрессивно, +CORS).
|
|
683
|
+
// Старые manifests на чатиуме могут содержать pub-…r2.dev URL'ы — этот
|
|
684
|
+
// rewrite их чинит без серверной миграции.
|
|
685
|
+
function _buildCdnByBoard(boards) {
|
|
686
|
+
const R2_PUB_PREFIX = 'https://pub-cd4114af9f7d44c9bf8c9442bc7dddc2.r2.dev/';
|
|
687
|
+
const R2_WORKER_GET = 'https://kingkont-r2-upload.timur-dd5.workers.dev/get/';
|
|
688
|
+
const cdnByBoard = {};
|
|
689
|
+
for (const board of boards || []) {
|
|
690
|
+
const map = {};
|
|
691
|
+
for (const [relPath, cdnUrlRaw] of Object.entries(board.files || {})) {
|
|
692
|
+
let cdnUrl = cdnUrlRaw;
|
|
693
|
+
if (cdnUrl && cdnUrl.startsWith(R2_PUB_PREFIX)) {
|
|
694
|
+
cdnUrl = R2_WORKER_GET + cdnUrl.slice(R2_PUB_PREFIX.length);
|
|
695
|
+
}
|
|
696
|
+
const thumbUrl = cdnUrl && cdnUrl.includes('fs.chatium.ru/get/')
|
|
697
|
+
? cdnUrl.replace('/get/', '/thumbnail/') + '/1024x'
|
|
698
|
+
: cdnUrl;
|
|
699
|
+
if (thumbUrl) map[relPath] = '/api/proxy?url=' + encodeURIComponent(thumbUrl);
|
|
700
|
+
}
|
|
701
|
+
cdnByBoard[board.name] = map;
|
|
702
|
+
}
|
|
703
|
+
return cdnByBoard;
|
|
704
|
+
}
|
|
705
|
+
|
|
637
706
|
// Подложить CDN-URL'ы под state.currentBoard.urls — рендеру медиа-нод
|
|
638
707
|
// в settings.js достаточно непустого `urls[node.file]`, чтобы не лезть
|
|
639
708
|
// в FS (см. settings.js:405).
|