# Design: Twitch ad blocking (vaft) in Frosty fork ## Intent Personal Forgejo fork of Frosty blocks Twitch live ads using [TwitchAdSolutions vaft](https://github.com/pixeltris/TwitchAdSolutions) ideas, adapted to Flutter. ## Upstream baseline Frosty **did not** ship an adblocker. The native player only **detects** stitched ad breaks (`adBreakStream`) to avoid bad latency/stall recovery. Turbo/sub may get `hide_ads` via linked web GQL session — server-side, not client blocking. ## Strategy ### Native player (primary — this is the reliable path) 1. When `SettingsStore.blockTwitchAds` is true, request `PlaybackAccessToken` with `playerType=popout` (vaft `ForceAccessTokenPlayerType`) instead of `site`. 2. When the native plugin reports an ad break, resolve a backup Usher URL trying `embed` → `popout` → `autoplay`, preferring playlists whose media m3u8 does not contain `stitched`, then `loadUrl` that stream. 3. When the ad break ends, restore the primary popout URL. 4. Overlay shows “Blocking ads” while `_blockingAds` is true. Implementation: `lib/apis/twitch_ad_solutions.dart`, `lib/apis/twitch_gql_api.dart`, `lib/screens/channel/video/native_video_store.dart`. ### WebView player (legacy, best-effort) Inject vendored `assets/js/vaft.user.js` on page start/finish. Not true `@run-at document-start` on Android via `webview_flutter`, so native remains preferred. Enabling adblock in Settings forces native on. ## Settings - `blockTwitchAds` (default `true`) - Turning adblock on sets `useNativePlayer = true` ## Non-goals - Upstream PR - Full browser Worker prototype rewriting on native - Third-party CDN proxies unless player-type swap proves insufficient