Commit Graph
5 Commits
Author SHA1 Message Date
vincent 832a8f0f26 fix: the menu bar could never read a browser's address
Tested end to end from the menu bar: a video playing in Arc was saved,
its channel subscribed to, and the subscription removed again.

Three things were wrong.

One script named all seven browsers. AppleScript resolves an
application's terminology when it compiles, so naming a browser that is
not installed is a compile error — which no `try` can catch, and which
kills the whole script before a line of it runs. On a Mac without Brave
the lookup failed outright and Arc, first in the list and working, was
never asked. Each browser now gets its own script.

The tray icon was dropped as soon as it was built. TrayIcon is
reference-counted and "the icon is removed when the last instance is
dropped", so it was created and destroyed in the same breath. It is
held for the life of the app.

Subscribing to a channel already present as a bare row — the parent of
a video saved from the menu bar — was refused as a duplicate, and the
upsert would not have promoted it anyway. Saving a video from a channel
therefore made it impossible to subscribe to. The check asks whether it
is a subscription, not whether the row exists, and subscribing promotes.

Feedback no longer depends on one channel that can fail silently: a
notification from the app, the AppleScript one behind it, and the
menu's own first line, which reports the last result and cannot be
suppressed. A log beside the database records each step, which is how
all three of these were found rather than guessed at.
2026-08-29 20:27:52 +02:00
vincent 1790453a47 feat: manage subscriptions in the app, and act from the menu bar
Takeout is still the way a subscription list arrives. These are the
things it cannot do.

Hovering a channel in the sidebar reveals a delete, sitting where the
count is — the least useful thing on that row at the moment you reach
for it. It asks first, and says what goes: the channel, its videos, and
how many downloaded files will be deleted. It also says plainly that
YouTube is not touched; only this app forgets the channel.

A + beside the cog adds one channel from any link — its page, its
@handle, or one of its videos. The channel id and name are read off the
page, which is the same pair the CSV carries, and the feed is fetched
straight away so it is not sitting there empty.

A menu bar item acts on whatever a browser is showing without leaving
it: save that video, or subscribe to its channel, while it plays on.
The address comes from whichever running browser has a YouTube page —
asked with AppleScript, guarded so no browser is launched to answer,
and reported honestly when macOS has not granted the permission yet.
Answers come back as notifications rather than by raising the window.

Saving a video is not subscribing to its channel, so a channel can now
exist as a parent row without being a subscription: out of the sidebar,
skipped by refreshes, and left alone when a CSV import replaces the
subscription list.

Also removes a stale duplicate of the file header that had been sitting
inside run()'s setup block. Items are legal inside a block, so it
compiled and nobody noticed.
2026-08-29 19:54:41 +02:00
vincent 61db10b2c8 fix: native video fullscreen, window dragging, quality picker, spinner
Enable WKWebView's elementFullscreenEnabled at startup. It is off by
default in a Tauri window, which is why the native player had no
full-screen button and why right-click 'Enter Full Screen' did nothing.
With it on, WebKit's own control appears on the video and gives the real
system fullscreen player, so the app-level workaround is gone.

Restore window dragging: data-tauri-drag-region needs
core:window:allow-start-dragging, which was missing, leaving the
title-bar strip inert.

Download quality is now a resolution picker (best/2160/1440/1080/720/
480) instead of a two-way toggle; every selector still pins AAC audio
because Opus in MP4 is silent in WebKit.

Tile titles truncate to a single line so rows stay uniform, and the
player shows a spinner while the video buffers, not just while the
stream URL resolves.
2026-08-29 10:38:35 +02:00
vincent a30423e4b5 feat: Tauri commands, concurrent refresh, download manager
Refresh fetches 8 channel feeds concurrently and mirrors thumbnails to
disk so the offline feed still renders. Downloads are capped at 2 and
shell out to yt-dlp with an absolute binary path, since GUI apps do not
inherit a login shell PATH.
2026-08-29 02:28:26 +02:00
vincent 6fdad60190 feat: scaffold Tauri + React + Tailwind v4 2026-08-29 02:21:25 +02:00