Commit Graph
25 Commits
Author SHA1 Message Date
KeelrLeek f8508da081 setup: the installer is our own window — the alpha key is the gate, the release comes down with it and is verified before the silent install, and the in-app tour asks for the key too 2026-09-09 18:00:02 -05:00
KeelrLeek fac6fc33dd release: 1.8.0-alpha
release / windows (push) Canceled after 0s
2026-09-09 16:16:22 -05:00
KeelrLeek cd2391198e first run, updates, installer: a setup tour stands in front of a fresh install, releases arrive through an in-app updater with stable and nightly channels behind a read-only token, and the branded installer builds again 2026-09-09 16:16:19 -05:00
KeelrLeek 07810f7543 release: 1.7.1-alpha 2026-09-09 12:13:10 -05:00
KeelrLeek d7bc92fda7 release: 1.7.0-alpha 2026-09-02 16:38:43 -05:00
KeelrLeek 8b511b20e7 community: spaces, an owner-signed roster with epochs, a bounded window of signed lines, bodies sealed to a rotating key when private 2026-09-02 15:50:18 -05:00
KeelrLeek 4378c4c0cc community: the encrypted inbox, friend requests and shares travel sealed to a box key when the other side has published one 2026-09-02 15:26:30 -05:00
KeelrLeek 6ed6f5b8f8 community: the soulseek link proof, one message to yourself links the account and one question links anyone who answers 2026-09-02 14:27:54 -05:00
KeelrLeek cf9558cf26 release: 1.6.0-alpha 2026-09-02 14:03:28 -05:00
KeelrLeek 6dce4e2ac7 the freenet layer: adapter, persona and profile services, the contracts bundled as commitments 2026-09-02 13:43:16 -05:00
KeelrLeek 93271aceec release: 1.5.0-alpha 2026-08-27 17:25:19 -05:00
KeelrLeek 225c9139aa release: 1.4.0-alpha 2026-08-26 07:57:03 -05:00
KeelrLeek 7dfba58ea7 release: 1.3.0-alpha 2026-08-25 08:05:07 -05:00
KeelrLeek ad2c912b71 release: 1.2.0-alpha 2026-08-24 18:12:02 -05:00
KeelrLeek 30eb6fe025 release: 1.1.0-alpha 2026-08-24 10:49:11 -05:00
KeelrLeek 1dd8573808 dj sets + lyrics: a mix that names its own tracks, and words pulled off the separated voice 2026-08-24 10:49:10 -05:00
KeelrLeek 4efe85b6bf release: 0.1.0-alpha.4 2026-08-17 18:06:04 -05:00
KeelrLeek df3d15553a playlists + lyrics: setlists with pages of their own, and the words timed to the voice 2026-08-17 18:05:31 -05:00
KeelrLeek e7d0971de2 import: the whole feature, and releases put back together
Everything the import grew over the last week, landing in one go — the
window, the picker, the audition pen, apply, and the review that stands
between them.

The fold is the new part. A release filed as a container of parts arrived
as N albums, because the scan groups audio by its immediate parent and the
container holds none of its own: Analord's eleven volumes were eleven
records, and six more releases split the same way. Records now fold into
the release above them, and apply is handed an explicit part list — never a
recursive walk, which is what let one stray file swallow 288 descendants
and duplicate 9 GB.

Where releases live is read off the collection rather than assumed, so a
genre-nested library moves the answer instead of breaking; below a dominant
majority at one depth the pass refuses entirely, because no folding beats
wrong folding. Three vetoes independent of depth catch a misread level.
Every fold is listed in the review with a way out.

research/import/fold-audit.mjs imports the shipping module, so the audited
code is the running code: 9 folds, 0 swallows across four library shapes,
and none of the 148 artist folders touched. It was that harness that killed
the tempting version of this rule — matching a part against its container
folded 40 artist folders, Mac Demarco's 8 albums into one, because album
folders carry the artist's name.

The regression test found a live bug on the way: parts number from 01 each,
so flattening two discs collided, and "same name, same size" read the
second file as already-imported and dropped it while still counting it.
That reuse now also requires that this run has not already written the
path.

Also here: the picker's accent crossfades between records instead of
cutting through the app's blue (ownership moved to the window, which
survives the per-record re-key), the fullscreen viewer wears the album's
accent instead of the one it left behind in the portal, Skip defers a
record without deciding it, and Keep mine is gone — with the cards picked
field by field it was Next under another name.
2026-08-10 07:55:59 -05:00
KeelrLeek f72b12a892 release: 0.1.0-alpha.3 2026-08-04 14:49:28 -05:00
KeelrLeek b33d403634 player bar: the name sets the width, and the waveform stops flattering the clamp
The source chips are gone — the rail already tells that story — and with
them the measured slot, its effects, and the bar's only container query.
The now-playing cluster hugs the song name with no cap, giving ground only
once the scrubber hits its 260px floor; the artist's 55% ceiling applies
only when an album sits beside it, so a lone loading artist no longer
renders as two letters in a twelve-pixel box.

The waveform is rebuilt on honesty. WAVE_BUCKETS rises 400 → 2000 (~128ms
per bucket — at 400, every display bar was ~2s of audio averaged twice),
and one shared shaping in waveshape.js replaces both lanes' gain-into-clamp
rule, which flat-topped 53.8% of the bars on a real decode and was propped
up by per-bar noise in the rail — deleted; the lane shows the record, not a
hash of the bar index. Bars fold with a mean+peak blend and stretch across
the track's own p05–p97, so a loud master stops pinning to the ceiling and
a quiet one stops vanishing.

The playbar copies the rail's fade verbatim: whole bars blend accent→grey
with cuts landing in the 4px gap, and the one bar under the playhead
crossfades toward whatever its neighbours are — the wash while hovering,
the muted grey otherwise. The redraw gate watches that blend instead of a
0.75px playhead move, so both lanes now step on every position event.

Loading is drawn, not implied: the solid fallback bar is gone and the lane
is always the bars, always seekable. Empty, it rests as the rail's dots; a
swell crosses them while a waveform is computed (2s sweep, 0.5s rest); a
streaming track's bars stand up left→right on a 40ms cadence, each rising
over 2s. The rise frontier is the waveform's OWN coverage, reported by
stream_waveform beside the peaks — the old contract zero-padded partial
peaks to full length and let the UI fold them against a fresher byte
count, which stretched the whole shape between refreshes. Where the bars
end is how much of the track has actually loaded; cached and local tracks
arrive at coverage 1 and pop in complete. The first partial is also
requested eagerly (fresh refresh clock per track, 700ms retries until
peaks exist), closing most of the audio-before-lane gap.
2026-08-03 16:08:26 -05:00
KeelrLeek 4179247203 build: strip the UTF-8 BOM that stopped both halves of the app starting
0.1.0-alpha.2 bumped three version strings with a tool that writes UTF-8
WITH a BOM, and committed it. Neither build survives that:

  package.json      vitefu JSON.parses the raw string, so `npm run dev`
                    exited instantly — "Unable to read package.json"
  tauri.conf.json   the Tauri build script failed with "expected value at
                    line 1 column 1"; cargo exit 101
  Cargo.toml        tolerated, but wrong

`require()` hides this. Node strips a BOM on require and JSON.parse does
not, so reading package.json from a REPL reports a perfectly good file
while both builds refuse it. Only the raw bytes show it: EF BB BF.

All 191 tracked files scanned. These three were the only ones affected,
and they are exactly the three 5682dfc touched. Stripped with Node rather
than PowerShell, whose default Out-File/Set-Content encoding is what wrote
them in the first place — the files are byte-identical but for the three
leading bytes.

Cargo.lock carries the 0.1.0-alpha.1 -> alpha.2 propagation the release
commit left behind in the working tree.
2026-07-30 07:39:30 -05:00
KeelrLeek 793f78370e feat: crossfade preview suite, loudness normalization, debug overlay
Preview modal audio, five rounds:
- True track-change crossfade: scheduleSettle no longer silences the
  outgoing clip at t=0; preview_load's equal-power fade owns both ramps,
  gated on the incoming voice's first Playing event (audible_marks), with
  failure/overstay fallbacks. CROSSFADE_MS = 340 — locked to the reel's
  card-slide so audio and visuals land together.
- Two-neighbour lease prefetch + a 15-min on-disk clip byte-cache
  (recent_clips): steps in BOTH directions crossfade in ~15 ms; revisits
  never re-download.
- Adaptive settle (isolated steps fire immediately, bursts coalesce) and
  anticipatory auto-advance (step at clip end minus 400 ms) so auto-play
  crossfades over the tail instead of gapping.
- Session resume memory: revisited tracks continue where they left off
  (decoder-level start offset via play_local_from/resume_at); finished
  tracks restart from the top.
- Open/close crossfades with the MAIN player: fade-pause with the
  desired-paused latch landing at ramp end, fade-resume from the paused
  position; MAIN_FADE_GEN guards; focus handshake relaxation documented
  in focusBridge.

Volume normalization (Settings > Playback, default on):
- Dependency-free BS.1770/EBU R128 meter in the player crate (K-weighting,
  400 ms gated blocks, incremental) + analyzer that reads the same growing
  file playback streams from — first plays are measured at download speed.
- Gain layered under user volume; audible start GATED on a preliminary
  measurement (10 s of audio or 800 ms budget) so the level is right from
  the first sample and never changes mid-track; prelim boosts capped 3 dB,
  peak-aware clipping guard, persistent loudness-cache.json.
- Gapless boundaries get their own sample-accurate gain via
  SetNextNormGainDb, fed by preload analysis.

Debug overlay (Ctrl+Shift+D): process-tree CPU / PDH GPU / working-set +
private-commit RAM / network rates / FPS / current-track download progress
read from the backend's own StreamProgress / live normalization state /
preview session phase. Polls only while visible.

131 JS + player + app tests green; every path verified live over CDP.
2026-07-23 16:05:14 -05:00
KeelrLeek 8cb3cd593b Phase 2A+2B: native preview backend and renderer glue
Rust (2A):
- metadata: deezer_track_uncached (fresh mint, cache-updating, paced) and
  fetch_preview_media — dedicated client whose custom redirect policy
  re-validates every hop against the media allowlist; bounded body read
  (cap enforced on received bytes, not Content-Length's promise); Date
  header captured for provider-clock lease math. httpdate dep added.
- src-tauri/preview.rs: second Player instance + soulstream:preview event
  channel; preview_resolve (fresh mint → host gate → MIME gate → ID3v2
  shell strip → MPEG sync check → clip file + opaque lease id → safe_for_ms
  mirroring lease.js); preview_load with start_paused via the
  desired-paused latch; preview_control/dispose; player_pause_acked
  exposing the Phase 0.4 ack on the MAIN player. 9 unit tests.

JS (2B):
- api.js: preview command surface (opaque lease ids only).
- nativeTransport.js: stamps {sessionId, generation, sessionKey} onto
  backend events; cleared context makes stragglers dispatch nothing.
- productionResolver.js: DTO → MediaLease, failure classes preserved.
- focusBridge.js: production coordinator binding with the documented
  renderer-side generation invariant (buffering counter + gateway).
- service.js: the orchestrator — settle window, resolve→load→play under
  focus, single capped retry, one forward lease prefetch with safe-window
  expiry, stale re-checks before every transport command, close/handoff.
  The service constructs its transport around its own dispatch — the
  factory signature exists because a pre-built transport silently loses
  the event wiring (caught by test).

70 JS tests passing (npm test); metadata 46 + app preview 9 in cargo.
2026-07-22 18:45:29 -05:00
KeelrLeek a667b4b28e Baseline: full tree snapshot after git repository loss
The previous .git directory was found gutted (only info/ remained), so
history is unrecoverable locally. This commit restores version control
with the tree exactly as it stands: the working app, the preview-tracks
launcher on the artist hero, the scrollable-track-previews design bundle
(docs + approved mockups), and the Phase 0 validation artifacts.
2026-07-22 17:57:00 -05:00