Skip to content

feat(milkdrop): favourites, tags and search by author - #605

Merged
CaYatur merged 2 commits into
mainfrom
milkdrop/library-576
Sep 22, 2026
Merged

CaYatur merged 2 commits into
mainfrom
milkdrop/library-576

Conversation

@CaYatur

@CaYatur CaYatur commented Sep 22, 2026 •

Copy link
Copy Markdown
Owner

Search matched the name only. Presets can now be starred and tagged, searched by author and tag, and auto advance can be limited to favourites or one tag.

Where they live. Favourites and free-form tags are the user's, not the preset's: in the settings next to the ratings (#569), keyed by preset id (milkdropLibrary.favorites, milkdropLibrary.tags), outside every scene. Preset files are untouched.

In a pack. An import gives every preset a new id, so an id map would not survive. Each preset in a pack carries its own library record (favourite, tags, rating), and the import folds it onto the new id.

  • The record never reaches the preset file.
  • Only presets that were really saved get one.
  • The MilkDrop panel (Pack What Is Shown, Import Pack) and the Studio's pack export both do this.
  • Built-ins stay out of packs, since every install has them.

Author. MilkDrop files have no author field, and names are mostly "Author - Title". The author comes from the name at search time, so nothing on disk needs migrating.

  • +, & and commas separate authors.
  • The first " - " ends the author part.
  • A part without a letter ("001 - …") is no author.

Search.

  • Words match the name (also a built-in's translated name), the authors and the tags.
  • #tag or tag:/etiket: search tags only; author:/yazar: search authors only.
  • Case and the Turkish I/ı, İ/i difference are ignored.
  • Show narrows to favourites or one tag, Author to one author. These are view settings and send no config.

Pool. Auto advance can pick from favourites or one tag only (milkdrop.autoFrom/autoTag, saved with the scene).

  • The filter sits where the cycle's list is built, so the timer, hard cuts, track changes and the look-ahead compile (MilkDrop: measure the preset-switch stall, then compile ahead of time #573) all see it.
  • An empty or one-preset pool says so through the cycle's own reasons (EMPTY, ALONE) and in the panel.
  • A follower does not filter: the leader's pick already came from the pool.
  • ◀, ▶, Random and the list still reach every preset, and the panel says so.

Also

  • A Favourite button and a MIDI/OSC action for the preset on screen.
  • Deleting a preset clears its rating, favourite and tags.
  • A search or filter that is hidden once six or fewer presets remain no longer keeps narrowing the list.
  • The library module loads on every page that runs the engine, the exporter and web overlay included.

Measured in an isolated copy with eight presets of our own:

  • stars in the list and the on-screen Favourite wrote the settings;
  • author:martin found the three Martin presets and not a title naming him;
  • with the pool on three favourites, the visualizer window went round those three for nine seconds and nothing else;
  • a pack of the eight carried two records; imported through the real save path, the favourites and tags landed on the new ids and in settings.json, and no preset file held a library field;
  • the English UI showed every new string translated.

In the running app the file dialog itself was not driven, because the bridge object cannot be stubbed from the page; the unit tests run the panel's own pack buttons with only the dialogs stubbed.

Tests. 2032 unit tests pass, 29 of them new. They cover authors, folding, tags, search, the pool, the pack round trip, the engine's own _autoCycle with a pool (timer, hard cut, track change, follower), a pick made in advance that the pool no longer holds, and the panel drawn with a fake DOM, including its pack buttons and ◀/▶/🎲 still reaching presets outside the pool. 49 of 49 mutations are caught. npm run smoke passes, and the user's settings and presets are unchanged.

Refs #576, #560

Search matched the name only. Presets can now be starred and tagged,
searched by author and tag, and auto advance can be limited to
favourites or one tag.

Favourites and free-form tags are the user's, not the preset's: they
live in the settings next to the ratings (#569), keyed by preset id
(milkdropLibrary.favorites / .tags), outside every scene. A pack cannot
carry an id map because an import gives every preset a new id, so each
preset in a pack carries its own `library` record (favourite, tags,
rating) and the import folds it onto the new id. The record never
reaches the preset file, and only presets that were really saved get
one. The MilkDrop panel (Pack What Is Shown, Import Pack) and the
Studio's pack export both do this; built-ins stay out of packs.

MilkDrop files have no author field and names are mostly "Author -
Title", so the author is derived from the name at search time and
nothing on disk needs migrating. Search words match the name (also a
built-in's translated name), the authors and the tags; `#tag`/`tag:`
and `author:`/`yazar:` narrow the field; comparison ignores case and
the Turkish I/ı, İ/i difference. Show and Author selectors narrow the
list without sending config.

The pool (milkdrop.autoFrom / autoTag, saved with the scene) filters
where the cycle's list is built, so the timer, hard cuts, track changes
and the look-ahead compile all see it; an empty or one-preset pool is
reported through the cycle's own reasons and in the panel. A follower
does not filter, since the leader's pick came from the pool. Manual
prev/next, random and list picks still reach every preset.

Also: a Favourite button and MIDI/OSC action for the preset on screen,
deleting a preset clears its rating, favourite and tags, and a search
or filter hidden once six or fewer presets remain no longer keeps
narrowing the list. The library module loads on every page that runs
the engine, the exporter and web overlay included.

Refs #576, #560
The pack export and import functions behind the MilkDrop panel's
buttons had not been executed by any test. They now run from the
rendered buttons with only the file dialogs stubbed: the visible
(filtered) presets are packed with their records, the same pack imports
onto new ids without touching existing ratings, a non-pack file is
refused, and an empty view exports nothing.

Two documented limits are pinned too: a pick made in advance with the
full list is not used once the pool no longer holds it (timer and track
change), and prev/next and random still reach presets outside the pool.

Refs #576, #560
@CaYatur
CaYatur merged commit 1fdba69 into main Sep 22, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant