* feat(chat): add bubbles for shared chat participant channels Twitch's native shared chat previously had no way to interact with participant channels the way manually-added chats work. Adds per-participant bubbles alongside manual tabs: tapping one spotlights that channel (fading the rest), hiding one filters its messages from the feed entirely. Defaults to unfaded, resets on rejoin (fresh ChatStore per connect). Manual "merged mode" fading is untouched and unaffected. * refactor(chat): dedup shared-chat tag lookup and extract fade policy - add IRCMessage.sourceChannelId, replacing three copies of the same source-room-id/room-id tag lookup - move the shared-chat spotlight/merged-mode fade decision out of ChatMessage's build into ChatStore.shouldFadeMessage, matching the extract-into-store convention already used for SharedChatBubbleState - factor the tab-bar item's Padding/Center wrapper into a shared _wrapItem helper instead of duplicating it per branch * fix(chat): don't spotlight a hidden shared-chat bubble toggleFocus didn't check hiddenChannelIds, so tapping a hidden bubble's chip added it to the spotlight set — fading every other participant to showcase a channel whose own messages were already filtered out of the feed. * fix(chat): stop shared-chat detection flapping on system messages _isInSharedChatMode was recomputed from every PRIVMSG/NOTICE/USERNOTICE, but only PRIVMSG reliably carries source-room-id for a session's duration. A sub/raid/announcement without the tag would flip the flag off and back on within a single live session. Previously this only risked a redundant asset refetch (already guarded); now the shared chat bubble bar reads the flag directly, so a flap would visibly collapse and reopen it. Scope detection to PRIVMSG only. |
||
|---|---|---|
| .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.