17 Commits

Author SHA1 Message Date
Homer ba05a4a7ef Never start fullscreen, and let the cookie dialog open
Two regressions from 5.5.0, both mine.

Fullscreen became a state of the main window, which is what stopped it
destroying the player's GL context -- but the window's geometry is saved on
exit and restoreGeometry() replays the state it was saved with. Quitting while
fullscreen therefore brought the app back fullscreen: no title bar, no close
button, and nothing able to leave it, because the player's F and Escape are
scoped to the player and the Watch tab need not even be visible. Fullscreen is
no longer restored at startup, it is left before the geometry is saved, and
F11/Escape are now window-level shortcuts so there is always a way out. The
controller also trusts the window rather than its own flag, so a fullscreen it
did not set is still escapable.

"Sign in with cookies" and the account button both call
show_cookie_login_dialog, which selects the Cookies tab by index before
showing the dialog. CustomOptionsDialog builds its tabs on SmoothTabWidget,
which stands in for a QTabWidget and says so in its docstring, but implemented
only set_current_index -- so setCurrentIndex raised and the dialog never
opened. That line had never run before: the method had no callers until 5.5.0
wired it up. SmoothTabWidget now provides the Qt-compatible API it claimed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 01:31:47 +02:00
Homer 9c4749e49b Release 5.5.0
Also stops one benign libmpv message being logged as an error: `after
creating texture: OpenGL error INVALID_ENUM` comes from the GL driver, arrives
several times per playback start and per fullscreen toggle, and playback
continues regardless. Hundreds of lines a session buried the errors that
matter -- it is a debug line now.

Verified end to end on the real display with an actual video playing: ten tab
switches and four fullscreen toggles while frames were rendering, position
advancing throughout, the render context intact, no crash, and an empty error
log afterwards.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 01:18:43 +02:00
Homer 3aca43b372 Give the app icons, tooltips and a finished theme
There was no icon system at all. Transport buttons called
QStyle.standardIcon(SP_MediaPlay), which returns the platform theme's dark
monochrome glyph -- painted onto the app's saturated red buttons at a fixed
36px with no text, that is the black square. Everything else called an icon
was an emoji baked into en.json, which is tofu wherever the emoji font is
missing. Qt stylesheets cannot recolour a QIcon, so the colour is an argument
to the new helper; that is the whole fix.

The SVGs are drawn here rather than vendored, which keeps a third-party
licence out of the tree, and they live in the module rather than as asset
files, which keeps them out of package-data and safe in a frozen build.

Tooltips were the other half: three widgets in the entire application had one
and nothing set an accessible name. Filling that in at the call sites would
have meant editing well over a hundred of them, most in upstream-owned files.
Instead one application-level event filter handles QEvent.Polish, which Qt
sends to every widget once before it is shown -- so it also reaches dialogs
built by upstream code, and survives the next merge. It maps placeholder
emoji to icons, fills empty tooltips from the button text, and logs icon-only
buttons that still have none so the gaps are findable.

StyleSheet.MAIN styles the window, inputs, buttons and tables and nothing
else, so the main tab bar, combos, sliders, lists, menus, splitters, tooltips
and the horizontal scrollbar fell through to the platform style. EXTRA_QSS
covers them, in a fork-owned module appended at the one application site.
SmoothTabWidget names its frame "tabContent" with the comment "We draw border
on content instead" -- that rule existed only inside two dialogs, and now
exists for the main window too.

Two corrections to rules that were already there: the pressed style changed
the padding, shifting every label two pixels and clipping fixed-width icon
buttons, and checkboxes were fully rounded, which reads as a radio button
rather than an on/off toggle.

Verified by screenshot on the real display: tab bar, buttons, combo carets
and checkboxes all render as intended, and all 35 icons rasterise non-empty.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 00:58:38 +02:00
Homer 089b144626 Correct the version and make the config merge deeply
The package version had been left at the scaffolded 0.1.0 while the released
tag was v5.4.0. Nothing in the code chose 0.1.0 -- it was npm-init's equivalent,
never updated -- and it made every version comparison meaningless: the window
title, the About dialog and the update check all read it.

ConfigManager merged a stored config over the defaults with dict.update(),
which is shallow. A config written by an older build carries partial "player"
and "feed" objects, and a shallow update replaces the whole nested default with
the partial one, so keys added since came back missing. The `or 15` and
`or "auto"` fallbacks at the call sites were load-bearing because of it. The
merge is now recursive, and keys present only in the stored file are kept so a
downgrade cannot destroy settings.

Configs now carry a config_version. A file written before 5.4.0 -- including
one inherited from an upstream YTSage install -- has its stored
check_app_updates cleared once, because that setting used to point at PyPI's
`ytsage` package and oop7/YTSage's releases, neither of which is this program.

The settings tab read a missing check_app_updates as enabled and persisted that
reading on OK, so merely opening Custom Options turned the checker back on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 00:31:56 +02:00
Jaroslav Beneš 8a05d5ff8f Rebrand user-visible surfaces to SageTube
The internal ytsage package name is kept deliberately - renaming it
would touch every file and destroy the ability to merge upstream
YTSage changes.

- pyproject: distribution name sagetube v0.1.0, sagetube entrypoint
  (ytsage alias retained), URLs point at the Gitea repo with an
  Upstream link to YTSage.
- Data dirs move to SageTube/ (fresh fork, fresh state) and the config
  file becomes sagetube_config.json; QApplication name and window
  title read SageTube.
- About dialog credits Houmeres and links "Based on YTSage by oop7".
- App self-update check against the upstream PyPI package is disabled
  by default; yt-dlp/deno/ffmpeg update flows are unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 02:45:58 +02:00
Jaroslav Beneš f886125857 Add embedded mpv player (render API + QOpenGLWidget)
New ytsage/gui/ytsage_gui_player.py:
- MpvRenderWidget hosts libmpv through MpvRenderContext in a
  QOpenGLWidget - works on native Wayland where wid-embedding cannot -
  with all mpv-thread callbacks marshalled to the GUI thread via queued
  signals only.
- PlayerPanel adds transport controls: play/pause, seek slider, time
  display, quality selector (caps ytdl-format height and reloads in
  place), speed, volume (persisted), subtitle toggle, fullscreen
  (reparent to top-level window), and Space/F/Escape keys.
- Playback resolves watch URLs through mpv's ytdl_hook pointed at the
  app-managed SHA256-verified yt-dlp binary (script-opts
  ytdl_hook-ytdl_path), inheriting cookies and proxy settings via
  ytdl-raw-options - stream freshness, DASH muxing and nsig handling
  stay in yt-dlp's hands.

New ytsage/core/ytsage_mpv.py probes libmpv availability; without it
the Watch UI shows a per-OS install hint and everything else works.
python-mpv added to dependencies (libmpv itself is a system package).
Config gains player.* and feed.* defaults.

Verified on Wayland: real YouTube video streams with position/duration
signals flowing and no thread-safety errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 01:44:25 +02:00
oop7 4bc43174b6 Release YTSage 5.2.0
Bump the project and package version from 5.2.0b to 5.2.0.
2026-07-01 13:42:10 +03:00
oop7 ec18262bba Bump version to 5.2.0b
Update package version from 5.0.10b to 5.2.0b in pyproject.toml and ytsage/__init__.py to reflect the new beta release and keep metadata in sync.
2026-06-14 17:54:03 +03:00
oop7 ba07a3300c Bump version to 5.0.10b
Update project version from 5.0.9b to 5.0.10b in pyproject.toml and ytsage/__init__.py to prepare a new beta release.
2026-05-01 22:51:06 +03:00
oop7 d2f96baf63 Bump version to 5.0.9b
Update package version from 5.0.7b to 5.0.9b in pyproject.toml and ytsage/__init__.py to reflect the new release.
2026-04-28 13:37:31 +03:00
oop7 d19ac96ff7 Bump package version to 5.0.7b
Update project version in pyproject.toml and ytsage/__init__.py from 5.0.5b to 5.0.7b to mark the new release.
2026-04-25 10:54:08 +03:00
oop7 00fc685e88 Bump version to 5.0.5b
Prepare a new beta release by updating the package version. Sync version from 5.0.4b to 5.0.5b in pyproject.toml and ytsage/__init__.py.
2026-04-10 17:19:44 +02:00
oop7 99f1adf8eb Bump package version to 5.0.4b
Update package version from 5.0.2b to 5.0.4b. Changed version in pyproject.toml and __version__ in ytsage/__init__.py to prepare for the new release.
2026-04-09 14:50:01 +02:00
oop7 1b3d60a1bc Bump project version to 5.0.2b
Update pyproject.toml project version from 5.0.1b to 5.0.2b to prepare the next beta release. No other code or metadata changes included in this commit.
2026-03-21 15:40:49 +02:00
oop7 64c9cf84da Bump version to 5.0.1b
Update project version from 5.0.0b5 to 5.0.1b in pyproject.toml and ytsage/__init__.py to reflect a new beta release.
2026-03-12 11:24:45 +02:00
oop7 026bd45c32 Bump project version to 5.0.0b5
Update pyproject.toml to change the project version from 4.9.7 to 5.0.0b5, marking a beta/pre-release for the upcoming 5.0 release cycle.
2026-02-10 14:45:35 +02:00
oop7 2aac706ef7 Migrate dependencies to pyproject.toml
Replaced requirements.txt with pyproject.toml to modernize project configuration and dependency management using PEP 621 standards. This change improves compatibility with modern Python packaging tools.
2026-01-25 14:04:31 +02:00