Request playback with non-site player types and swap to backup Usher streams on stitched ad breaks; inject vendored vaft into the legacy WebView and expose a Settings toggle. Co-authored-by: Cursor <cursoragent@cursor.com>
1.7 KiB
1.7 KiB
Design: Twitch ad blocking (vaft) in Frosty fork
Intent
Personal Forgejo fork of Frosty blocks Twitch live ads using TwitchAdSolutions vaft 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)
- When
SettingsStore.blockTwitchAdsis true, requestPlaybackAccessTokenwithplayerType=popout(vaftForceAccessTokenPlayerType) instead ofsite. - When the native plugin reports an ad break, resolve a backup Usher URL trying
embed→popout→autoplay, preferring playlists whose media m3u8 does not containstitched, thenloadUrlthat stream. - When the ad break ends, restore the primary popout URL.
- Overlay shows “Blocking ads” while
_blockingAdsis 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(defaulttrue)- 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