@musnows/scriverse 1.1.0 → 1.1.2
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/dist/ai.js +23 -5
- package/dist/ai.js.map +1 -1
- package/dist/app.js +14 -0
- package/dist/app.js.map +1 -1
- package/dist/public/ai-skill-menu.js +25 -5
- package/dist/public/app.js +325 -101
- package/dist/public/chapter-directory.d.ts +22 -0
- package/dist/public/chapter-directory.js +22 -0
- package/dist/public/index.html +3 -2
- package/dist/public/mobile-app-runtime.js +662 -0
- package/dist/public/mobile-app.css +19 -0
- package/dist/public/mobile-offline-api.js +196 -0
- package/dist/public/mobile-service-worker.js +82 -0
- package/dist/public/mobile-sync-client.js +292 -0
- package/dist/public/mobile-sync-store.js +1004 -0
- package/dist/public/styles.css +6 -3
- package/dist/store.js +15 -8
- package/dist/store.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/public/styles.css
CHANGED
|
@@ -1452,9 +1452,12 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1452
1452
|
.chapter-add-button { flex: none; }
|
|
1453
1453
|
.volume-chapters { display: block; }
|
|
1454
1454
|
.volume-node.is-collapsed .volume-chapters { display: none; }
|
|
1455
|
-
.chapter-node { display: grid; grid-template-columns: minmax(0, 1fr) max-content; gap: 8px; width: calc(100% + 6px); padding: 9px 8px 9px 24px; border: 0; background: transparent; border-radius: 4px; text-align: left; font-size: 12px; }
|
|
1455
|
+
.chapter-node { display: grid; grid-template-columns: minmax(0, 1fr) max-content; gap: 8px; width: calc(100% + 6px); padding: 9px 8px 9px 24px; border: 0; background: transparent; border-radius: 4px; text-align: left; font-size: 12px; position: relative; cursor: pointer; user-select: none; }
|
|
1456
1456
|
.chapter-node:hover, .chapter-node.active { background: var(--row-active); }
|
|
1457
|
-
.chapter-
|
|
1457
|
+
.chapter-drag-handle { position: absolute; inset: 0 auto 0 0; display: grid; place-items: center; width: 24px; color: var(--muted); cursor: grab; opacity: .5; }
|
|
1458
|
+
.chapter-drag-handle svg { width: 12px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; pointer-events: none; }
|
|
1459
|
+
.chapter-node:hover .chapter-drag-handle, .chapter-node:focus-visible .chapter-drag-handle { opacity: 1; }
|
|
1460
|
+
.chapter-node.is-dragging .chapter-drag-handle { cursor: grabbing; }
|
|
1458
1461
|
.chapter-node.is-dragging { opacity: .42; cursor: grabbing; }
|
|
1459
1462
|
.chapter-node.is-drag-over { box-shadow: inset 0 2px 0 var(--accent); }
|
|
1460
1463
|
.chapter-node.is-drag-over.drop-after { box-shadow: inset 0 -2px 0 var(--accent); }
|
|
@@ -1580,7 +1583,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1580
1583
|
.editor-body { display: flex; grid-row: 3; min-height: 0; flex-direction: column; }
|
|
1581
1584
|
.chapter-editor-frame { position: relative; display: flex; flex-direction: column; flex: 1 1 auto; width: 100%; min-height: 0; margin: 0; overflow: hidden; }
|
|
1582
1585
|
.chapter-editor-scroll { position: relative; display: grid; grid-template-columns: 38px minmax(0, 1fr); flex: 1 1 auto; width: 100%; min-height: 0; overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; }
|
|
1583
|
-
.chapter-line-numbers { position: relative; z-index: 2; grid-column: 1; grid-row: 1; min-height: 0; overflow:
|
|
1586
|
+
.chapter-line-numbers { position: relative; z-index: 2; grid-column: 1; grid-row: 1; min-height: 0; overflow: clip; overflow-clip-margin: 12px; border-right: 1px solid var(--line); background: linear-gradient(to right, transparent, rgba(143,132,116,.04)); color: var(--muted); font-family: var(--font-latin), monospace; font-size: clamp(11px, calc(var(--editor-font-size) * .72), 14px); line-height: 1.2; user-select: none; }
|
|
1584
1587
|
#chapter-line-numbers-inner { position: absolute; top: 32px; left: 0; right: 0; }
|
|
1585
1588
|
.chapter-line-number { position: absolute; left: 0; box-sizing: border-box; display: flex; width: 100%; align-items: flex-start; justify-content: center; padding: 0; border: 0; background: transparent; color: inherit; font: inherit; font-variant-numeric: tabular-nums; text-align: center; }
|
|
1586
1589
|
.chapter-line-number-select { position: relative; display: flex; width: 100%; height: 100%; align-items: flex-start; justify-content: center; padding-inline: 3px; border: 0; background: transparent; color: inherit; font: inherit; font-variant-numeric: tabular-nums; cursor: pointer; }
|
package/dist/store.js
CHANGED
|
@@ -2571,25 +2571,32 @@ export class Store {
|
|
|
2571
2571
|
this.assertExpectedRevision("chapter", chapterId, expectedVersionNo, "章节", Number(lockedChapter.versionNo));
|
|
2572
2572
|
const sourceVolumeId = String(lockedChapter.volumeId);
|
|
2573
2573
|
const targetVolumeId = input.volumeId;
|
|
2574
|
-
const
|
|
2574
|
+
const sourceChapters = this.db.all("SELECT id, sort_order FROM chapters WHERE volume_id = ? AND deleted_at IS NULL ORDER BY sort_order, created_at, id", sourceVolumeId);
|
|
2575
|
+
const sourceChapterIds = sourceChapters.map((row) => requiredString(row, "id")).filter((idValue) => idValue !== chapterId);
|
|
2576
|
+
const targetChapters = sourceVolumeId === targetVolumeId
|
|
2577
|
+
? sourceChapters
|
|
2578
|
+
: this.db.all("SELECT id, sort_order FROM chapters WHERE volume_id = ? AND deleted_at IS NULL ORDER BY sort_order, created_at, id", targetVolumeId);
|
|
2579
|
+
const previousSortOrders = new Map([...sourceChapters, ...targetChapters].map((row) => [requiredString(row, "id"), numberValue(row, "sort_order")]));
|
|
2575
2580
|
const targetChapterIds = sourceVolumeId === targetVolumeId
|
|
2576
2581
|
? sourceChapterIds
|
|
2577
|
-
:
|
|
2582
|
+
: targetChapters.map((row) => requiredString(row, "id")).filter((idValue) => idValue !== chapterId);
|
|
2578
2583
|
const targetIndex = Math.min(input.sortOrder, targetChapterIds.length);
|
|
2579
2584
|
targetChapterIds.splice(targetIndex, 0, chapterId);
|
|
2580
2585
|
const timestamp = now();
|
|
2581
|
-
|
|
2586
|
+
const updateSortOrder = (idValue, sortOrder) => {
|
|
2587
|
+
if (idValue === chapterId || previousSortOrders.get(idValue) === sortOrder)
|
|
2588
|
+
return;
|
|
2582
2589
|
this.db.run("UPDATE chapters SET sort_order = ?, updated_at = ? WHERE id = ?", sortOrder, timestamp, idValue);
|
|
2583
|
-
}
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2590
|
+
};
|
|
2591
|
+
if (sourceVolumeId !== targetVolumeId)
|
|
2592
|
+
sourceChapterIds.forEach(updateSortOrder);
|
|
2593
|
+
targetChapterIds.forEach(updateSortOrder);
|
|
2587
2594
|
const versionNo = Number(lockedChapter.versionNo) + 1;
|
|
2588
2595
|
this.db.run(`UPDATE analysis_tasks SET status = 'expired', updated_at = ?
|
|
2589
2596
|
WHERE work_id = ? AND status IN ('pending', 'running', 'completed', 'partial', 'review')
|
|
2590
2597
|
AND json_extract(scope_json, '$.type') = 'volume'
|
|
2591
2598
|
AND json_extract(scope_json, '$.volumeId') IN (?, ?)`, timestamp, String(lockedChapter.workId), sourceVolumeId, targetVolumeId);
|
|
2592
|
-
this.db.run("UPDATE chapters SET version_no = ?, analysis_status = 'expired', updated_at = ? WHERE id = ?", versionNo, timestamp, chapterId);
|
|
2599
|
+
this.db.run("UPDATE chapters SET volume_id = ?, sort_order = ?, version_no = ?, analysis_status = 'expired', updated_at = ? WHERE id = ?", targetVolumeId, targetIndex, versionNo, timestamp, chapterId);
|
|
2593
2600
|
this.syncChapterParagraphSearchVersion(chapterId, versionNo);
|
|
2594
2601
|
this.insertChapterVersionRow({
|
|
2595
2602
|
workId: String(lockedChapter.workId),
|