mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-08-11 03:09:57 +00:00
feat(v3): tabbed, card-row settings page + per-plugin settings category (#584)
Replace the single long scrolling v3 settings screen with a horizontal tab bar (Gameplay / Audio / Graphics / Keybinds / Progression / Mic / Plugins / System) over card rows (icon + title + description, control on the right) with a per-category Reset. - static/v3/index.html: tab bar + card-row markup (ids keep hydrating through the unchanged app.js loadSettings()/persistSetting() path). - static/v3/settings.js (new): tab switching + active-tab persistence (localStorage 'v3-settings-tab'), per-category reset, read-only Keybinds reference from window.getAllShortcuts(). - static/v3/v3.css: plain CSS, no Tailwind rebuild. - Per-plugin settings tab: new optional settings.category in plugin.json → plugins/__init__.py surfaces settings_category; app.js mounts each plugin <details> into #plugin-settings-<category> (fallback: Plugins tab). highway_3d ships category: "graphics". - New gameplay settings: countdown_before_song (wired end-to-end, default off); miss_penalty + fail_behavior (persist-only stubs); "Note highway speed" surfaces existing master_difficulty. - New POST /api/settings/reset clears whitelisted keys back to defaults. Tests: test_settings_api.py, test_plugins.py::test_settings_category_parsed_from_manifest, tests/browser/settings-tabbed.spec.ts. 179 passed locally. Ported from the pre-rename feat/v3-settings-tabbed WIP onto current main (slopsmith→feedBack rename applied; settings-screen markup conflict resolved in favour of the new tabbed layout — all prior setting ids preserved). Closes #579 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
f3a5cb9ed3
commit
3b485fe62b
@@ -4006,3 +4006,32 @@ def test_loader_honors_persisted_disable_without_memory_flip(tmp_path, reset_plu
|
||||
assert not (config_dir / "z_marker").exists()
|
||||
assert plugins.PENDING_PLUGINS["z_target"]["status"] == "disabled"
|
||||
assert plugins.PENDING_PLUGINS["z_target"]["enabled"] is False
|
||||
|
||||
|
||||
def test_settings_category_parsed_from_manifest(tmp_path, reset_plugin_state):
|
||||
"""A plugin manifest's settings.category is parsed into settings_category
|
||||
on the loaded entry (drives the v3 settings-tab placement). Absent or a
|
||||
bare-string `settings` value yields None → the frontend's fallback tab."""
|
||||
plugins = reset_plugin_state
|
||||
|
||||
def _write(pid, settings_value):
|
||||
d = tmp_path / pid
|
||||
d.mkdir()
|
||||
(d / "plugin.json").write_text(json.dumps({
|
||||
"id": pid, "name": pid, "routes": "routes.py", "settings": settings_value,
|
||||
}))
|
||||
(d / "routes.py").write_text("def setup(app, ctx):\n pass\n")
|
||||
|
||||
_write("graphy", {"html": "settings.html", "category": "graphics"})
|
||||
_write("plainset", {"html": "settings.html"}) # dict, no category
|
||||
_write("noset", None) # no settings at all
|
||||
|
||||
_run_load_plugins(plugins, type("FakeApp", (), {})(), tmp_path)
|
||||
|
||||
rows = {p["id"]: p for p in plugins.LOADED_PLUGINS}
|
||||
assert rows["graphy"]["settings_category"] == "graphics"
|
||||
assert rows["graphy"]["has_settings"] is True
|
||||
assert rows["plainset"]["settings_category"] is None
|
||||
assert rows["plainset"]["has_settings"] is True
|
||||
assert rows["noset"]["settings_category"] is None
|
||||
assert rows["noset"]["has_settings"] is False
|
||||
|
||||
Reference in New Issue
Block a user