- fix global stores documentation (add GlobalAssetsStore location, remove UserStore) - correct error handling docs (typed exceptions via BaseApiClient, not Future.error) - add missing lint rules (avoid_redundant_argument_values, unnecessary_parenthesis) - fix emote factory methods (add all 4: fromTwitch, fromBTTV, fromFFZ, from7TV) - update build_runner commands to modern dart run syntax - add MobX reactions examples and API architecture section - align commit convention with actual repo style (lowercase, no prefixes) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
8.3 KiB
Copilot Instructions for Frosty
Project Overview
Frosty is a cross-platform Flutter app for Twitch that supports third-party emotes (7TV, BTTV, FFZ). The architecture is built around MobX state management with strict code generation requirements and a shared HTTP client pattern for API efficiency.
Critical Development Workflow
Essential Commands
Dependencies and Development:
flutter pub get- Install dependenciesflutter run- Run the app on connected device/emulatorflutter build apk- Build Android APKflutter build ios- Build iOS appflutter analyze- Run static analysis and lint checksflutter test- Run all tests
Code Generation (REQUIRED)
All MobX stores and JSON models require code generation. Always run after any MobX or model changes:
dart run build_runner build --delete-conflicting-outputs
Alternative commands:
dart run build_runner build- Generate code oncedart run build_runner watch- Watch and regenerate code on changes
Generated .g.dart files are excluded from linting but must be committed to source control.
Environment Setup
Twitch API requires client credentials via --dart-define:
flutter run --dart-define=clientId=YOUR_TWITCH_CLIENT_ID --dart-define=secret=YOUR_TWITCH_CLIENT_SECRET
Architecture Patterns
State Management (MobX)
- Store Pattern: Each feature has stores in
lib/screens/{feature}/stores/(not at screen root) - Naming: All stores end with
Storesuffix and have corresponding.g.dartfiles - Global Stores:
AuthStore,SettingsStoreinlib/screens/settings/stores/GlobalAssetsStore(shared emote/badge cache) inlib/stores/
- Dependency Injection: Stores are provided via Provider in
main.dartwith shared HTTP client
API Service Architecture
- Shared HTTP Client: Single Dio instance configured in
DioClient.createClient()with:- Connection pooling and keep-alive headers for efficiency
- Optimized timeouts: 8s connect, 15s receive, 10s send
- Global Twitch User-Agent header
- Simple logging in debug mode (not verbose to avoid log spam)
- API Services:
TwitchApi,BTTVApi,FFZApi,SevenTVApiinlib/apis/ - Authentication Interceptor:
TwitchAuthInterceptorautomatically injects auth headers:- Detects Twitch API URLs and adds Authorization + Client-Id headers
- Updates automatically when user authentication changes
- Eliminates manual header passing throughout the codebase
- Error Handling:
UnauthorizedInterceptorcatches 401 errors for token refresh - Service Pattern: All API services extend
BaseApiClientfor consistent error handling
Project Structure
Key Directories:
lib/screens/- UI screens organized by feature (home, channel, settings, onboarding)- Each screen has its own MobX stores in a
stores/subdirectory
- Each screen has its own MobX stores in a
lib/models/- Data models with JSON serialization (uses.g.dartfiles)lib/apis/- API services for Twitch, BTTV, FFZ, and 7TVlib/widgets/- Reusable UI componentslib/cache_manager.dart- Custom cache management for images/medialib/utils.dart- Utility functions and helperslib/utils/- Additional utility modules including context extensions
Screen Organization
lib/screens/{feature}/
├── {feature}.dart # Main UI
├── stores/ # Feature stores directory
│ ├── {feature}_store.dart
│ └── {feature}_store.g.dart
└── subdirectories/ # Feature sub-components
Main Application Flow:
- App starts in
main.dartwith Firebase initialization and dependency injection via Provider - Authentication handled by
AuthStoreusing Twitch OAuth - Settings persisted via
SettingsStorewith SharedPreferences - API services inject common HTTP client for efficient connection reuse
Model Generation
- JSON Serialization: Models use
@JsonSerializable()with.g.dartcompanions - Emote Architecture: Base
Emoteclass with platform-specific factories (Emote.fromTwitch(),Emote.fromBTTV(),Emote.fromFFZ(),Emote.from7TV())
Key Integration Points
Firebase Services
Initialized in main.dart with error handling:
- Crashlytics for uncaught errors
- Performance monitoring
- Analytics
Chat System
- IRC Connection: WebSocket to Twitch IRC for real-time chat
- Emote Loading: Asynchronous third-party emote fetching (BTTV/FFZ/7TV)
- Message Parsing: Custom rendering with emote/badge support
- Real-time IRC: WebSocket connection to Twitch IRC with custom
IRCMessageparsing - Third-party Emotes: Asynchronous loading of BTTV, FFZ, and 7TV assets via dedicated APIs
- Message Management: 5000 message limit with 20% batch removal optimization for performance
- Assets Store: Separate
ChatAssetsStoremanages emotes, badges, and chat-related data - User interaction features: Blocking, reporting, moderation capabilities
Authentication Flow
- OAuth: Twitch OAuth via WebView in
AuthStore - Token Storage: FlutterSecureStorage for secure token persistence
- Auto-refresh: Token validation and refresh logic in
AuthStore - Two-tier Token System:
- Default app token for unauthenticated requests
- Optional user token stored in Flutter Secure Storage
- Automatic token validation on startup with fallback
- WebView OAuth Flow: Custom JavaScript injection in WebView for seamless Twitch login experience without opening external browsers
- Secure Storage Cleanup: First-run detection clears secure storage to handle Android/iOS uninstall scenarios where secure storage persists
Code Style Enforcement
Analysis rules in analysis_options.yaml:
- Single quotes:
prefer_single_quotes - Package imports:
always_use_package_imports - Trailing commas:
require_trailing_commas - Final locals:
prefer_final_locals - Additional rules:
directives_ordering,avoid_void_async,always_declare_return_types,avoid_redundant_argument_values,unnecessary_parenthesis
Important: .g.dart files are excluded from analysis but must be committed to source control.
Common Patterns
MobX Reactions
late final ReactionDisposer _disposeReaction;
_disposeReaction = reaction(
(_) => authStore.isLoggedIn,
(_) => _selectedIndex = 0,
);
Settings Persistence
Auto-saving pattern in main.dart:
autorun((_) => prefs.setString('settings', jsonEncode(settingsStore)));
Error Handling
API services use typed exceptions via BaseApiClient (lib/apis/base_api_client.dart):
ApiException,NetworkException,TimeoutException,ServerException,NotFoundException,UnauthorizedException
MobX Store Implementation
Store Pattern
All stores follow StoreBase with _$StoreName pattern:
- Generate
.g.dartfiles withdart run build_runner build - Use
@observable,@action, and@computedannotations - Settings store uses
@JsonSerializable()with automatic persistence viaautorun()
Authentication Headers
Generated as @computed properties that automatically update when tokens change.
State Persistence
Settings automatically saved to SharedPreferences via MobX autorun() reaction.
Custom Cache Management
- Orphaned File Cleanup:
CustomCacheManager.removeOrphanedCacheFiles()runs on startup to remove files not in database - Optimized Settings: 30-day stale period, 10,000 max objects for efficient image caching across the app
Code Style Guidelines
- Prefer modern Flutter/Dart features and type-safety
- Use consistent naming, comments, and styles matching the existing codebase
- Single quotes, trailing commas, and final locals per lint rules
- Package imports over relative imports
- Observer widgets only wrap necessary UI components for MobX optimization
Platform Support
- iOS/Android: Native platform features via plugins
- Custom Cache:
CustomCacheManagerfor media caching - PiP Mode: Custom implementation via git dependency
Commit Convention
Commits use lowercase, descriptive messages without prefixes (e.g., fix landscape bottom padding in chat bottom bar, add swipe pip gesture support). Keep commits tightly scoped.
When working with this codebase, always consider MobX code generation requirements and the shared HTTP client pattern for API efficiency.