Three related PiP gaps on Android: `handleAndroidPipChanged` lived on `NativeVideoPlayerInterface`, and `notifyPip` type-checked against it, so the WebView store never learned it was in PiP — `_isInPipMode` stayed false for the whole session and the overlay kept auto-hiding behind the PiP window. Moved to the shared `VideoPlayerInterface` and implemented in both stores. The WebView store's two JS PiP channel bodies collapse into one `_setPipActive` state machine, now shared with the Android callback. `NativeVideoStore` never called `_pip.setIsPlaying()`, so with the `mediaOnlyPause` layout the PiP window's button was stuck on whatever glyph it started with, and `onPipAction` — which toggles blind — could do the opposite of what the button showed. `VideoStore.handleAppResume()` did nothing in video mode, while the native store calls `play()`. Backgrounding can suspend the webview's playback with no way for the page to restart itself, leaving it dead until a manual refresh. Resumes now unless the user was the one who paused. Not fixed: PiP with the WebView player. Twitch's embed refuses to play below 400x300 CSS pixels and a PiP window is far under that, Android resizes the activity before firing onPictureInPictureModeChanged so any correction arrives too late, and the embed latches once tripped. The native player has no such constraint. Refs #563. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|---|---|---|
| .claude | ||
| .github | ||
| .vscode | ||
| android | ||
| assets | ||
| ios | ||
| lib | ||
| scripts | ||
| test | ||
| web | ||
| .env.example | ||
| .gitignore | ||
| .mcp.json | ||
| .metadata | ||
| AGENTS.md | ||
| analysis_options.yaml | ||
| firebase.json | ||
| LICENSE | ||
| pubspec.lock | ||
| pubspec.yaml | ||
| README.md | ||
Download
Why
The official Twitch mobile app doesn't support emotes from 7TV, BetterTTV (BTTV), and FrankerFaceZ (FFZ) — third-party extensions for Twitch used by millions. As a result, only emote text names are rendered rather than their actual image or GIF, making the chat unreadable in many channels.
Features
- Support for 7TV, BetterTTV, and FrankerFaceZ emotes and badges
- Browse followed streams, top streams, and top categories
- Autocomplete for emotes and user mentions
- Light, dark, and black (OLED) themes
- Search for channels and categories
- See and filter chatters in a channel
- Local chat user message history
- Theater and fullscreen mode
- Watch live streams with chat
- Picture-in-picture mode
- Block and report users
- Emote menu
- Sleep timer
- And more...
For a more detailed overview, visit frostyapp.io.
Development setup
-
Clone this repo (e.g.,
git clone https://github.com/tommyxchow/frosty.git). -
Go to the Twitch dev console and register a new application to retrieve a Client ID and Client Secret.
-
Copy
.env.exampleto.envand fill in your credentials:cp .env.example .env -
Run
flutter pub getto fetch all the dependencies. -
Choose an emulator or device and run the app! The included VS Code launch configurations will automatically read your
.envfile. -
(Optional) Run
dart run scripts/get_twitch_token.dartto quickly get a user auth token. Long-press the Anonymous account tile in the app to log in.
Important
Frosty uses MobX for state management. Please refer to the documentation about code generation, otherwise your changes within MobX stores may not be applied.
Donate
If you appreciate my work and would like to donate/tip, you can through:
Otherwise, downloading Frosty, leaving a review, or starring this repository is more than enough to show support. Thank you!
License
Frosty is licensed under AGPL-3.0-or-later.