Two pieces of the "port v4's exact UI onto v5's backend" plan: - core/contract.py: new optional ModuleSpec.category field (closed set: continuity, guidance, conditioning, sampling, post, system), validated in core/schema.py, threaded through core/registry.py's FIELDS and to_manifest(). Presentation grouping, independent of STAGE (execution order) -- a module can be stage="sampling" and category="guidance" at once. Only the 4 existing modules that actually render a settings panel (alg, sharpen, appearance, full_control) got a category assigned; the other 12 have none to categorize (no SETTINGS block) and stay uncategorised, which is valid. - v4's frontend (movie_editor/frontend/*, ~29k lines, 61 files) copied verbatim into app/legacy/. core/routes.py's "/" route now serves legacy/index.html instead of the composer entry point; a <base> tag in that file resolves its own relative script/link tags against /funpack/app/legacy/ regardless of what URL it's served at, so every file moved as a unit with zero per-file path edits. Verified live: all 61 assets load 200 OK, the real v4 onboarding screen renders pixel-for- pixel (it's the actual DOM/CSS, not a reimplementation), and several v4 API calls (/api/media, /api/projects, /api/git/status) already succeed against v5's real backend by coincidence of shared route naming -- the rest 404/405 as expected, since api.js's ~90 functions haven't been rewired to v5's actual routes yet (next piece of this plan). The old composer entry point (app/index.html, app/composer/**) stays in the tree, unreferenced, until a later cleanup pass once nothing imports it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
41 lines
1.2 KiB
Python
41 lines
1.2 KiB
Python
"""Appearance: theme and grid density.
|
|
|
|
The first real vertical slice, and deliberately the smallest one that exercises
|
|
the whole path -- announcement, schema, panel, values -- with no model, no
|
|
sampler and nothing that needs a GPU to be seen working.
|
|
"""
|
|
|
|
ID = "appearance"
|
|
TITLE = "Appearance"
|
|
MOUNT = "settings.general"
|
|
STAGE = "load"
|
|
CATEGORY = "system"
|
|
STATUS = "proven"
|
|
|
|
SETTINGS = {
|
|
"theme": {
|
|
"type": "enum", "default": "auto",
|
|
"label": "Colour scheme", "ui": "segmented",
|
|
"options": [
|
|
{"value": "dark", "label": "Dark"},
|
|
{"value": "light", "label": "Light"},
|
|
{"value": "auto", "label": "Auto"},
|
|
],
|
|
},
|
|
"density": {
|
|
"type": "int", "default": 0, "min": 0, "max": 4, "step": 1,
|
|
"label": "Media columns",
|
|
"hint": "0 fits as many as the panel allows.",
|
|
"ui": "stepper",
|
|
},
|
|
}
|
|
|
|
|
|
def apply(values, context=None):
|
|
"""Nothing to do at generation time: appearance is the browser's business.
|
|
|
|
Declared anyway so the module has the same shape as every other one -- a
|
|
module core has to special-case is a module that will be forgotten.
|
|
"""
|
|
return context
|