12 Commits

Author SHA1 Message Date
82f7fa7545 fix(1.0.9): revert OAuth popup BrowserWindow — Google detects embedded popups
1.0.1 ("trusted-domains OAuth popups") changed setWindowOpenHandler to
return action:'allow' with overrideBrowserWindowOptions for trusted
domains (Google, Yandex, etc.), opening a real Electron BrowserWindow
as popup. The reasoning was that OAuth flows need window.opener +
postMessage. That's correct for some flows but wrong for YouTube-style
login, which uses straight redirect.

Worse: Google specifically detects popup-style embedded browsers
(Electron BrowserWindow has distinct fingerprint vs real Chrome popup)
and blocks them with "Возможно, этот браузер небезопасны". The user
reported this stopped working after 1.0.0 — that's why.

Restore the 1.0.0 behavior for trusted domains: deny the popup and call
view.webContents.loadURL(newUrl) in the same view. The OAuth flow now
happens as a normal in-place navigation: YouTube → accounts.google.com
→ (user logs in) → redirect back to YouTube. No popup, no fingerprint
mismatch. The only UX loss is the popup window aesthetic; behavior is
functionally identical and matches what worked in 1.0.0.

Untrusted cross-domain still asks for confirmation, same-origin popups
still navigate in-place — unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 22:31:37 +03:00
b5e1296a7a fix(1.0.8): strip cliqz adblocker preload — breaks CSP-strict sites
cliqz/adblocker-electron registers its preload at session level via
session.setPreloads([...preloads, PRELOAD_PATH]) inside
enableBlockingInSession. That preload injects inline <script> elements
via doc.createElement('script') + script.appendChild(textNode) +
parent.appendChild(script). On modern strict-CSP sites this breaks:

- Trusted Types (YouTube, Gmail): "An HTMLScriptElement was directly
  modified and will not be executed" — 52+ console errors.
- Nonce-required CSP (kinogo via Cloudflare): "Refused to execute inline
  script ... script-src 'nonce-...'" — competing with Cloudflare's
  challenge JS, likely the proximate cause of the 403 we see on kinogo
  (CF treats the broken page as bot).

Remove the cliqz preload from each session immediately after
enableBlockingInSession. The network/CSP/blockers attached via
webRequest hooks remain active — only the script-injection layer for
anti-anti-adblock scriptlets is lost, which is a niche feature that
breaks more sites than it fixes.

The 1.0.7 Blink TrustedDOMTypes disable stays (defense in depth, no
cost). The 1.0.6 CSP-header strip stays removed (adblocker overwrites
the webRequest listener anyway).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 22:24:47 +03:00
e80704c534 fix(1.0.7): disable Trusted Types engine-wide via Blink feature flag
The 1.0.6 fix (strip require-trusted-types-for from CSP via
onHeadersReceived) didn't take effect: cliqz/adblocker calls
session.webRequest.onHeadersReceived during enableBlockingInSession,
overwriting our hook (Electron permits only one listener per session).

Replace with engine-level kill switch:
  app.commandLine.appendSwitch('disable-blink-features', 'TrustedDOMTypes')

Makes the entire Trusted Types runtime feature inert, so
require-trusted-types-for CSP becomes a no-op site-wide. Safe in this
kiosk/single-user context; only relaxes one security boundary that
sites use to harden against XSS via adblocker-style script injection —
which is exactly what we need to neutralize for cliqz's anti-anti-adblock
scriptlets on YouTube.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 22:14:19 +03:00
c9c9e1171b fix(1.0.6): strip Trusted Types CSP on YouTube/Google to unbreak adblocker
YouTube response sends Content-Security-Policy: require-trusted-types-for
'script' which blocks the cliqz adblocker's inline-script injection used
to neutralize YT's anti-adblock detection (52 "HTMLScriptElement was
directly modified and will not be executed" console errors).

Strip require-trusted-types-for and trusted-types directives from CSP
and CSP-Report-Only headers for youtube.com / youtu.be / google.com /
gmail.com (and subdomains) via onHeadersReceived on all 3 sessions.
Other CSP directives stay intact so site-level security boundaries hold.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 22:01:26 +03:00
461e7ed737 fix(1.0.5): revert Sec-CH-UA spoof (white pages), add DevTools shortcut
- Sec-CH-UA / Sec-CH-UA-Mobile / Sec-CH-UA-Platform header overrides on
  every request in 1.0.4 broke page rendering (all views white). Reverted
  to image-Referer-only behavior from 1.0.3. The Google "embedded browser"
  fix in 1.0.4 came primarily from the adblock whitelist (which IS kept)
  — Sec-CH-UA spoofing was the suspect for the regression.
- Ctrl+Shift+I and F12 now open DevTools on the main shell and on every
  in-app browser view. Always-on so kiosk machines can be debugged
  without leaving kiosk mode.
- Restore session sequenced (await 150ms between tabs) to avoid concurrent
  create-view races where multiple setLoader/addChild interleaved.
- Update banner now shows error state with a "Повторить" button instead
  of hiding it, so install-update failures are visible to the user.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 21:24:38 +03:00
542be8135a fix: whitelist Google/OAuth domains in adblock, spoof Sec-CH-UA brand
Two-part fix for Google login "Возможно, этот браузер небезопасны" error:

1. The adblocker was eating Google integrity-check resources (gstatic,
   google-analytics, googletagmanager — flagged by EasyPrivacy). Add @@
   whitelist filters for Google, Yandex, Microsoft, Apple, Facebook,
   GitHub, VK, Mail.ru ecosystems. Also switch from non-existent
   addFilters() to updateFromDiff({added}) — previous TMDB whitelist was
   silently failing in a then().catch() and never applied. Adblock cache
   bumped to v3 so the new filters take effect.
2. Sec-CH-UA client-hints branding was leaking Electron app name as the
   browser brand. Override sec-ch-ua, sec-ch-ua-mobile, sec-ch-ua-platform
   headers via webRequest.onBeforeSendHeaders on all 3 sessions so
   embedded-browser detectors see real-Chrome brand list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 20:54:35 +03:00
a171f62629 feat: seamless auto-update via electron-updater, multi-select filters, session restore
- electron-updater wired with Gitea API discovery: setFeedURL dynamically
  per release (Gitea 1.24.7 lacks /releases/latest/download/ shortcut).
  Differential download via .blockmap saves ~70 MB per patch. Renderer
  banner shows states: available → downloading X% → ready. User clicks
  "Установить и перезапустить" → quitAndInstall replaces files + relaunches.
- Multi-select filters per user spec: genres AND (TMDB with_genres comma-
  joined), countries OR (pipe-joined into with_origin_country /
  with_original_language), years OR (fan-out one request per year, merge
  by id since TMDB has no discrete-year OR). Rating stays single threshold.
- Session persistence: openedSession {tabs, activeName} saved to config
  on tab create/show/hide/remove/in-app navigation, plus before-quit.
  Restored after did-finish-load via ipcMain.emit('create-view',...) per
  tab. Survives auto-update relaunch — bring user back to the same page.
- electron-builder publish config (generic provider) so latest.yml is
  generated during build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 20:42:25 +03:00
10361cf3c0 fix: strip Electron UA tokens, refresh bookmark star on in-app navigation
- main.js: app.userAgentFallback cleaned of Electron/X.X and ESH-Media/X.X
  tokens at startup; applied to default/proxy/direct sessions. Google's
  accounts page blocked Electron UA with "Поддержка JavaScript отключена".
- Header.tsx: subscribe currentUrl to updateWebButtons (already fired on
  each in-app navigation). Bookmark star now updates as user clicks
  between movies inside the same opened site, not only on app switch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 20:27:26 +03:00
2857a40d1e feat: trusted-domains OAuth popups, og:image bookmark posters, periodic updater
- main.js: trusted-domains list with default Google/Yandex/GitHub/etc.;
  cross-domain confirmation skipped for trusted; setWindowOpenHandler
  returns action:'allow' for trusted so OAuth popups work (postMessage
  back to opener, popup self-closes). Fixes YouTube/Google login reset.
- main.js: get-page-meta IPC extracts og:image / twitter:image / JSON-LD
  image from current view; HDRezka also tries .b-sidecover img for hi-res.
- Header: bookmark button pulls og:image as poster and the page's title;
  duplicate detection switched from hostname to full URL so multiple
  movies from same site can coexist.
- BookmarksBar: site icon rendered next to source domain when distinct
  from poster; img onerror falls back to placeholder.
- Settings: trusted domains chip list with add/remove/reset.
- Updater: proper semver compare (only show if latest > current),
  direct installer URL detection per platform, hourly re-check.

Bookmark schema gains optional siteIcon; existing bookmarks remain valid.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 18:56:12 +03:00
6c314b614d feat: back-to-search button, retry site search, update checker, nsis installer 2026-03-14 14:25:52 +03:00
14da54f204 fix: kiosk toggle sync, load more animation, remove nsis target 2026-03-14 12:48:29 +03:00
c31e4a304d init 2026-03-14 05:04:51 +03:00