Commit Graph
37 Commits
Author SHA1 Message Date
shadowdaoandClaude Sonnet 5.5 12cfca8b17 Publish a fixed-URL "latest" AppImage for static-URL updaters
Gitea has no /releases/latest/download/ redirect and release URLs always
include the tag, so updaters that poll a constant URL (Shelly) cannot use
them. After publishing a vX.Y.Z release, replace the asset on a rolling
pre-release tagged "latest":

  .../releases/download/latest/WhatsThatMusic-latest-linux-x86_64.AppImage

Replacing the asset changes its ETag and Last-Modified, which Shelly
compares. The pre-release flag keeps Gitea's own "latest release" on the
newest vX.Y.Z. The logic lives in .gitea/scripts/update-latest.sh so it can
be run against the API outside CI. The publish job now checks out first,
since checkout cleans the workspace and would delete downloaded artifacts.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 12:17:46 -07:00
jknapp 0e5b20498a Merge pull request 'Fix now-playing scraper, quit hang, tray icon and tray race (v1.0.1)' (#6) from fix/now-playing-scraper-and-quit into main
Build release artifacts / linux (push) Successful in 4m9s
Build release artifacts / macos (push) Successful in 1m6s
Build release artifacts / windows (push) Successful in 1m51s
Build release artifacts / publish (push) Successful in 15s
v1.0.1 latest
2026-10-04 18:37:51 +00:00
shadowdaoandClaude Sonnet 5.5 e49078ee03 Fix now-playing scraper, quit hang, tray icon, and tray race (v1.0.1)
- Read the track from the Media Session API, falling back to the legacy
  ytmusic-player-bar scrape. Current YT Music layouts render no player bar,
  so the API and tray stayed empty while music played. Artist is also clean
  now (no "• views • likes" suffix).
- Terminate connected WebSocket clients before closing the server. ws's
  close() waits for every client to disconnect, so quitting with an overlay
  open hung forever, leaving the window playing and the port bound.
- Replace the tray icon with a valid PNG (the old one had a bad IDAT CRC and
  decoded to an empty image) and test that its chunks are well formed.
- Create the tray before the window so early state updates are not dropped.
- Bump version to 1.0.1.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 11:37:38 -07:00
jknapp f73ea93dde Merge pull request 'Surface API errors in the publish step' (#5) from ci/harden-publish into main 2026-08-29 03:39:57 +00:00
shadowdaoandClaude Opus 5 d218f4c6f3 Surface API errors in the publish step
The publish job has never run successfully. When it failed on the v1.0.0
tag it reported "SyntaxError: Unexpected end of JSON input" from piping an
empty curl body into JSON.parse, which said nothing about the actual cause
(an unset token). An opaque failure there costs a full three-platform build.

Routes every call through a helper that captures the HTTP status and prints
the response body on 4xx/5xx. Also switches artifact iteration to while-read
so filenames with spaces cannot split, and dumps the artifact tree when
nothing matches.

Helper verified against the live API: existing tag resolves to its release
id, a missing tag reports HTTP 404 with the body and yields an empty id so
the create path runs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 20:39:45 -07:00
jknapp 1f79d7bcfe Merge pull request 'Match actual runner labels and use the injected token' (#4) from fix/runner-labels into main 2026-08-29 01:57:08 +00:00
shadowdaoandClaude Opus 5 394dc7107c Match actual runner labels and use the injected token
The mac job targeted macos-arm64, but the registered Mac runner is
labelled macos-latest, so that job would have queued forever rather than
failing -- a job with no matching runner is silently pending.

Also switches the publish step to secrets.GITEA_TOKEN, which Gitea injects
automatically and scopes to the repo, instead of requiring a hand-created
RELEASE_TOKEN. RELEASE_TOKEN still overrides it if wider rights are needed.

Runners confirmed via /api/v1/admin/actions/runners: ubuntu-latest,
windows-latest (x2) and macos-latest are all online.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 18:56:58 -07:00
jknapp f8d10d3a24 Merge pull request 'Build each platform on its own native runner' (#3) from ci/native-builders into main 2026-08-29 01:53:39 +00:00
shadowdaoandClaude Opus 5 72485d44ff Build each platform on its own native runner
Splits the release workflow into linux, windows and macos jobs feeding a
single publish job. The publish step is separate so parallel builds cannot
race to create the release and fail on a duplicate tag.

Windows now builds natively, so signAndEditExecutable no longer has to be
disabled. That flag was suppressing rcedit, which is what embeds the icon
and version resources -- the v1.0.0 exe shipped with the stock Electron
icon as a result. Also adds an NSIS installer alongside the portable zip.

macOS gains a dmg target, which cannot be produced off macOS. Builds stay
unsigned pending a Developer ID, with CSC_IDENTITY_AUTO_DISCOVERY disabled
so electron-builder builds unsigned instead of failing on a real Mac.

Nothing cross-builds now; all three runners must be registered before
tagging, since a job with no matching runner queues silently.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 18:53:24 -07:00
jknapp 240535506b Merge pull request 'Add macOS target and platform-qualified artifact names' (#2) from release/v1.0.0 into main
Build AppImage / appimage (push) Failing after 22s
v1.0.0
2026-08-29 01:11:44 +00:00
shadowdaoandClaude Opus 5 289cb6d4b1 Add macOS target and put platform in artifact names
Adds a mac zip target (x64 + arm64) so releases cover all three
platforms. Builds unsigned: electron-builder skips code signing when not
running on macOS, so these need the quarantine attribute cleared.

Also puts ${os} in artifactName. Without it the Windows and macOS zips
were both WhatsThatMusic-1.0.0-x64.zip, which collide as release assets
and give no clue which platform they are.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 18:11:31 -07:00
jknapp 9240dc3cb6 Add Linux AppImage build target, app icon, and release workflow (#1) 2026-08-29 00:58:42 +00:00
shadowdaoandClaude Opus 5 be0b62a5ba Add Gitea Actions workflow to build AppImage on tag
Builds the Linux AppImage on a v* tag, runs the test suite first, and
attaches the artifact to a Gitea release via the API (no third-party
action, so nothing needs to be fetched from github.com at runtime).

Guards that the tag matches package.json version: electron-builder names
the artifact from package.json, so tagging v1.0.1 without bumping the
manifest would otherwise publish an AppImage named 1.0.0.

Requires a RELEASE_TOKEN secret and a registered act_runner; neither is
set up yet, so this is inert until both exist.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 17:58:19 -07:00
shadowdaoandClaude Opus 5 d8107a06c2 Add Linux AppImage build target and app icon
The build config only had a Windows target. Adds a linux block producing
an AppImage, plus a 512x512 build/icon.png so the packaged app does not
ship with the stock Electron icon.

Verified by running the packaged binary: the embedded server comes up on
9095 and serves the overlay from process.resourcesPath, confirming the
extraResources mapping works in a packaged build.

StartupWMClass is deliberately not set via linux.desktop -- electron-builder
already emits the correct value, and the nested { entry: {...} } form leaks a
literal "entry=[object Object]" line into the .desktop file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 17:54:05 -07:00
shadowdaoandClaude Opus 4.7 2cd5fe6f0f Ignore electron-builder dist output
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 10:40:55 -07:00
shadowdao ba36dd569f Bundle overlay via extraResources for packaged build 2026-04-26 10:40:03 -07:00
shadowdao 0474f51f03 Update README for single-app architecture 2026-04-26 10:38:13 -07:00
shadowdaoandClaude Sonnet 4.6 ac255bfa75 Delete extension, OS backends, standalone server, root npm project
Removes extension/, desktop-client/backends/, desktop-client/config.js,
server/, root package.json/package-lock.json/node_modules/, and the
now-unused electron-store dependency from desktop-client/package.json.
The desktop-client is now a self-contained Electron app with no external
deps beyond express and ws.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 10:36:53 -07:00
shadowdao 60845b7870 Bypass beforeunload on window close so app quits while audio plays 2026-04-26 10:34:42 -07:00
shadowdaoandClaude Sonnet 4.6 98a12e1e3e Update startServer JSDoc; surface boot errors via dialog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 10:12:14 -07:00
shadowdaoandClaude Sonnet 4.6 6fd858347f Fall back to next port on EADDRINUSE; show dialog and update tray URL
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 10:08:15 -07:00
shadowdaoandClaude Sonnet 4.6 65e871c16e Move tray state into createTray closure
Removes top-level let trayInstance, opts, currentTitle, currentArtist
and the top-level buildMenu function. All mutable state and buildMenu
now live inside the createTray closure. Public API and behaviour are
unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 09:56:48 -07:00
shadowdao 8be1999a6b Rewrite tray: simple menu, no server-URL config 2026-04-26 09:50:59 -07:00
shadowdaoandClaude Sonnet 4.6 affc71bd0f Harden Electron main: re-entrancy guard, tray destroy, loadURL error log
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 09:49:20 -07:00
shadowdao 7ea303a2ef Rewrite Electron main: in-process server + YT Music BrowserWindow 2026-04-26 09:46:08 -07:00
shadowdao ffa045469b Add YT Music preload scraper that emits wtm:state IPC 2026-04-26 09:42:49 -07:00
shadowdaoandClaude Sonnet 4.6 03128cbe6b Harden server: drain connections on stop, validate proxy URL scheme, add fetch timeout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 09:41:44 -07:00
shadowdaoandClaude Sonnet 4.6 3445ef89f0 Add in-process server module with setState entry point
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 09:38:11 -07:00
shadowdao 81e08afa00 Add tests for null no-change and zero as real value 2026-04-26 09:35:53 -07:00
shadowdao acf5e74f30 Add pure state-merge module with unit tests 2026-04-26 09:32:52 -07:00
shadowdao ad8fde0dda Use cross-platform quoting in test script 2026-04-26 09:31:25 -07:00
shadowdao 43e77ef7db Add server deps and test script to desktop-client package 2026-04-26 09:27:44 -07:00
shadowdaoandClaude Opus 4.7 c9023a8da2 Add implementation plan for embedded YouTube Music player
Bite-sized, TDD-where-applicable tasks covering branch setup, state
merge unit tests, server module, preload scraper, Electron main
rewrite, tray rewrite, manual smoke tests, Windows zip build, and
cleanup of the superseded extension/server/OS-detection code.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 09:24:17 -07:00
shadowdaoandClaude Opus 4.7 24054a29bb Add design spec for embedded YouTube Music player
Replaces the OS-detection / browser-extension input architecture with
a single Electron app that embeds music.youtube.com and pushes
now-playing state to an in-process server on localhost:9095.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 09:18:27 -07:00
shadowdaoandClaude Opus 4.6 7f9a090666 Fix image proxy by moving API routes before static middleware
Express was matching static files before API routes, causing the
image-proxy endpoint to return 404 in browser.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:58:12 -07:00
shadowdaoandClaude Opus 4.6 e36c4d1a74 Add YouTube Music now-playing server, OBS overlay, and browser extension
Node.js server on port 9095 receives now-playing data via POST and broadcasts
to connected WebSocket clients. Includes a Firefox/Chrome extension that scrapes
YouTube Music's player bar every 3s, an OBS-ready transparent overlay with
animated equalizer bars, and an image proxy to bypass CDN restrictions in OBS.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:55:04 -07:00
shadowdao 74bbf4e9b6 first commit 2026-04-12 11:30:46 -07:00