mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-09-11 02:14:29 +00:00
e9d95ad1901e48f1a8a28db4b3bb7d45cac525a3
* v3 library: multi-chart work grouping engine + work-charts API — P5a/P5b
Charts of the same song (same normalized artist+title) now GROUP under a
computed work_key, with a materialized representative filter so the grid
can collapse them without breaking keyset paging:
- work_key = normalize(artist+title) (diacritics/punct/case folded,
leading "The" folded on artist); resolves the effective artist via the
artist_alias table when present (feature-detected, no hard dep).
- Sparse, never-purged-on-rescan tables: chart_group_pref(work_key,
preferred_filename) + chart_group_split(filename, split_key); purged
only by the explicit per-song delete.
- Materialized work_display(filename, work_key, effective_work_key,
is_group_representative, group_size) read-model: lazy rebuild via a
dirty flag set on put/delete; set_chart_preferred does an incremental
re-flip (no full rebuild). Auto-pick representative = most
arrangements -> most plays -> newest -> filename; a user pref wins and
degrades to auto-pick if its file disappears.
- group=1 on query_page/query_stats = one extra representative
predicate applied identically to page + total + sort_letters, so the
keyset cursor (sort_value, filename) stays a valid total order and
counts works, not charts. Grouped rows carry chart_count + work_key.
- Charts API: GET /api/work/{work_key}/charts (members + which is the
keeper, your pick vs auto), PUT/DELETE .../preferred, and
POST /api/chart/{filename}/split + /unsplit (under /api/chart so the
DELETE /api/song catch-all can't shadow them).
Tests: 15 grouping-engine + 7 charts-API tests, including grouped
keyset pagination (no skip/dupe across pages).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nm7tHs1Yvjjtnnu4nzJgdN
* v3 library: grouped grid card + persistent "N charts" chip — P5c
Flip the v3 grid to the grouped library (group=1 on /api/library and the
rail's /api/library/stats fetch): one card per song, showing the
representative (preferred/auto-pick) chart. group rides page, total and
sort_letters identically so the A-Z rail's cumulative-seek math and the
virtualized sizer stay consistent, counting works not charts; the keyset
cursor chains with group on every page.
- New groupingActive() helper, default ON per the design; the persisted
per-view toggle (P5e) lands there. Only the local provider implements
group=; smart collections and remote providers ignore it and stay
flat, so it is safe to send unconditionally.
- chartsChipHtml(): a "flag N charts" chip rendered ONLY when
chart_count >= 2 - single-chart cards emit byte-identical markup.
First in the fixed-height chip row + shrink-0 so it never clips and
card height is unchanged.
- Chip click = feature-detected window.__fbOpenChartsDrawer (the Charts
drawer arrives in P5d); until then a no-op. Plain-click / play / the
arrangement chips are untouched and play the representative.
- The library-home repertoire meter's stats fetch deliberately stays
ungrouped: its mastered numerator counts chart filenames, so a works
denominator could exceed 100% - reconciling that is P5e's
mastery-anchor work. The tree view stays flat (query_artists has no
grouping; its opener is wired in P5d).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nm7tHs1Yvjjtnnu4nzJgdN
* v3 library: Charts drawer + openers — P5d
The single deep-management surface for a work's charts (design UX-2/3):
a body-appended slide-in drawer (filter-drawer idiom) listing every
chart of the work as a radiogroup — the checked row is the keeper the
grid card plays.
- Rows show format / tuning / arrangements / year / your accuracy (or
"not played") plus the pack filename, usually the only human-readable
distinguisher between duplicate charts. Keeper is labeled
"Preferred (auto)" vs "Preferred - your pick".
- Row click (or Enter/Space) = one-tap Set-preferred; "Reset to auto
pick" appears when the keeper is an explicit pick. Writes go through
the work-charts API and the drawer re-renders from the response; the
grid re-fetches in place since the representative may have flipped.
- Per-row Play (plays that exact chart) and Add-to-playlist (the picker
is z-[200], layering over the z-50 drawer).
- a11y: Tab focus-trap, Escape closes, ArrowUp/Down move focus between
rows (focus only - arrow-select would fire a preferred write per
keystroke), focus restored to the opener on close.
- Openers: the "N charts" chip opens the drawer directly; the card's
overflow menu gains "Charts (N)..." and "Play version >" (expands
inline; picking one plays it as a one-off - the keeper/headline does
not move). Tree rows ride the ungrouped artists endpoint, so the menu
resolves their work lazily via the new GET /api/chart/{fn}/work
({work_key, chart_count}) and slots a "Charts (N)..." entry in when
versions exist. A window.__fbOpenChartsDrawer global lets other views
open the drawer. Right-click is deferred: the open native card
context-menu PR should host that entry once both merge.
- tailwind.min.css rebuilt: carries the new utility classes from this
and the previous commit (the grouped-card chip tint was missing).
Split keys contain '#', so clients MUST URL-encode work_key in paths
(the v3 client does; a test documents the round-trip). 4 new endpoint
tests; 26/26 grouping+charts tests green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nm7tHs1Yvjjtnnu4nzJgdN
* v3 library: group toggle, split UI, the filter law + mastery-anchor rules — P5e
Completes the multi-chart grouping slice (design 7.1):
- Filter law under group=1: work-identity (artist/album/search) and
practice-state (favorites/mastery/tags/difficulty) predicates stay on
the representative row, while CHART-INTRINSIC predicates (format/
arrangements/stems/lyrics/tuning) now match if ANY member of the work
does - a song you own in Drop D is no longer hidden because your
preferred chart is E Standard. Intrinsic clauses moved to an
alias-aware builder and re-applied as a member EXISTS; identical in
query_page and query_stats so counts and the A-Z rail stay in
lockstep. A pure predicate - keyset paging is untouched (tested).
- Display-chart switch: when the representative itself doesn't match,
the row carries a display_chart override (the matching member). The
row stays the representative's - swapping rows wholesale would break
the (sort_value, filename) cursor - and the card renders/plays the
member while the accuracy badge and heart stay anchored on the
preferred chart.
- Mastery sort aggregates MAX across the group ("a song surfaces on any
chart you've touched"); OFFSET-paged, so cursor-safe. The
Recently-Added aggregate is deliberately deferred: mtime IS a keyset
sort, so its aggregate would need materializing into work_display.
- History-sticky auto-pick: most-played -> most-complete -> newest.
A newer/"more complete" import can't silently take the pick from the
chart your reps accrued on, and a one-off try of an alternate can't
out-rank a practiced incumbent; all-unplayed groups still pick by
completeness.
- Persisted "One card per song" toggle in the filter drawer (default
ON; OFF = one card per chart). A view mode: never counted in the
filter badge, never saved into collection rules, local provider only.
- Split escape hatch: "Split out" per drawer row gives a chart its own
card; the split card's overflow menu offers "Rejoin other versions"
(rows and the chart-work lookup now carry is_split).
- Mastery-anchor heads-up: after set-preferred the drawer shows a
one-line ambient note that practice history stays with each chart
(no toast - hearing-safe).
10 new filter-law tests; 38/38 grouping tests green. tailwind.min.css
rebuilt for the new utility classes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nm7tHs1Yvjjtnnu4nzJgdN
* fix(v3): work-grouping — escape Charts-drawer meta (XSS), keep non-Latin titles distinct, guard mid-rebuild reads (PR #702 review)
- XSS: esc() the composed `meta` string in _chartRowHtml (arrangement/tuning
names come from untrusted feedpak metadata) before innerHTML; acc stays HTML.
- Non-Latin titles: _norm_token falls back to raw lowercased whitespace-collapsed
text when the NFKD+strip fold yields "" (CJK/Cyrillic/Greek/Arabic), so distinct
non-Latin titles keep distinct _work_key values instead of collapsing into one
bogus work. Latin names still hit the folded branch — behavior unchanged.
- Mid-rebuild reads: wrap the grouped representative SELECT in query_page and
query_stats under self._lock (nullcontext when ungrouped, so lazy reads stay
lock-free) so a reader can't observe work_display between rebuild_work_display's
DELETE and INSERT/commit. _ensure_work_display stays OUTSIDE the lock — it
self-locks the rebuild and self._lock is non-reentrant — so only the SELECT is
guarded (rebuild fully completes before the guarded SELECT runs).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: byrongamatos <xasiklas@gmail.com>
v3 library: multi-chart work grouping, complete (engine + API + card + drawer + toggle/split/filter-law) — P5a–P5e (#702)
v3 library: multi-chart work grouping, complete (engine + API + card + drawer + toggle/split/filter-law) — P5a–P5e (#702)
v3 library: multi-chart work grouping, complete (engine + API + card + drawer + toggle/split/filter-law) — P5a–P5e (#702)
fee[dB]ack
Plugins
| Plugin | Description | Install |
|---|---|---|
| Create from Tab | Search Ultimate Guitar for GP tabs and convert to playable songs | git clone ...feedBack-plugin-ug.git ultimate_guitar |
| Import Tab | Drag and drop Guitar Pro files to create songs | git clone ...feedBack-plugin-tabimport.git tab_import |
| Practice Journal | Auto-track practice time, speed, loops. Dashboard with charts | git clone ...feedBack-plugin-practice.git practice_journal |
| Setlist Builder | Create ordered playlists with sequential playback | git clone ...feedBack-plugin-setlist.git setlist |
| Metronome | Audible click and visual beat flash synced to song tempo | git clone ...feedBack-plugin-metronome.git metronome |
| Tone Player | View amp/pedal/cab signal chains with gear artwork | git clone ...feedBack-plugin-tones.git tones |
| Fretboard View | Live fretboard overlay showing active notes in real-time | git clone ...feedBack-plugin-fretboard.git fretboard |
| Tab View | Scrolling guitar tablature notation via alphaTab | git clone ...feedBack-plugin-tabview.git tab_view |
| MIDI Amp Control | Auto-switch amp/modeler presets via MIDI on tone changes | git clone ...feedBack-plugin-midi.git midi_amp |
| Section Map | Color-coded song structure minimap with clickable navigation | git clone ...feedBack-plugin-sectionmap.git section_map |
| Arrangement Editor | DAW-like visual editor for creating and editing song note charts | git clone ...feedBack-plugin-editor.git editor |
| MIDI Capo | MIDI capo control for real-time transposition | git clone ...slopsmith-plugin-midi-capo.git midi_capo |
| Note Detection | Real-time pitch detection and scoring against highway notes | git clone ...feedBack-plugin-notedetect.git note_detect |
| Find More | Search for more songs by the same artist | git clone ...slopsmith-plugin-find-more.git find_more |
| Piano Highway | Scrolling piano/keyboard view for Keys arrangements with MIDI input | git clone ...feedBack-plugin-piano.git piano |
| Studio | Collaborative band recording and multi-track mixing | git clone ...feedBack-plugin-studio.git studio |
| Drum Highway | Lane-based drum highway with MIDI drum pad input and built-in sounds | git clone ...feedBack-plugin-drums.git drums |
| Invert Highway | Flip the highway note direction | git clone ...slopsmith-plugin-invert-highway.git invert_highway |
| Jumping Tab | Yousician-style 2D horizontal tab with trajectory arcs and hopping ball | git clone ...slopsmith-plugin-jumpingtab.git jumpingtab |
| Step Mode | Step-by-step practice mode — highway freezes at each note until played (via Note Detection) or Space | git clone ...feedBack-plugin-stepmode.git step_mode |
| Lyrics Sync | Generate synced LRC lyrics from text + vocals stem via Whisper alignment | git clone ...feedBack-plugin-lyrics-sync.git lyrics_sync |
| Lyrics Karaoke | Per-syllable karaoke pitch ribbon for sloppak songs (Whisper alignment + librosa pYIN) | git clone ...feedBack-plugin-lyrics-karaoke.git lyrics_karaoke |
| NAM Tone Engine | In-browser amp modeling with NAM WASM, cabinet IRs, tone auto-switching | git clone ...feedBack-plugin-nam-tone.git nam_tone |
| Guitar Theory Lab | Explore scales, chords, intervals, tunings, and voicings on a fully interactive fretboard | git clone ...slopsmith-plugin-guitar-theory.git guitar-theory-lab |
| Themes | Offers several basic recolorings of the interface | git clone ...slopsmith-plugin-themes.git themes |
| Update Manager | Installs, updates, and uninstalls other plugins and the feedBack core itself | git clone ...slopsmith-update-manager.git update_manager |
| Simplify Chords | Changes complex chords on the note highway to simpler ones. Inspired by Ultimate Guitar's Simplify button. | git clone ...slopsmith-plugin-simplify-chords.git simplify-chords |
| Key Bindings | Highway key bindings for keyboard and TV remote | git clone ...slopsmith-plugin-key-bindings.git key_bindings |
| Virtuoso | Practice studio for guitar & bass — scale, technique, and rhythm drills, timed workouts, and jam backing that teach skills you take off the screen. | git clone ...feedBack-plugin-virtuoso.git virtuoso |
| Audio Preview | Quick audio previews from library cards with configurable start time, volume, and duration | git clone ...slopsmith-plugin-audio-preview.git audio_preview |
| Song Mastery | Auto-adjusts difficulty based on your rolling note accuracy and saves the slider position per song | git clone ...slopsmith-plugin-song-mastery.git song_mastery |
| Mobile Note Highway | Touch-optimized player with collapsible controls, highway gestures, and device-adaptive layouts for phones and tablets | git clone ...slopsmith-plugin-mobile-note-highway.git mobile_note_highway |
Install any plugin by cloning it into your plugins/ directory and restarting:
cd plugins
git clone https://github.com/got-feedback/feedBack-plugin-ug.git ultimate_guitar
docker compose restart
Languages
JavaScript
56.4%
Python
37.1%
HTML
3.2%
CSS
1.2%
TypeScript
1.1%
Other
1%