scenri 0.11.1 → 0.13.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.
- package/CHANGELOG.md +49 -0
- package/dist/{chunk-K6IELFL3.js → chunk-MHTA6O3A.js} +3 -3
- package/dist/{cli-GMRPOISO.js → cli-4A3QWRSC.js} +3 -3
- package/dist/index.js +2 -2
- package/dist/serve.js +168 -25
- package/dist/{src-TC4UQ7H6.js → src-INKSTJNC.js} +3 -3
- package/package.json +1 -1
- package/studio-dist/assets/first-shot-square-hTczF9bl.webp +0 -0
- package/studio-dist/assets/first-shot-wide-BSpJwjNx.webp +0 -0
- package/studio-dist/assets/{index-BWeypLhE.css → index-BjmJCeT_.css} +1 -1
- package/studio-dist/assets/index-D8pLsQ5q.js +107 -0
- package/studio-dist/assets/presenter-square-BpqHv8Aq.webp +0 -0
- package/studio-dist/assets/presenter-wide-ecc4y7eJ.webp +0 -0
- package/studio-dist/assets/product-square-DPR77tr0.webp +0 -0
- package/studio-dist/assets/product-wide-DLSsO8IK.webp +0 -0
- package/studio-dist/assets/refine-square-CietHTPe.webp +0 -0
- package/studio-dist/assets/refine-wide-BM5sVq6w.webp +0 -0
- package/studio-dist/assets/reuse-square-CMLhjEwt.webp +0 -0
- package/studio-dist/assets/reuse-wide-DbbTeKsL.webp +0 -0
- package/studio-dist/assets/scene-square-CQBwEfXy.webp +0 -0
- package/studio-dist/assets/scene-wide-CJ9ENIrh.webp +0 -0
- package/studio-dist/index.html +2 -2
- package/studio-dist/assets/index-Dtkr2AoI.js +0 -107
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.13.0](https://github.com/tonygorb/Scenri/compare/v0.12.0...v0.13.0) (2026-09-21)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **studio:** rebuild transient alerts as a quiet toast stack ([7b44141](https://github.com/tonygorb/Scenri/commit/7b44141b57cc6748942d97bc6acc27a022260207))
|
|
9
|
+
* **studio:** turn first-use on, with a tutor that can go back ([df6b799](https://github.com/tonygorb/Scenri/commit/df6b799708d65cf31130233dabe2fd0ee1095a28))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* **cli:** an install that has made a shot is not offered the first-use welcome ([4dae292](https://github.com/tonygorb/Scenri/commit/4dae292f3e833180448b2310a81573b641408bcc))
|
|
15
|
+
* **create:** keep the feed still when a shot archives or the rail toggles ([b3276cd](https://github.com/tonygorb/Scenri/commit/b3276cd1f68315455e8b29d7dfdf13c768a0438a))
|
|
16
|
+
* **studio:** a lesson on its first step has not begun, and Learn cannot take the app down ([cf0540b](https://github.com/tonygorb/Scenri/commit/cf0540b1ecd1e8fbdde2e3d203538f9e13f46d8c))
|
|
17
|
+
* **studio:** a lesson owns its progress, and only the screen is shared ([8c58bdb](https://github.com/tonygorb/Scenri/commit/8c58bdbc06124d2f9fda0775a41f84fa156e10ea))
|
|
18
|
+
* **studio:** a library lesson keeps its button in sight on narrow screens ([93869f4](https://github.com/tonygorb/Scenri/commit/93869f4f1f1fa8791c15ff893ef8ac536deda721))
|
|
19
|
+
* **studio:** a step scrolled out of sight is not gone ([49ceccb](https://github.com/tonygorb/Scenri/commit/49ceccb8d7dc41daf8327ecefb8353f98ed94e70))
|
|
20
|
+
* **studio:** alerts stand above a docked composer instead of over its buttons ([b6756c7](https://github.com/tonygorb/Scenri/commit/b6756c79c63419ca2ed146fc2e3c6d868eeb6f79))
|
|
21
|
+
* **studio:** Learn gives the keyboard back to whichever control opened it ([e9c5945](https://github.com/tonygorb/Scenri/commit/e9c5945d60e6ceb55704da1130fe23a988c6044f))
|
|
22
|
+
* **studio:** no empty alert on every page, and a held toast stays held ([3305f75](https://github.com/tonygorb/Scenri/commit/3305f7542fb38f604c9b4087c59aa7cfe0d4cf6b))
|
|
23
|
+
* **studio:** refining teaches how to find a shot, instead of picking one for you ([228938f](https://github.com/tonygorb/Scenri/commit/228938f2440e17b48d9bab836e7c4aeeb0a74cef))
|
|
24
|
+
|
|
25
|
+
## [0.12.0](https://github.com/tonygorb/Scenri/compare/v0.11.1...v0.12.0) (2026-09-20)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Features
|
|
29
|
+
|
|
30
|
+
* archive a selection, and make the selection dock a toolbar ([a2697a2](https://github.com/tonygorb/Scenri/commit/a2697a26201314185e609125d04a2bf6391c4e6e))
|
|
31
|
+
* **create:** archive a whole selection from the dock ([d5c2181](https://github.com/tonygorb/Scenri/commit/d5c2181210f0f92b1df528b0113a773a049e916d))
|
|
32
|
+
* **studio:** make the selection dock a toolbar ([362112e](https://github.com/tonygorb/Scenri/commit/362112e9d1bc2be6bf171f0b0702e61ca8845720))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Bug Fixes
|
|
36
|
+
|
|
37
|
+
* ask the browser whether the page is still here ([2800f8d](https://github.com/tonygorb/Scenri/commit/2800f8d72feb294b7a54da090242ecb2a66e6929))
|
|
38
|
+
* **brand:** a deleted brand does not reopen its dialogs on the next one ([dbe69eb](https://github.com/tonygorb/Scenri/commit/dbe69eb2e6679dc068c426721a0a0ebbfd39c3ca))
|
|
39
|
+
* **brand:** brand saves, renames, deletes and shot wipes reach the screen ([020c905](https://github.com/tonygorb/Scenri/commit/020c905c6700d8e909cef025d437bc7d4566b663))
|
|
40
|
+
* **create:** a shot restored from the archive comes back to the feed ([131d132](https://github.com/tonygorb/Scenri/commit/131d1329dac03a4d43299636ecf94cb90a26c0e1))
|
|
41
|
+
* **create:** keep a phone's toast clear of the tab bar ([c42f947](https://github.com/tonygorb/Scenri/commit/c42f94791f226879d15f460f2e054ddd79529a9b))
|
|
42
|
+
* **create:** the selection dock is a shelf on a phone, not the pill squeezed ([ffac597](https://github.com/tonygorb/Scenri/commit/ffac5970779d28dfabd52d7655d7469a993417e6))
|
|
43
|
+
* make every saved change reach every surface without a reload ([fb1e517](https://github.com/tonygorb/Scenri/commit/fb1e517170d1327eb4b1ce8af5a6e93d42c9ed7e))
|
|
44
|
+
* **presenters:** a saved person is on every surface the moment they land ([dd6ed16](https://github.com/tonygorb/Scenri/commit/dd6ed16ba1e687c1bf8848bb1f070349663ddb81))
|
|
45
|
+
* **products:** a product edit or delete reaches every surface at once ([2e34a76](https://github.com/tonygorb/Scenri/commit/2e34a765fe038e26d440a2ee586ea7844b6c35b9))
|
|
46
|
+
* **scenes:** a deleted scene leaves every surface at once ([1d132cf](https://github.com/tonygorb/Scenri/commit/1d132cff749437f1ed6ec5ea7635eaa92125763e))
|
|
47
|
+
* **studio:** ask the browser, not the last render, whether the page is still here ([0c4d874](https://github.com/tonygorb/Scenri/commit/0c4d8742a7358dad11fc5d6a2d137f8bb9d11448))
|
|
48
|
+
* **studio:** hand focus on after a delete, and write the rule down ([07efb5c](https://github.com/tonygorb/Scenri/commit/07efb5c653af482e4725587a731dceb1701de130))
|
|
49
|
+
* **studio:** let the selection bar undo Select all ([da21207](https://github.com/tonygorb/Scenri/commit/da21207c9d1215e85b10670b7af8c3b5631462b3))
|
|
50
|
+
* **studio:** order brand answers so a late read never undoes a newer write ([abac146](https://github.com/tonygorb/Scenri/commit/abac146d5fa8ff559bb1105589d2c4418c5df94b))
|
|
51
|
+
|
|
3
52
|
## [0.11.1](https://github.com/tonygorb/Scenri/compare/v0.11.0...v0.11.1) (2026-09-18)
|
|
4
53
|
|
|
5
54
|
|
|
@@ -865,7 +865,7 @@ function createStore(db) {
|
|
|
865
865
|
}));
|
|
866
866
|
},
|
|
867
867
|
updateBrand(id, json) {
|
|
868
|
-
db.prepare("UPDATE brands SET json=?, slug=?, updated_at=
|
|
868
|
+
db.prepare("UPDATE brands SET json=?, slug=?, updated_at=strftime('%Y-%m-%d %H:%M:%f','now') WHERE id=?").run(
|
|
869
869
|
JSON.stringify(json),
|
|
870
870
|
uniqueSlug(db, json.meta.name, id),
|
|
871
871
|
id
|
|
@@ -2224,5 +2224,5 @@ function createCore(homeDir = defaultHome()) {
|
|
|
2224
2224
|
}
|
|
2225
2225
|
|
|
2226
2226
|
export { ASPECT_TOLERANCE, BUDGET_EXHAUSTED, EDIT_REFERENCE_ROLE_DIRECTIVE, REFERENCE_ROLE_DIRECTIVE, SCHEMA_VERSION, STEM_MIN, SchemaTooNewError, SpendCapError, TRIGRAM_MIN, budgetSize, createCatalogStore, createCore, createStore, defaultHome, fold, ftsMatch, matchesQuery, ratioLabel, searchTerms, termMatches, uniqueProjectSlug, uniqueSetSlug, uniqueSlug };
|
|
2227
|
-
//# sourceMappingURL=chunk-
|
|
2228
|
-
//# sourceMappingURL=chunk-
|
|
2227
|
+
//# sourceMappingURL=chunk-MHTA6O3A.js.map
|
|
2228
|
+
//# sourceMappingURL=chunk-MHTA6O3A.js.map
|
|
@@ -463,7 +463,7 @@ async function addOrRepair(ownEntry, say, over) {
|
|
|
463
463
|
}
|
|
464
464
|
async function rememberDecline(home) {
|
|
465
465
|
try {
|
|
466
|
-
const { createCore } = await import('./src-
|
|
466
|
+
const { createCore } = await import('./src-INKSTJNC.js');
|
|
467
467
|
const core = createCore(home);
|
|
468
468
|
try {
|
|
469
469
|
core.store.setSetting("desktop.prompt", "declined");
|
|
@@ -530,5 +530,5 @@ function tail(path, bytes = 4096) {
|
|
|
530
530
|
}
|
|
531
531
|
|
|
532
532
|
export { addToDesktop, assetsDirFor, installDeps, runDesktopCommand, runExecFile, runOpenCommand };
|
|
533
|
-
//# sourceMappingURL=cli-
|
|
534
|
-
//# sourceMappingURL=cli-
|
|
533
|
+
//# sourceMappingURL=cli-4A3QWRSC.js.map
|
|
534
|
+
//# sourceMappingURL=cli-4A3QWRSC.js.map
|
package/dist/index.js
CHANGED
|
@@ -86,12 +86,12 @@ try {
|
|
|
86
86
|
break;
|
|
87
87
|
}
|
|
88
88
|
case "desktop": {
|
|
89
|
-
const { runDesktopCommand } = await import('./cli-
|
|
89
|
+
const { runDesktopCommand } = await import('./cli-4A3QWRSC.js');
|
|
90
90
|
process.exit(await runDesktopCommand(command, fileURLToPath(import.meta.url)));
|
|
91
91
|
break;
|
|
92
92
|
}
|
|
93
93
|
case "open": {
|
|
94
|
-
const { runOpenCommand } = await import('./cli-
|
|
94
|
+
const { runOpenCommand } = await import('./cli-4A3QWRSC.js');
|
|
95
95
|
process.exit(await runOpenCommand(fileURLToPath(import.meta.url)));
|
|
96
96
|
break;
|
|
97
97
|
}
|
package/dist/serve.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createUpdateChecker, classify, findNpm, isReleaseTriplet, stageVersion } from './chunk-YK37H6DM.js';
|
|
2
2
|
import { shouldAdoptRunning, anotherScenriLines, portBusyLines } from './chunk-CMLJGPYC.js';
|
|
3
|
-
import { SchemaTooNewError, createCore, BUDGET_EXHAUSTED, SpendCapError, EDIT_REFERENCE_ROLE_DIRECTIVE, REFERENCE_ROLE_DIRECTIVE, ratioLabel, searchTerms, termMatches, budgetSize, SCHEMA_VERSION, ASPECT_TOLERANCE } from './chunk-
|
|
3
|
+
import { SchemaTooNewError, createCore, BUDGET_EXHAUSTED, SpendCapError, EDIT_REFERENCE_ROLE_DIRECTIVE, REFERENCE_ROLE_DIRECTIVE, ratioLabel, searchTerms, termMatches, budgetSize, SCHEMA_VERSION, ASPECT_TOLERANCE } from './chunk-MHTA6O3A.js';
|
|
4
4
|
import { detectInstallKind } from './chunk-PAIAXRAC.js';
|
|
5
5
|
export { detectInstallKind } from './chunk-PAIAXRAC.js';
|
|
6
6
|
import { readMeta, repoSlug } from './chunk-Y3ZPBPLP.js';
|
|
@@ -8007,6 +8007,7 @@ async function runSceneBuild(deps, job, hashes, instruction, signal) {
|
|
|
8007
8007
|
commit(core, job.brandId, (json) => {
|
|
8008
8008
|
const rows = brandScenes(json);
|
|
8009
8009
|
const at = rows.findIndex((s) => s?.id === scene.id);
|
|
8010
|
+
if (at < 0 && job.sceneId) throw new Error("This scene was deleted while it was being read again.");
|
|
8010
8011
|
json.scenes = at >= 0 ? rows.map((s, i) => i === at ? scene : s) : [...rows, scene];
|
|
8011
8012
|
});
|
|
8012
8013
|
patch(job, {
|
|
@@ -8052,6 +8053,11 @@ function sceneBuildRunning(brandId, sceneId) {
|
|
|
8052
8053
|
}
|
|
8053
8054
|
return false;
|
|
8054
8055
|
}
|
|
8056
|
+
function cancelSceneBuilds(brandId, sceneId) {
|
|
8057
|
+
for (const b of builds.values()) {
|
|
8058
|
+
if (b.brandId === brandId && b.sceneId === sceneId && !b.finished) cancelAssetBuild(b.id);
|
|
8059
|
+
}
|
|
8060
|
+
}
|
|
8055
8061
|
var LOOPBACK = ["localhost", "127.0.0.1", "::1"];
|
|
8056
8062
|
var ACCESS_COOKIE = "sc_access";
|
|
8057
8063
|
var LEGACY_ACCESS_COOKIE = "bt_access";
|
|
@@ -10947,10 +10953,16 @@ function registerAssetBuildRoutes(app, deps) {
|
|
|
10947
10953
|
if (!brand) return;
|
|
10948
10954
|
const id = String(req.params.sceneId);
|
|
10949
10955
|
if (!brandScenes(brand.json).some((s) => s.id === id)) return reply.status(404).send({ error: "scene not found" });
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
10953
|
-
|
|
10956
|
+
cancelSceneBuilds(brand.id, id);
|
|
10957
|
+
let row;
|
|
10958
|
+
try {
|
|
10959
|
+
row = commit(core, brand.id, (json) => {
|
|
10960
|
+
json.scenes = brandScenes(json).filter((s) => s.id !== id);
|
|
10961
|
+
});
|
|
10962
|
+
} catch (err) {
|
|
10963
|
+
return reply.status(err.statusCode ?? 500).send({ error: err.message });
|
|
10964
|
+
}
|
|
10965
|
+
return { ok: true, brand: row };
|
|
10954
10966
|
});
|
|
10955
10967
|
app.post("/api/brands/:id/scenes/:sceneId/reread", async (req, reply) => {
|
|
10956
10968
|
const brand = brandOr404(req, reply);
|
|
@@ -11704,6 +11716,44 @@ function registerImageRoutes(app, deps) {
|
|
|
11704
11716
|
|
|
11705
11717
|
// src/release/notes.data.ts
|
|
11706
11718
|
var RELEASES = [
|
|
11719
|
+
{
|
|
11720
|
+
version: "0.13.0",
|
|
11721
|
+
date: "2026-09-21",
|
|
11722
|
+
title: "Learn teaches Scenri one lesson at a time, alerts are quieter, and the Create feed holds still.",
|
|
11723
|
+
sections: [
|
|
11724
|
+
{
|
|
11725
|
+
heading: "Learn",
|
|
11726
|
+
body: "Learn sits in the top bar, or under Help on a smaller screen, and teaches Scenri in six short lessons: your first shot, adding a product, a presenter, a scene, using a product again, and refining a shot. Each lesson keeps its own place, so you can set one down, take up another and come back to it. A new install is offered a guided first shot, and the guide can step back when you change your mind."
|
|
11727
|
+
},
|
|
11728
|
+
{
|
|
11729
|
+
heading: "Alerts",
|
|
11730
|
+
body: "Alerts are smaller and stack at the bottom of the screen, above the composer rather than over it. The same event twice shares one card, an error stays until you close it, and an alert holds still while you point at it or tab into it."
|
|
11731
|
+
},
|
|
11732
|
+
{
|
|
11733
|
+
heading: "Create",
|
|
11734
|
+
body: "Archiving a shot no longer makes the pictures around it blink, and opening or closing the side panel rearranges the feed in one step."
|
|
11735
|
+
}
|
|
11736
|
+
]
|
|
11737
|
+
},
|
|
11738
|
+
{
|
|
11739
|
+
version: "0.12.0",
|
|
11740
|
+
date: "2026-09-20",
|
|
11741
|
+
title: "Saved work shows up everywhere at once, and a selection has its own toolbar.",
|
|
11742
|
+
sections: [
|
|
11743
|
+
{
|
|
11744
|
+
heading: "Create",
|
|
11745
|
+
body: "Pick several shots and the dock can archive the lot in one go, with a single Undo that brings them all back. That dock is a toolbar now: how many are picked, Select all, and the verbs as tools that name themselves. It is the same bar on a phone, at a size a thumb can hit."
|
|
11746
|
+
},
|
|
11747
|
+
{
|
|
11748
|
+
heading: "Brand",
|
|
11749
|
+
body: "A brand you save, rename or delete, and a workspace you wipe, show up on every screen straight away. A brand you have just deleted no longer reopens its dialogs on the brand you land in next."
|
|
11750
|
+
},
|
|
11751
|
+
{
|
|
11752
|
+
heading: "Fixes",
|
|
11753
|
+
body: "A product edit, a new presenter and a deleted scene each reach every surface that shows them, without a reload, and a slow answer can no longer undo a newer change. Walking to another page while a delete is still out leaves you where you went, instead of pulling you back when it answers. A shot restored from the archive comes back to the feed where it belongs. After deleting a record, focus lands somewhere sensible instead of at the top of the page. On a phone a toast no longer sits on the tab bar."
|
|
11754
|
+
}
|
|
11755
|
+
]
|
|
11756
|
+
},
|
|
11707
11757
|
{
|
|
11708
11758
|
version: "0.11.1",
|
|
11709
11759
|
date: "2026-09-18",
|
|
@@ -12804,14 +12854,24 @@ function registerSystemRoutes(app, deps) {
|
|
|
12804
12854
|
}
|
|
12805
12855
|
|
|
12806
12856
|
// src/routes/guide.ts
|
|
12807
|
-
var TASKS = ["first-shot", "refine", "product", "presenter", "scene"];
|
|
12857
|
+
var TASKS = ["first-shot", "refine", "product", "presenter", "scene", "reuse"];
|
|
12808
12858
|
var MILESTONES = ["shot", "refine", "product", "presenter", "scene"];
|
|
12809
12859
|
var KEY = "guide";
|
|
12810
12860
|
var isTask = (t) => TASKS.includes(t);
|
|
12811
12861
|
var isMilestone = (m) => MILESTONES.includes(m);
|
|
12812
12862
|
var num2 = (n) => typeof n === "number" && Number.isFinite(n) && n >= 0 ? n : 0;
|
|
12813
12863
|
function blank(eligible) {
|
|
12814
|
-
return {
|
|
12864
|
+
return {
|
|
12865
|
+
v: 2,
|
|
12866
|
+
eligible,
|
|
12867
|
+
welcome: null,
|
|
12868
|
+
hidden: null,
|
|
12869
|
+
done: {},
|
|
12870
|
+
lessons: {},
|
|
12871
|
+
dismissed: [],
|
|
12872
|
+
active: null,
|
|
12873
|
+
progress: {}
|
|
12874
|
+
};
|
|
12815
12875
|
}
|
|
12816
12876
|
function parse2(raw) {
|
|
12817
12877
|
if (!raw) return null;
|
|
@@ -12823,9 +12883,47 @@ function parse2(raw) {
|
|
|
12823
12883
|
if (j.done && typeof j.done === "object") {
|
|
12824
12884
|
for (const [k, at] of Object.entries(j.done)) if (isMilestone(k) && typeof at === "string") done[k] = at;
|
|
12825
12885
|
}
|
|
12886
|
+
const lessons = {};
|
|
12887
|
+
if (j.lessons && typeof j.lessons === "object") {
|
|
12888
|
+
for (const [k, at] of Object.entries(j.lessons)) if (isTask(k) && typeof at === "string") lessons[k] = at;
|
|
12889
|
+
}
|
|
12890
|
+
const asTask = (a2) => {
|
|
12891
|
+
const b2 = a2?.baseline;
|
|
12892
|
+
return a2 && isTask(a2.task) && typeof a2.brandId === "string" && typeof a2.since === "string" ? {
|
|
12893
|
+
task: a2.task,
|
|
12894
|
+
brandId: a2.brandId,
|
|
12895
|
+
since: a2.since,
|
|
12896
|
+
baseline: { products: num2(b2?.products), presenters: num2(b2?.presenters), scenes: num2(b2?.scenes) },
|
|
12897
|
+
...a2.paused === true ? { paused: true } : {}
|
|
12898
|
+
} : null;
|
|
12899
|
+
};
|
|
12900
|
+
const asProgress = (v) => {
|
|
12901
|
+
const p = v;
|
|
12902
|
+
const b2 = p?.baseline;
|
|
12903
|
+
return p && typeof p.brandId === "string" && typeof p.since === "string" ? {
|
|
12904
|
+
brandId: p.brandId,
|
|
12905
|
+
since: p.since,
|
|
12906
|
+
baseline: { products: num2(b2?.products), presenters: num2(b2?.presenters), scenes: num2(b2?.scenes) },
|
|
12907
|
+
reached: Array.isArray(p.reached) ? p.reached.filter((m) => typeof m === "string") : [],
|
|
12908
|
+
...p.paused === true ? { paused: true } : {}
|
|
12909
|
+
} : null;
|
|
12910
|
+
};
|
|
12911
|
+
const progress = {};
|
|
12912
|
+
if (j.progress && typeof j.progress === "object") {
|
|
12913
|
+
for (const [k, v] of Object.entries(j.progress)) {
|
|
12914
|
+
const p = asProgress(v);
|
|
12915
|
+
if (isTask(k) && p) progress[k] = p;
|
|
12916
|
+
}
|
|
12917
|
+
}
|
|
12918
|
+
if (j.parked && typeof j.parked === "object") {
|
|
12919
|
+
for (const [k, v] of Object.entries(j.parked)) {
|
|
12920
|
+
const t = asTask(v);
|
|
12921
|
+
if (isTask(k) && t && !progress[k]) progress[k] = { ...t, reached: [], paused: true };
|
|
12922
|
+
}
|
|
12923
|
+
}
|
|
12826
12924
|
const a = j.active;
|
|
12827
12925
|
const b = a?.baseline;
|
|
12828
|
-
const
|
|
12926
|
+
const held = a && isTask(a.task) && typeof a.brandId === "string" && typeof a.since === "string" ? {
|
|
12829
12927
|
task: a.task,
|
|
12830
12928
|
brandId: a.brandId,
|
|
12831
12929
|
since: a.since,
|
|
@@ -12838,8 +12936,11 @@ function parse2(raw) {
|
|
|
12838
12936
|
welcome: j.welcome === "taken" || j.welcome === "declined" ? j.welcome : null,
|
|
12839
12937
|
hidden: typeof j.hidden === "boolean" ? j.hidden : null,
|
|
12840
12938
|
done,
|
|
12939
|
+
lessons,
|
|
12841
12940
|
dismissed: Array.isArray(j.dismissed) ? j.dismissed.filter(isTask) : [],
|
|
12842
|
-
|
|
12941
|
+
// an old record's one task in hand is that lesson's progress now
|
|
12942
|
+
active: typeof j.active === "string" && isTask(j.active) ? j.active : held?.task ?? null,
|
|
12943
|
+
progress: held && !progress[held.task] ? { ...progress, [held.task]: { ...held, reached: [] } } : progress
|
|
12843
12944
|
};
|
|
12844
12945
|
} catch {
|
|
12845
12946
|
return null;
|
|
@@ -12898,21 +12999,33 @@ function readGuide(core, env) {
|
|
|
12898
12999
|
changed = true;
|
|
12899
13000
|
}
|
|
12900
13001
|
}
|
|
12901
|
-
|
|
12902
|
-
|
|
13002
|
+
for (const [t, p] of Object.entries(r.progress)) {
|
|
13003
|
+
if (core.store.getBrand(p.brandId)) continue;
|
|
13004
|
+
delete r.progress[t];
|
|
13005
|
+
if (r.active === t) r.active = null;
|
|
12903
13006
|
changed = true;
|
|
12904
13007
|
}
|
|
12905
13008
|
if (changed) write(core.store, r);
|
|
12906
|
-
const
|
|
12907
|
-
const
|
|
12908
|
-
|
|
13009
|
+
const on = r.active ? r.progress[r.active] : null;
|
|
13010
|
+
const a = r.active && on ? {
|
|
13011
|
+
task: r.active,
|
|
13012
|
+
brandId: on.brandId,
|
|
13013
|
+
since: on.since,
|
|
13014
|
+
baseline: on.baseline,
|
|
13015
|
+
...on.paused ? { paused: true } : {}
|
|
13016
|
+
} : null;
|
|
13017
|
+
const nodeKind = a?.task === "first-shot" || a?.task === "reuse" ? "generation" : a?.task === "refine" ? "edit" : null;
|
|
13018
|
+
const settled = r.welcome === null && !!r.done.shot;
|
|
13019
|
+
const eligible = r.eligible && !settled && env.SCENRI_NO_GUIDE !== "1";
|
|
12909
13020
|
return {
|
|
12910
13021
|
eligible,
|
|
12911
13022
|
welcome: r.welcome,
|
|
12912
13023
|
hidden: r.hidden ?? !eligible,
|
|
12913
13024
|
done: r.done,
|
|
13025
|
+
lessons: r.lessons,
|
|
12914
13026
|
dismissed: r.dismissed,
|
|
12915
13027
|
active: a,
|
|
13028
|
+
progress: r.progress,
|
|
12916
13029
|
activeNodes: a && nodeKind ? core.store.nodesSince(a.brandId, nodeKind, a.since) : [],
|
|
12917
13030
|
activeDraftId: a?.task === "presenter" ? core.store.presenterDraftSince(a.brandId, a.since) : null,
|
|
12918
13031
|
counts: a ? countsOf(core, a.brandId) : null
|
|
@@ -12930,19 +13043,34 @@ function applyIntent(core, body) {
|
|
|
12930
13043
|
if (typeof s.brandId !== "string") return "brandId required";
|
|
12931
13044
|
const baseline = countsOf(core, s.brandId);
|
|
12932
13045
|
if (!baseline) return "brand not found";
|
|
12933
|
-
const
|
|
12934
|
-
if (
|
|
12935
|
-
|
|
12936
|
-
|
|
12937
|
-
|
|
13046
|
+
const guiding = r.active ? r.progress[r.active] : null;
|
|
13047
|
+
if (r.active && r.active !== s.task && guiding) r.progress[r.active] = { ...guiding, paused: true };
|
|
13048
|
+
const mine = r.progress[s.task];
|
|
13049
|
+
if (mine && mine.brandId === s.brandId) {
|
|
13050
|
+
const { paused: _, ...going } = mine;
|
|
13051
|
+
r.progress[s.task] = going;
|
|
13052
|
+
} else r.progress[s.task] = { brandId: s.brandId, since: core.store.now(), baseline, reached: [] };
|
|
13053
|
+
r.active = s.task;
|
|
12938
13054
|
r.dismissed = r.dismissed.filter((t) => t !== s.task);
|
|
12939
13055
|
} else if ("finish" in b) {
|
|
12940
13056
|
if (!isTask(b.finish)) return "unknown task";
|
|
12941
|
-
if (r.
|
|
13057
|
+
if (!r.lessons[b.finish]) r.lessons[b.finish] = (/* @__PURE__ */ new Date()).toISOString();
|
|
13058
|
+
if (r.active === b.finish) r.active = null;
|
|
13059
|
+
delete r.progress[b.finish];
|
|
12942
13060
|
} else if ("dismiss" in b) {
|
|
12943
13061
|
if (!isTask(b.dismiss)) return "unknown task";
|
|
12944
13062
|
if (!r.dismissed.includes(b.dismiss)) r.dismissed.push(b.dismiss);
|
|
12945
|
-
|
|
13063
|
+
const shut = r.progress[b.dismiss];
|
|
13064
|
+
if (shut) r.progress[b.dismiss] = { ...shut, paused: true };
|
|
13065
|
+
if (r.active === b.dismiss) r.active = null;
|
|
13066
|
+
} else if ("reached" in b) {
|
|
13067
|
+
const w = b.reached ?? {};
|
|
13068
|
+
if (!isTask(w.task)) return "unknown task";
|
|
13069
|
+
if (typeof w.moment !== "string" || !w.moment) return "moment required";
|
|
13070
|
+
const p = r.progress[w.task];
|
|
13071
|
+
if (!p) return null;
|
|
13072
|
+
if (p.reached.includes(w.moment)) return null;
|
|
13073
|
+
r.progress[w.task] = { ...p, reached: [...p.reached, w.moment].slice(-24) };
|
|
12946
13074
|
} else if ("hidden" in b) {
|
|
12947
13075
|
if (typeof b.hidden !== "boolean") return "hidden is true or false";
|
|
12948
13076
|
r.hidden = b.hidden;
|
|
@@ -12976,7 +13104,7 @@ function registerDesktopRoutes(app, deps) {
|
|
|
12976
13104
|
record: null
|
|
12977
13105
|
};
|
|
12978
13106
|
}
|
|
12979
|
-
const { installDeps } = await import('./cli-
|
|
13107
|
+
const { installDeps } = await import('./cli-4A3QWRSC.js');
|
|
12980
13108
|
const { desktopStatus } = await import('./install-VXJPLYWM.js');
|
|
12981
13109
|
return desktopStatus(installDeps(runtime.entry));
|
|
12982
13110
|
});
|
|
@@ -12984,7 +13112,7 @@ function registerDesktopRoutes(app, deps) {
|
|
|
12984
13112
|
if (!runtime.entry) {
|
|
12985
13113
|
return { ok: false, reason: "unsupported", message: "Desktop shortcuts are not available on this system yet." };
|
|
12986
13114
|
}
|
|
12987
|
-
const { addToDesktop } = await import('./cli-
|
|
13115
|
+
const { addToDesktop } = await import('./cli-4A3QWRSC.js');
|
|
12988
13116
|
return addToDesktop(runtime.entry);
|
|
12989
13117
|
});
|
|
12990
13118
|
app.get("/api/desktop", async () => {
|
|
@@ -13092,7 +13220,12 @@ function buildServer(opts) {
|
|
|
13092
13220
|
return { ...row, warnings, report };
|
|
13093
13221
|
});
|
|
13094
13222
|
app.put("/api/brands/:id", async (req, reply) => {
|
|
13095
|
-
const
|
|
13223
|
+
const body = req.body ?? {};
|
|
13224
|
+
let json = body.brand;
|
|
13225
|
+
if (body.keepAssets === true && json && typeof json === "object") {
|
|
13226
|
+
const stored = core.store.getBrand(req.params.id);
|
|
13227
|
+
if (stored) json = withStoredAssets(json, stored.json);
|
|
13228
|
+
}
|
|
13096
13229
|
const v = validateBrand(json);
|
|
13097
13230
|
if (!v.valid) return reply.status(400).send({ error: "invalid .brand", details: v.errors });
|
|
13098
13231
|
const row = core.store.updateBrand(req.params.id, json);
|
|
@@ -14474,6 +14607,16 @@ function buildServer(opts) {
|
|
|
14474
14607
|
}
|
|
14475
14608
|
return app;
|
|
14476
14609
|
}
|
|
14610
|
+
var ASSET_COLLECTIONS = ["products", "scenes", "characters"];
|
|
14611
|
+
function withStoredAssets(sent, stored) {
|
|
14612
|
+
const out = { ...sent };
|
|
14613
|
+
const held = stored ?? {};
|
|
14614
|
+
for (const key of ASSET_COLLECTIONS) {
|
|
14615
|
+
if (key in held) out[key] = held[key];
|
|
14616
|
+
else delete out[key];
|
|
14617
|
+
}
|
|
14618
|
+
return out;
|
|
14619
|
+
}
|
|
14477
14620
|
|
|
14478
14621
|
// src/serve.ts
|
|
14479
14622
|
var PORT = Number(process.env.SCENRI_PORT || 4747);
|
|
@@ -14625,7 +14768,7 @@ async function run() {
|
|
|
14625
14768
|
}
|
|
14626
14769
|
}
|
|
14627
14770
|
const ownEntry = fileURLToPath(import.meta.url);
|
|
14628
|
-
const { addToDesktop, installDeps } = await import('./cli-
|
|
14771
|
+
const { addToDesktop, installDeps } = await import('./cli-4A3QWRSC.js');
|
|
14629
14772
|
const { refreshLauncher } = await import('./refresh-5HBDLLLB.js');
|
|
14630
14773
|
const { askOnTerminal, offerDesktop, shouldOfferDesktop } = await import('./offer-W6NJXMWT.js');
|
|
14631
14774
|
const { launcherInstalled } = await import('./paths-6ZXRZUHY.js');
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { ASPECT_TOLERANCE, BUDGET_EXHAUSTED, EDIT_REFERENCE_ROLE_DIRECTIVE, REFERENCE_ROLE_DIRECTIVE, SCHEMA_VERSION, STEM_MIN, SchemaTooNewError, SpendCapError, TRIGRAM_MIN, budgetSize, createCatalogStore, createCore, createStore, defaultHome, fold, ftsMatch, matchesQuery, ratioLabel, searchTerms, termMatches, uniqueProjectSlug, uniqueSetSlug, uniqueSlug } from './chunk-
|
|
2
|
-
//# sourceMappingURL=src-
|
|
3
|
-
//# sourceMappingURL=src-
|
|
1
|
+
export { ASPECT_TOLERANCE, BUDGET_EXHAUSTED, EDIT_REFERENCE_ROLE_DIRECTIVE, REFERENCE_ROLE_DIRECTIVE, SCHEMA_VERSION, STEM_MIN, SchemaTooNewError, SpendCapError, TRIGRAM_MIN, budgetSize, createCatalogStore, createCore, createStore, defaultHome, fold, ftsMatch, matchesQuery, ratioLabel, searchTerms, termMatches, uniqueProjectSlug, uniqueSetSlug, uniqueSlug } from './chunk-MHTA6O3A.js';
|
|
2
|
+
//# sourceMappingURL=src-INKSTJNC.js.map
|
|
3
|
+
//# sourceMappingURL=src-INKSTJNC.js.map
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|