mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-08-12 11:49:28 +00:00
rename: slopsmith → feedBack, byron → got-feedBack (#537)
* Update GitHub repo references from feedback* to feedBack* * rename: slopsmith -> feedBack, byron -> got-feedBack Renames across the entire codebase: - slopsmith/Slopsmith/SLOPSMITH/SlopSmith -> feedBack/FeedBack/FEEDBACK/FeedBack - byron/Byron/Byrongamatos -> got-feedBack/got-feedBack/got-feedBack - /home/byron/ -> /opt/got-feedBack/ - byron@ougsoft.com -> hi@got-feedBack.org - github.com/byrongamatos/ -> github.com/got-feedback/ - com.byron. -> com.got-feedback. - SLOPSMITH_ env vars -> FEEDBACK_ with backward-compat fallback - Protocol/storage strings migrated with read-old/write-new pattern - window.slopsmith JS API -> window.feedBack (canonical) + backward-compat alias Refs: #rename-slopsmith * rename: complete regen against current main + fix backward-compat alias Regenerated the slopsmith->feedBack / byron->got-feedBack rename on top of current main (3 commits had landed since the branch: #572/#554/#574), resolving the four content conflicts in favour of main's newer content (autoplay/auto-exit, accuracy-badge, Virtuoso re-home, feedpak badge). Completion fixes on top of the mechanical rename: - Re-apply rename to post-branch content the original rename never saw: window.slopsmith(.Tour) consumers in lessons.js / notifications.js / onboarding-tour.js, and the matching JS + python tests (autoplay_exit, progression_*, test_feedpak_extension FEEDBACK_* env vars). The test env vars now match server.py (which reads FEEDBACK_SYNC_STARTUP / FEEDBACK_SKIP_STARTUP_TASKS), so the sync-startup test exercises the real path again. - Restore the window.slopsmith backward-compat alias dropped during conflict resolution, and move the bus aliases to AFTER the _feedBackExisting merge block so they reference the fully-assembled object (also fixes the loop_api.test.js API-surface regex, which the original PR latently broke). - Drop the stray empty data/web_library.db (runtime DB lives in CONFIG_DIR) and gitignore it. - Fix stale tone-source test: feed[dB]ack -> fee[dB]ack to match shipped source labels. Verified locally (org CI billing-blocked): JS 819/819 pass; pytest 1669 passed / 1683 collected with 0 import errors; zero residual slopsmith/byron except the two intentional window.slopsmith aliases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * rename: implement advertised backward-compat + prune dead community plugins Address gaps where PR #537's "Backward compatibility" section was advertised but not implemented, and clean up the community plugin list. Env vars (FEEDBACK_* canonical, legacy SLOPSMITH_* honoured): - New lib/env_compat.py (getenv_compat / env_flag_compat) + tests. server.py (_env_flag + all FEEDBACK_* reads), diagnostics_hardware, gp2midi and tailwind_rebuild now resolve the legacy alias, so existing SLOPSMITH_UI / SLOPSMITH_PLUGINS_DIR / etc. deployments keep working. - Fix the rename collapsing plugins/__init__.py and minigames/routes.py from `FEEDBACK_PLUGINS_DIR or SLOPSMITH_PLUGINS_DIR` into a redundant `FEEDBACK_ or FEEDBACK_` (the fallback was silently lost). Storage (app.js update-channel): - Read feedBack-update-channel, fall back to legacy slopsmith-update-channel, and clear the legacy key on write — so a user's update-channel preference survives the rename instead of resetting to "stable". Community plugin list (README): the rename rewrote third-party repo URLs we don't own. Probed every one; their owners never renamed, so: - Restore the 13 live community plugins to their real slopsmith-* names. - Prune 6 that are 404 to the public (topkoa splitscreen/stems, OmikronApex tuner, Jafz2001 nam-rig-builder, DeathlySin song-preview, Erikcb91 shuffle). - Fix a pre-existing Guitar Theory clone-command typo (nam-tone -> guitar-theory). Verified: env_compat 7/7, JS 819/819, pytest 1690 collected / 0 import errors, rename-sensitive + startup suites green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: byrongamatos <xasiklas@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
byrongamatos
parent
a8ad02739a
commit
af2949677a
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
const sm = window.slopsmith;
|
||||
const sm = window.feedBack;
|
||||
const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => (
|
||||
{ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
||||
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
const sm = window.slopsmith;
|
||||
const sm = window.feedBack;
|
||||
const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => (
|
||||
{ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
||||
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
const sm = window.slopsmith;
|
||||
const sm = window.feedBack;
|
||||
if (!sm || !sm.libraryCardActions) return;
|
||||
|
||||
const STD_RETUNABLE = ['Eb Standard', 'D Standard', 'C# Standard', 'C Standard'];
|
||||
const reg = sm.libraryCardActions;
|
||||
const hooks = window.__slopsmithV3CoreCardActions || (window.__slopsmithV3CoreCardActions = {});
|
||||
const hooks = window.__feedBackV3CoreCardActions || (window.__feedBackV3CoreCardActions = {});
|
||||
if (hooks.installed) return;
|
||||
hooks.installed = true;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
const sm = window.slopsmith;
|
||||
const sm = window.feedBack;
|
||||
const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => (
|
||||
{ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
||||
const enc = encodeURIComponent;
|
||||
@@ -106,7 +106,7 @@
|
||||
|
||||
const name = (profile && profile.display_name) || 'there';
|
||||
const ver = (version && version.version) || '';
|
||||
const changelogUrl = ((version && version.source_url) || 'https://github.com/got-feedback/feedback') + '/blob/main/CHANGELOG.md';
|
||||
const changelogUrl = ((version && version.source_url) || 'https://github.com/got-feedback/feedBack') + '/blob/main/CHANGELOG.md';
|
||||
const songCount = (libStats && (libStats.total_songs ?? libStats.total)) || 0;
|
||||
const pluginCount = Array.isArray(plugins)
|
||||
? plugins.filter((p) => (p && (p.status || 'ready') === 'ready')).length : 0;
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
*
|
||||
* A vanilla-JS reskin of the bundled `minigames` plugin's screen into the fb-*
|
||||
* design (constitution P-II). It REUSES the minigames backend + the
|
||||
* window.slopsmithMinigames SDK — it does not fork scoring/run logic and adds
|
||||
* window.feedBackMinigames SDK — it does not fork scoring/run logic and adds
|
||||
* no second XP curve. XP stays unified through the core store (P15): the header
|
||||
* reads /api/profile/progress (the same data the topbar profile badge shows),
|
||||
* while per-game bests + cross-game unlocks come from the minigames /profile.
|
||||
*
|
||||
* UI placement is a DEFERRED capability domain (design/05): we use the legacy
|
||||
* plugin loader + /api/plugins/minigames/* routes, NOT capability dispatch.
|
||||
* Launch delegates to slopsmithMinigames.start(gameId), which mounts the
|
||||
* Launch delegates to feedBackMinigames.start(gameId), which mounts the
|
||||
* plugin's own #mg-stage overlay (eagerly injected at boot) — so this screen
|
||||
* never needs to visit the legacy #plugin-minigames hub.
|
||||
*/
|
||||
@@ -18,7 +18,7 @@
|
||||
'use strict';
|
||||
|
||||
const SCREEN_ID = 'v3-feedbarcade';
|
||||
const sm = window.slopsmith;
|
||||
const sm = window.feedBack;
|
||||
const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => (
|
||||
{ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
||||
const enc = encodeURIComponent;
|
||||
@@ -32,7 +32,7 @@
|
||||
let _stageWasVisible = false;
|
||||
let _refreshTimer = null;
|
||||
|
||||
function sdk() { return window.slopsmithMinigames || null; }
|
||||
function sdk() { return window.feedBackMinigames || null; }
|
||||
function registeredList() {
|
||||
const s = sdk();
|
||||
try { return (s && typeof s.listRegistered === 'function') ? s.listRegistered() : []; }
|
||||
@@ -271,7 +271,7 @@
|
||||
// The minigames plugin publishes its SDK + injects #mg-stage at boot and
|
||||
// fires this once ready; re-render so late-registered specs appear and
|
||||
// the stage observer attaches.
|
||||
window.addEventListener('slopsmith-minigames-ready', () => { ensureStageObserver(); refresh(); });
|
||||
window.addEventListener('feedBack-minigames-ready', () => { ensureStageObserver(); refresh(); });
|
||||
}
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', boot, { once: true });
|
||||
|
||||
+21
-21
@@ -1,6 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
fee[dB]ack v0.3.0 shell (SLOPSMITH_UI=v3 / GET /v3).
|
||||
fee[dB]ack v0.3.0 shell (FEEDBACK_UI=v3 / GET /v3).
|
||||
|
||||
This is a re-chromed copy of the legacy static/index.html: the v0.3.0
|
||||
sidebar + topbar replace the (hidden) legacy navbar, new #v3-* screens are
|
||||
@@ -9,7 +9,7 @@
|
||||
boots UNMODIFIED and the whole engine — player/highway, plugin loader,
|
||||
capabilities, audio, library, settings — is reused as-is. Navigation is the
|
||||
shared window.showScreen across both #v3-* and legacy/#plugin-* screens.
|
||||
See ~/Repositories/slopsmith-feedback-v030/prompts/12-app-shell.md.
|
||||
See ~/Repositories/feedBack-feedback-v030/prompts/12-app-shell.md.
|
||||
-->
|
||||
<html lang="en" class="dark scroll-smooth">
|
||||
<head>
|
||||
@@ -69,7 +69,7 @@
|
||||
stylesheet (regenerated by scripts/build-tailwind.sh). The old
|
||||
Play CDN (cdn.tailwindcss.com) JIT scanned the DOM ~1.8x/sec
|
||||
on the main thread, dropping ~26% of frames with the 3D
|
||||
highway running — see slopsmith-desktop#110. Theme extensions
|
||||
highway running — see feedBack-desktop#110. Theme extensions
|
||||
(dark/accent/gold colors, Inter font) live in tailwind.config.js. -->
|
||||
<link rel="stylesheet" href="/static/tailwind.min.css">
|
||||
<!-- UI font: Rubik (Google Fonts, OFL). Applied via fontFamily.display in tailwind.config.js. -->
|
||||
@@ -82,7 +82,7 @@
|
||||
<link rel="stylesheet" href="/static/v3/v3.css">
|
||||
<!-- Diagnostics console capture must wrap console.* before any other
|
||||
script logs anything; load it as early as possible. See
|
||||
docs/diagnostics-bundle-spec.md (slopsmith#166). -->
|
||||
docs/diagnostics-bundle-spec.md (feedBack#166). -->
|
||||
<script src="/static/diagnostics.js"></script>
|
||||
<script src="/static/capabilities.js"></script>
|
||||
<script src="/static/capabilities/library.js"></script>
|
||||
@@ -143,7 +143,7 @@
|
||||
<div class="max-w-7xl mx-auto px-6 h-16 flex items-center justify-between">
|
||||
<div class="flex items-end gap-1.5">
|
||||
<a href="#" onclick="showScreen('home');return false" class="text-xl font-bold bg-gradient-to-r from-accent-light to-purple-400 bg-clip-text text-transparent">
|
||||
Slopsmith
|
||||
FeedBack
|
||||
</a>
|
||||
<span id="app-version" class="text-xs text-gray-600 mb-0.5"></span>
|
||||
</div>
|
||||
@@ -229,7 +229,7 @@
|
||||
<!-- Tree controls -->
|
||||
<button onclick="toggleAllArtists(true)" class="lib-tree-ctrl bg-dark-700 border border-gray-800 rounded-xl px-3 py-2.5 text-sm text-gray-400 hover:text-white transition">Expand All</button>
|
||||
<button onclick="toggleAllArtists(false)" class="lib-tree-ctrl bg-dark-700 border border-gray-800 rounded-xl px-3 py-2.5 text-sm text-gray-400 hover:text-white transition">Collapse All</button>
|
||||
<!-- Filters drawer toggle (slopsmith#129) -->
|
||||
<!-- Filters drawer toggle (feedBack#129) -->
|
||||
<button onclick="toggleLibFilters()" id="btn-lib-filters"
|
||||
class="bg-dark-700 border border-gray-800 hover:border-accent/40 rounded-xl px-4 py-2.5 text-sm text-gray-300 transition flex items-center gap-2"
|
||||
title="Filter by parts, tuning, lyrics">
|
||||
@@ -242,7 +242,7 @@
|
||||
class="bg-dark-700 border border-gray-800 rounded-xl px-4 py-2.5 text-sm text-gray-300 placeholder-gray-600 focus:border-accent/50 focus:ring-1 focus:ring-accent/30 outline-none flex-1 md:w-60 transition">
|
||||
</div>
|
||||
</div>
|
||||
<!-- Active-filter chip row (only visible when filters are set, slopsmith#129) -->
|
||||
<!-- Active-filter chip row (only visible when filters are set, feedBack#129) -->
|
||||
<div id="lib-filter-chips" class="hidden flex flex-wrap gap-2 mb-5"></div>
|
||||
<div id="lib-grid" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
|
||||
<!-- Cards populated by JS -->
|
||||
@@ -252,7 +252,7 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ══ Filters drawer (slopsmith#129/#69/#22) ═════════════════════ -->
|
||||
<!-- ══ Filters drawer (feedBack#129/#69/#22) ═════════════════════ -->
|
||||
<div id="lib-filter-overlay" class="fixed inset-0 bg-black/40 z-40 hidden"
|
||||
onclick="toggleLibFilters(false)"></div>
|
||||
<aside id="lib-filter-drawer"
|
||||
@@ -352,7 +352,7 @@
|
||||
<div class="space-y-10">
|
||||
<!-- App Updates — Velopack auto-update, desktop only. Stays
|
||||
hidden in the plain web app; setupAppUpdates() unhides
|
||||
this block when window.slopsmithDesktop.update exists,
|
||||
this block when window.feedBackDesktop.update exists,
|
||||
and shows a disabled "not available on Linux" fallback
|
||||
when running on Linux. -->
|
||||
<div id="app-updates-block" class="hidden border border-gray-800 rounded-xl bg-dark-800/40 p-5">
|
||||
@@ -378,13 +378,13 @@
|
||||
<p id="app-update-status" class="text-xs text-gray-500 mt-3">Loading updater status…</p>
|
||||
<p id="app-update-linux-note" class="hidden text-xs text-yellow-300 mt-2">
|
||||
Auto-update is not available on Linux —
|
||||
<a href="https://github.com/got-feedback/feedback-desktop/releases" target="_blank" rel="noopener" class="text-accent hover:text-accent-light underline">download new versions from GitHub Releases</a>.
|
||||
<a href="https://github.com/got-feedback/feedBack-desktop/releases" target="_blank" rel="noopener" class="text-accent hover:text-accent-light underline">download new versions from GitHub Releases</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- ── Core Slopsmith settings ─────────────────────────────── -->
|
||||
<!-- ── Core FeedBack settings ─────────────────────────────── -->
|
||||
<section>
|
||||
<h3 class="text-xs font-semibold uppercase tracking-wider text-gray-500 mb-4">Slopsmith</h3>
|
||||
<h3 class="text-xs font-semibold uppercase tracking-wider text-gray-500 mb-4">FeedBack</h3>
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<label class="text-sm font-medium text-gray-400 mb-2 block">Library Folder Path</label>
|
||||
@@ -455,7 +455,7 @@
|
||||
class="flex-1 bg-dark-700 border border-gray-800 rounded-xl px-4 py-2.5 text-sm text-gray-300 placeholder-gray-600 focus:border-accent/50 outline-none">
|
||||
<button onclick="saveSettings()" class="bg-accent hover:bg-accent-light px-6 py-2.5 rounded-xl text-sm font-semibold text-white transition">Save</button>
|
||||
</div>
|
||||
<p class="text-xs text-gray-600 mt-1">Optional. Run <a href="https://github.com/byrongamatos/slopsmith-demucs-server" target="_blank" rel="noopener" class="text-accent hover:text-accent-light underline">slopsmith-demucs-server</a> on a machine with a GPU to offload stem splitting and avoid resource exhaustion on the host running Slopsmith.</p>
|
||||
<p class="text-xs text-gray-600 mt-1">Optional. Run <a href="https://github.com/got-feedBack/feedBack-demucs-server" target="_blank" rel="noopener" class="text-accent hover:text-accent-light underline">feedBack-demucs-server</a> on a machine with a GPU to offload stem splitting and avoid resource exhaustion on the host running FeedBack.</p>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-sm font-medium text-gray-400 mb-2 block">Library</label>
|
||||
@@ -476,7 +476,7 @@
|
||||
</div>
|
||||
<p class="text-xs text-gray-600 mt-1">Export bundles server config, browser preferences, and opted-in plugin data into one JSON file. Import overwrites current settings and reloads.</p>
|
||||
</div>
|
||||
<!-- ── Diagnostics (slopsmith#166) ────────────────────── -->
|
||||
<!-- ── Diagnostics (feedBack#166) ────────────────────── -->
|
||||
<div>
|
||||
<label class="text-sm font-medium text-gray-400 mb-2 block">Diagnostics</label>
|
||||
<div class="grid grid-cols-2 gap-2 mb-3 text-xs text-gray-400">
|
||||
@@ -520,10 +520,10 @@
|
||||
<section>
|
||||
<h3 class="text-xs font-semibold uppercase tracking-wider text-gray-500 mb-4">About</h3>
|
||||
<div class="space-y-2 text-sm text-gray-400">
|
||||
<div>Slopsmith <span id="app-version-about" class="text-gray-500"></span></div>
|
||||
<div>Licensed under <a id="about-license-link" href="https://github.com/got-feedback/feedback/blob/main/LICENSE" target="_blank" rel="noopener" class="text-accent hover:text-accent-light underline">GNU AGPL v3.0</a>.</div>
|
||||
<div><a id="about-source-link" href="https://github.com/got-feedback/feedback" target="_blank" rel="noopener" class="text-accent hover:text-accent-light underline">Source code repository</a></div>
|
||||
<p class="text-xs text-gray-600 mt-2">Slopsmith is free software. You can redistribute it and modify it under the terms of the AGPL. If you run a modified version that interacts with users over a network, you must make the modified source available to those users.</p>
|
||||
<div>FeedBack <span id="app-version-about" class="text-gray-500"></span></div>
|
||||
<div>Licensed under <a id="about-license-link" href="https://github.com/got-feedback/feedBack/blob/main/LICENSE" target="_blank" rel="noopener" class="text-accent hover:text-accent-light underline">GNU AGPL v3.0</a>.</div>
|
||||
<div><a id="about-source-link" href="https://github.com/got-feedback/feedBack" target="_blank" rel="noopener" class="text-accent hover:text-accent-light underline">Source code repository</a></div>
|
||||
<p class="text-xs text-gray-600 mt-2">FeedBack is free software. You can redistribute it and modify it under the terms of the AGPL. If you run a modified version that interacts with users over a network, you must make the modified source available to those users.</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -701,7 +701,7 @@
|
||||
<select id="viz-picker" onchange="setViz(this.value)" class="v3-pop-select" aria-labelledby="viz-picker-label" title="Visualization">
|
||||
<option value="auto">Auto (match arrangement)</option>
|
||||
<option value="default">Classic 2D Highway</option>
|
||||
<!-- Additional entries populated on load from /api/plugins (slopsmith#36).
|
||||
<!-- Additional entries populated on load from /api/plugins (feedBack#36).
|
||||
The bundled 3D Highway plugin (plugins/highway_3d/) registers as
|
||||
`highway_3d` and is the default on fresh installs — see
|
||||
_populateVizPicker() in app.js. -->
|
||||
@@ -762,7 +762,7 @@
|
||||
<div id="v3-rail-pop-mixer" class="v3-rail-pop hidden" role="group" aria-label="Mixer">
|
||||
<div id="mixer-control">
|
||||
<div id="mixer-anchor" class="relative">
|
||||
<button id="btn-mixer" type="button" onclick="window.slopsmith.audio.toggleMixer()" class="v3-pop-btn" aria-haspopup="true" aria-expanded="false" aria-controls="mixer-popover" title="Audio mixer">Mixer ▾</button>
|
||||
<button id="btn-mixer" type="button" onclick="window.feedBack.audio.toggleMixer()" class="v3-pop-btn" aria-haspopup="true" aria-expanded="false" aria-controls="mixer-popover" title="Audio mixer">Mixer ▾</button>
|
||||
<div id="mixer-popover" class="hidden absolute left-0 top-full mt-2 z-50 bg-dark-700 border border-gray-800 rounded-xl shadow-xl" role="group" aria-label="Audio mixer"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -858,7 +858,7 @@
|
||||
<script src="/static/tour-engine.js"></script>
|
||||
<!-- fee[dB]ack v0.3.0 shell: brand helper, then the shell (sidebar/topbar/
|
||||
routing). Loaded after app.js/audio-mixer so window.showScreen and
|
||||
window.slopsmith(.audio) exist; dashboard.js is filled in prompt 13. -->
|
||||
window.feedBack(.audio) exist; dashboard.js is filled in prompt 13. -->
|
||||
<script src="/static/v3/brand.js"></script>
|
||||
<script src="/static/v3/shell.js"></script>
|
||||
<!-- Progression (spec 010): theme-core before profile.js so the equipped
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
const sm = window.slopsmith;
|
||||
const sm = window.feedBack;
|
||||
const PLUGIN_ID = 'tutorials';
|
||||
const API = '/api/plugins/' + PLUGIN_ID;
|
||||
const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => (
|
||||
@@ -228,16 +228,16 @@
|
||||
// the first navigation that leaves the launch flow (any screen other
|
||||
// than the tutorials waypoint or the player that consumes it).
|
||||
try {
|
||||
if (window.slopsmith && typeof window.slopsmith.setReturnScreen === 'function') {
|
||||
window.slopsmith.setReturnScreen('v3-lessons');
|
||||
if (window.feedBack && typeof window.feedBack.setReturnScreen === 'function') {
|
||||
window.feedBack.setReturnScreen('v3-lessons');
|
||||
if (sm && typeof sm.on === 'function' && typeof sm.off === 'function') {
|
||||
const clearStale = (e) => {
|
||||
const id = e && e.detail && e.detail.id;
|
||||
if (id === 'plugin-tutorials') return; // expected waypoint — keep waiting
|
||||
// 'player' means playSong already consumed the override;
|
||||
// anything else means the launch was abandoned.
|
||||
if (id !== 'player' && window.slopsmith._nextReturnScreen === 'v3-lessons') {
|
||||
window.slopsmith.setReturnScreen(null);
|
||||
if (id !== 'player' && window.feedBack._nextReturnScreen === 'v3-lessons') {
|
||||
window.feedBack.setReturnScreen(null);
|
||||
}
|
||||
sm.off('screen:changed', clearStale);
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
(function (root) {
|
||||
'use strict';
|
||||
|
||||
const KEY = 'slopsmith-live-guitar-tone-source';
|
||||
const KEY = 'feedBack-live-guitar-tone-source';
|
||||
|
||||
const SOURCES = Object.freeze({
|
||||
INTERNAL: 'internal',
|
||||
|
||||
@@ -240,7 +240,7 @@
|
||||
|
||||
if (typeof document !== 'undefined') {
|
||||
const boot = () => {
|
||||
const sm = root && root.slopsmith;
|
||||
const sm = root && root.feedBack;
|
||||
if (sm) bindRuntime(sm);
|
||||
};
|
||||
if (document.readyState === 'loading') {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Vanilla JS, no framework (constitution P-II). Animation + accent colors are
|
||||
* inline styles so the prebuilt Tailwind stylesheet needs no new utilities.
|
||||
* Self-contained: it subscribes through window.slopsmith.on, degrading to a
|
||||
* Self-contained: it subscribes through window.feedBack.on, degrading to a
|
||||
* no-op when the bus or DOM isn't present (SSR/headless safety, P15).
|
||||
*/
|
||||
(function () {
|
||||
@@ -95,7 +95,7 @@
|
||||
window.fbNotify = { show: show, clear: clear };
|
||||
|
||||
// ── Progression wiring ────────────────────────────────────────────────────
|
||||
const sm = window.slopsmith;
|
||||
const sm = window.feedBack;
|
||||
if (!sm || typeof sm.on !== 'function') return; // no bus → toasts API still usable
|
||||
|
||||
const periodLabel = (p) => (p === 'weekly' ? 'Weekly Quest' : p === 'daily' ? 'Daily Quest' : 'Quest');
|
||||
@@ -106,7 +106,7 @@
|
||||
};
|
||||
|
||||
// The bus delivers a CustomEvent; the progression payload is e.detail
|
||||
// (matches every other window.slopsmith.on consumer, e.g. progress.js).
|
||||
// (matches every other window.feedBack.on consumer, e.g. progress.js).
|
||||
sm.on('progression:quest-progressed', (e) => {
|
||||
const q = e && e.detail;
|
||||
if (!q) return;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* fee[dB]ack v0.3.0 — first-run home tour.
|
||||
*
|
||||
* Registers a spotlight tour over the home-page cards with the shared tour
|
||||
* engine (window.slopsmithTour / Shepherd) and auto-runs it once, the first
|
||||
* engine (window.feedBackTour / Shepherd) and auto-runs it once, the first
|
||||
* time the user lands on the home page after completing onboarding. It stays
|
||||
* replayable forever from the per-screen "?" tour menu (registered with
|
||||
* screens: ['v3-home']).
|
||||
@@ -72,7 +72,7 @@
|
||||
}
|
||||
|
||||
function register() {
|
||||
var t = window.slopsmithTour;
|
||||
var t = window.feedBackTour;
|
||||
if (!t || typeof t.register !== 'function') return false;
|
||||
t.register(TOUR_ID, {
|
||||
name: 'Welcome tour', // label in the "?" tour menu
|
||||
@@ -88,7 +88,7 @@
|
||||
// honour the engine's own seen/dismissed state so it never repeats and a
|
||||
// dismissal isn't nagged. Stays replayable from the "?" menu either way.
|
||||
function startFirstRun() {
|
||||
var t = window.slopsmithTour;
|
||||
var t = window.feedBackTour;
|
||||
if (!t || typeof t.start !== 'function') return;
|
||||
try {
|
||||
if (t.hasSeen(TOUR_ID) || t.hasDismissed(TOUR_ID)) return;
|
||||
@@ -118,12 +118,12 @@
|
||||
// can't start the tour immediately — there is no home screen to spotlight
|
||||
// yet. Arm it to run the first time the user lands back on v3-home.
|
||||
function armPendingFirstRun() {
|
||||
var t = window.slopsmithTour;
|
||||
var t = window.feedBackTour;
|
||||
if (!t || typeof t.start !== 'function') return;
|
||||
try {
|
||||
if (t.hasSeen(TOUR_ID) || t.hasDismissed(TOUR_ID)) return;
|
||||
} catch (e) { /* private mode — fall through */ }
|
||||
var sm = window.slopsmith;
|
||||
var sm = window.feedBack;
|
||||
if (!sm || typeof sm.on !== 'function') return;
|
||||
var onScreen = function (e) {
|
||||
if (!(e && e.detail && e.detail.id === 'v3-home')) return;
|
||||
@@ -135,7 +135,7 @@
|
||||
|
||||
window.v3OnboardingTour = { startFirstRun: startFirstRun, armPendingFirstRun: armPendingFirstRun };
|
||||
|
||||
// tour-engine.js assigns window.slopsmithTour at script-eval time, so if it
|
||||
// tour-engine.js assigns window.feedBackTour at script-eval time, so if it
|
||||
// is loaded before us register() succeeds immediately; otherwise retry once
|
||||
// the DOM (and the engine) are ready.
|
||||
if (!register()) {
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
// the pedal photos measure ~57.5% down), so they stay aligned at any size.
|
||||
var JACK_FRAC = 0.575;
|
||||
|
||||
var sm = window.slopsmith;
|
||||
var sm = window.feedBack;
|
||||
|
||||
// ---- pure geometry helpers (exported for tests) -----------------------
|
||||
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
let openPop = null; // { btn, pop }
|
||||
|
||||
// ── v3 UI signal + plugin-control slot API ───────────────────────────────
|
||||
// Lets plugins detect v3 (window.slopsmith.uiVersion === 'v3') and mount
|
||||
// Lets plugins detect v3 (window.feedBack.uiVersion === 'v3') and mount
|
||||
// controls into a stable slot instead of the auto-hiding transport.
|
||||
window.slopsmith = window.slopsmith || {};
|
||||
window.slopsmith.uiVersion = 'v3';
|
||||
window.slopsmith.ui = window.slopsmith.ui || {};
|
||||
window.slopsmith.ui.version = 'v3';
|
||||
window.slopsmith.ui.playerControlSlot = function () { return $('v3-plugin-controls-slot'); };
|
||||
window.feedBack = window.feedBack || {};
|
||||
window.feedBack.uiVersion = 'v3';
|
||||
window.feedBack.ui = window.feedBack.ui || {};
|
||||
window.feedBack.ui.version = 'v3';
|
||||
window.feedBack.ui.playerControlSlot = function () { return $('v3-plugin-controls-slot'); };
|
||||
|
||||
// ── Plugin-control re-homing shim ────────────────────────────────────────
|
||||
// Legacy plugins inject controls into #player-controls (now an auto-hiding
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
const sm = window.slopsmith;
|
||||
const sm = window.feedBack;
|
||||
|
||||
const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => (
|
||||
{ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
var sm = window.slopsmith;
|
||||
var sm = window.feedBack;
|
||||
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
|
||||
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; }); };
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
return '<div class="v3-pedal' + (off ? ' v3-pedal-off' : '') + '" data-id="' + esc(p.id) + '" tabindex="0" role="button" ' +
|
||||
'aria-label="' + esc((p.name || p.id) + action) + '" title="' + esc(tip) + '"' + style + '>' +
|
||||
'<span class="v3-pedal-glow" aria-hidden="true"></span>' +
|
||||
(p.bundled ? '<span class="v3-pedal-bundled" title="Ships with Slopsmith core">core</span>' : '') +
|
||||
(p.bundled ? '<span class="v3-pedal-bundled" title="Ships with FeedBack core">core</span>' : '') +
|
||||
'<span class="v3-pedal-offbadge" aria-hidden="true">off</span>' +
|
||||
'<div class="v3-pedal-label">' +
|
||||
'<img class="v3-pedal-thumb" alt="" loading="lazy" src="' + esc(thumbUrl(p)) + '">' +
|
||||
|
||||
@@ -206,7 +206,7 @@
|
||||
// public global is set at the end of the plugin's screen.js, after the
|
||||
// owner is registered, so it is a reliable readiness signal.
|
||||
function waitForInputSetup(timeoutMs) {
|
||||
const ready = () => !!(window.slopsmithInputSetup && typeof window.slopsmithInputSetup.launch === 'function');
|
||||
const ready = () => !!(window.feedBackInputSetup && typeof window.feedBackInputSetup.launch === 'function');
|
||||
return new Promise((resolve) => {
|
||||
if (ready()) { resolve(true); return; }
|
||||
const t0 = Date.now();
|
||||
@@ -222,9 +222,9 @@
|
||||
if (!instruments.length) return;
|
||||
// Don't let a plugin-load race skip the mandatory input-setup step.
|
||||
if (!(await waitForInputSetup(8000))) return;
|
||||
const caps = window.slopsmith && window.slopsmith.capabilities;
|
||||
const caps = window.feedBack && window.feedBack.capabilities;
|
||||
if (!caps || typeof caps.command !== 'function') {
|
||||
try { await window.slopsmithInputSetup.launch(instruments); } catch (e) { /* proceed */ }
|
||||
try { await window.feedBackInputSetup.launch(instruments); } catch (e) { /* proceed */ }
|
||||
return;
|
||||
}
|
||||
await new Promise((resolve) => {
|
||||
@@ -459,7 +459,7 @@
|
||||
songDirEl.addEventListener('input', () => { songDir = songDirEl.value.trim(); refreshSubmit(); });
|
||||
}
|
||||
// Native folder picker on desktop; web users type/paste the path.
|
||||
const _desktop = window.slopsmithDesktop;
|
||||
const _desktop = window.feedBackDesktop;
|
||||
if (songDirBrowse && _desktop && typeof _desktop.pickDirectory === 'function') {
|
||||
songDirBrowse.classList.remove('hidden');
|
||||
songDirBrowse.addEventListener('click', async () => {
|
||||
@@ -510,7 +510,7 @@
|
||||
}
|
||||
renderBadge();
|
||||
renderProfileScreen();
|
||||
if (window.slopsmith && window.slopsmith.emit) window.slopsmith.emit('v3:profile-updated', _profile);
|
||||
if (window.feedBack && window.feedBack.emit) window.feedBack.emit('v3:profile-updated', _profile);
|
||||
// First-run only: after a genuine onboarding completion (not a
|
||||
// profile edit), kick off the one-time home tour — but NOT when we're
|
||||
// about to launch the diagnostic ("Play it now"), which navigates to
|
||||
@@ -627,9 +627,9 @@
|
||||
renderProfileScreen();
|
||||
// Rank / dB / frames re-render whenever progression state or equipped
|
||||
// cosmetics move (progression-core.js / theme-core.js own the fetches).
|
||||
if (window.slopsmith && typeof window.slopsmith.on === 'function') {
|
||||
window.slopsmith.on('progression:updated', () => { renderBadge(); renderProfileScreen(); });
|
||||
window.slopsmith.on('v3:cosmetics-applied', () => { renderBadge(); renderProfileScreen(); });
|
||||
if (window.feedBack && typeof window.feedBack.on === 'function') {
|
||||
window.feedBack.on('progression:updated', () => { renderBadge(); renderProfileScreen(); });
|
||||
window.feedBack.on('v3:cosmetics-applied', () => { renderBadge(); renderProfileScreen(); });
|
||||
}
|
||||
}
|
||||
if (document.readyState === 'loading') {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
const sm = window.slopsmith;
|
||||
const sm = window.feedBack;
|
||||
const SCREEN_ID = 'v3-progress';
|
||||
|
||||
const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => (
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* (buy/equip require authorization:'user-action')
|
||||
*
|
||||
* Lifecycle events are emitted on the capability surface and mirrored on
|
||||
* window.slopsmith as `progression:*` for non-capability consumers:
|
||||
* window.feedBack as `progression:*` for non-capability consumers:
|
||||
* challenge-completed, quest-completed, quest-progressed, path-level-up,
|
||||
* path-progressed, rank-changed, db-changed, calibration-completed,
|
||||
* cosmetic-equipped (+ progression:updated whenever fresh state lands).
|
||||
@@ -24,7 +24,7 @@
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
const sm = window.slopsmith = window.slopsmith || {};
|
||||
const sm = window.feedBack = window.feedBack || {};
|
||||
|
||||
let _state = null; // last /api/progression payload
|
||||
let _fetching = null; // in-flight refresh (coalesced)
|
||||
@@ -151,7 +151,7 @@
|
||||
if (!diagnostics || typeof diagnostics.contribute !== 'function' || !_state) return;
|
||||
try {
|
||||
diagnostics.contribute('progression', {
|
||||
schema: 'slopsmith.progression.diag.v1',
|
||||
schema: 'feedBack.progression.diag.v1',
|
||||
mastery_rank: _state.mastery_rank,
|
||||
calibration_status: (_state.onboarding || {}).calibration_status,
|
||||
paths: (_state.paths || []).map((p) => ({ id: p.id, level: p.level, max_level: p.max_level })),
|
||||
|
||||
+3
-3
@@ -287,7 +287,7 @@
|
||||
|
||||
// ── showScreen wrapper (idempotent rehydration — design/05 §Rehydration) ─
|
||||
function installShowScreenHook() {
|
||||
const hooks = window.__slopsmithV3ShellHooks || (window.__slopsmithV3ShellHooks = {});
|
||||
const hooks = window.__feedBackV3ShellHooks || (window.__feedBackV3ShellHooks = {});
|
||||
hooks.syncActive = syncActive; // always point at the latest impl
|
||||
if (hooks.installed) return;
|
||||
hooks.installed = true;
|
||||
@@ -359,8 +359,8 @@
|
||||
// The "Welcome back, {name}!" title needs the profile, which loads
|
||||
// async — refresh once it's in (and whenever it changes).
|
||||
function refreshHomeTitle() { if (currentScreenId() === 'v3-home') setTopbarTitle(titleFor('v3-home')); }
|
||||
if (window.slopsmith && typeof window.slopsmith.on === 'function') {
|
||||
window.slopsmith.on('v3:profile-updated', refreshHomeTitle);
|
||||
if (window.feedBack && typeof window.feedBack.on === 'function') {
|
||||
window.feedBack.on('v3:profile-updated', refreshHomeTitle);
|
||||
}
|
||||
setTimeout(refreshHomeTitle, 700);
|
||||
}
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
const sm = window.slopsmith;
|
||||
const sm = window.feedBack;
|
||||
const SCREEN_ID = 'v3-shop';
|
||||
|
||||
let _data = null; // last GET /api/shop payload
|
||||
|
||||
+3
-3
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
const sm = window.slopsmith;
|
||||
const sm = window.feedBack;
|
||||
const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => (
|
||||
{ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
||||
const enc = encodeURIComponent;
|
||||
@@ -266,7 +266,7 @@
|
||||
async function jget(url) { try { const r = await fetch(url); return r.ok ? r.json() : null; } catch (e) { return null; } }
|
||||
|
||||
// ── Provider-aware song helpers ────────────────────────────────────────
|
||||
// Remote library providers (slopsmith-plugin-remote-library-*) expose songs
|
||||
// Remote library providers (feedBack-plugin-remote-library-*) expose songs
|
||||
// by provider-owned id with their own art/sync/play flow. Reuse the legacy
|
||||
// app.js globals (the shared engine) so v3 behaves identically for remote
|
||||
// providers instead of assuming every row is a local file. All degrade to
|
||||
@@ -835,7 +835,7 @@
|
||||
try {
|
||||
const lp = sm && sm.libraryProviders;
|
||||
// refresh() re-fetches /api/library/providers so REMOTE providers
|
||||
// (registered by slopsmith-plugin-remote-library-*) appear — list()
|
||||
// (registered by feedBack-plugin-remote-library-*) appear — list()
|
||||
// returns only the capability's initial local-only snapshot.
|
||||
const fn = lp && (typeof lp.refresh === 'function' ? lp.refresh : (typeof lp.list === 'function' ? lp.list : null));
|
||||
if (fn) {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
*
|
||||
* Bridges the highway note-detection scorer to the core song_stats store
|
||||
* (POST /api/stats). The scorer lives in the OPTIONAL external plugin
|
||||
* slopsmith-plugin-notedetect, which emits `note:hit` / `note:miss` per note
|
||||
* on window.slopsmith — note-detection is a DEFERRED capability domain, so we
|
||||
* feedBack-plugin-notedetect, which emits `note:hit` / `note:miss` per note
|
||||
* on window.feedBack — note-detection is a DEFERRED capability domain, so we
|
||||
* use those legacy events directly (design/05-capability-pipelines.md). If the
|
||||
* plugin isn't installed, no note events fire and nothing is recorded
|
||||
* (graceful degrade — the dashboard simply shows no accuracy).
|
||||
@@ -21,7 +21,7 @@
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
const sm = window.slopsmith;
|
||||
const sm = window.feedBack;
|
||||
if (!sm || typeof sm.on !== 'function') return;
|
||||
|
||||
let cur = null; // active session
|
||||
|
||||
@@ -116,8 +116,8 @@
|
||||
if (r.ok) {
|
||||
const profile = await r.json();
|
||||
applyCosmetics(profile.cosmetics);
|
||||
if (window.slopsmith && typeof window.slopsmith.emit === 'function') {
|
||||
window.slopsmith.emit('v3:cosmetics-applied', profile.cosmetics || {});
|
||||
if (window.feedBack && typeof window.feedBack.emit === 'function') {
|
||||
window.feedBack.emit('v3:cosmetics-applied', profile.cosmetics || {});
|
||||
}
|
||||
}
|
||||
} catch (e) { /* offline — keep current look */ }
|
||||
@@ -134,7 +134,7 @@
|
||||
refresh();
|
||||
// Re-apply when an equip/unequip happens anywhere (shop screen, capability
|
||||
// command from a plugin).
|
||||
if (window.slopsmith && typeof window.slopsmith.on === 'function') {
|
||||
window.slopsmith.on('progression:cosmetic-equipped', refresh);
|
||||
if (window.feedBack && typeof window.feedBack.on === 'function') {
|
||||
window.feedBack.on('progression:cosmetic-equipped', refresh);
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
(function (root) {
|
||||
'use strict';
|
||||
|
||||
const KEY = 'slopsmith-venue-mood-fx';
|
||||
const MOTION_KEY = 'slopsmith-venue-motion';
|
||||
const KEY = 'feedBack-venue-mood-fx';
|
||||
const MOTION_KEY = 'feedBack-venue-motion';
|
||||
const SETTINGS = Object.freeze({ OFF: 'off', SUBTLE: 'subtle', FULL: 'full' });
|
||||
const DEFAULT = SETTINGS.SUBTLE;
|
||||
const MOTION_DEFAULT = SETTINGS.SUBTLE;
|
||||
@@ -508,7 +508,7 @@
|
||||
|
||||
if (typeof document !== 'undefined') {
|
||||
const boot = () => {
|
||||
const sm = root && root.slopsmith;
|
||||
const sm = root && root.feedBack;
|
||||
if (sm) bindRuntime(sm);
|
||||
};
|
||||
if (document.readyState === 'loading') {
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
? root.highway.getSongInfo()
|
||||
: null;
|
||||
if (si && si.arrangement) return si.arrangement;
|
||||
const cs = root.slopsmith && root.slopsmith.currentSong;
|
||||
const cs = root.feedBack && root.feedBack.currentSong;
|
||||
if (cs && cs.arrangement) return cs.arrangement;
|
||||
if (cs && cs.arrangementSmartName) return cs.arrangementSmartName;
|
||||
} catch (_) { /* visual-only */ }
|
||||
@@ -166,7 +166,7 @@
|
||||
function bindRuntime() {
|
||||
if (_bound) return;
|
||||
_bound = true;
|
||||
const sm = root && root.slopsmith;
|
||||
const sm = root && root.feedBack;
|
||||
if (sm && typeof sm.on === 'function') {
|
||||
sm.on('v3:live-performance-state', onPerformanceState);
|
||||
sm.on('song:loaded', () => {
|
||||
|
||||
Reference in New Issue
Block a user