Files
xtremobile/lib/core/providers/theme_provider.dart
T
MichaelandClaude Sonnet 4.6 6bb0d73f38 fix: restore EPG display in live TV player and channel cards
- Fix EPG not showing in NativePlayerScreen by reusing the shared
  mobileXtreamServiceProvider (cache already populated by channel cards)
  instead of creating a fresh service instance per player session
- Add periodic EPG refresh timer (every 5 min) matching LitePlayerScreen
- Fix empty-title fallback in _buildEPGBox
- Force dark theme, invert default live TV player (NativePlayer default),
  remove next-program display from OSD
- Fix back button exit dialog firing from wrong tab (add tab index guards)
- Halve card grid count for Movies/Series (6 categories, 8 items)
- Revamp Movies/Series search bars to match Live TV aesthetic
- Fix first channel row clipping when entering a category (scroll-to-top)
- Fix playlist edit dialog TV remote navigation
- Fix empty playlist screen button readability
- Remove theme switcher from settings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 10:04:47 +02:00

94 lines
2.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
/// Theme mode preference options
enum AppThemeMode {
system, // Follow system preference
light, // Force light mode
dark, // Force dark mode
}
/// Keys for SharedPreferences storage
class _ThemeKeys {
static const String themeMode = 'app_theme_mode';
}
/// Theme state containing current mode
class ThemeState {
final AppThemeMode appThemeMode;
final ThemeMode themeMode;
const ThemeState({
this.appThemeMode = AppThemeMode.dark,
this.themeMode = ThemeMode.dark,
});
ThemeState copyWith({
AppThemeMode? appThemeMode,
ThemeMode? themeMode,
}) {
return ThemeState(
appThemeMode: appThemeMode ?? this.appThemeMode,
themeMode: themeMode ?? this.themeMode,
);
}
}
/// Theme provider for managing light/dark mode with persistence
class ThemeNotifier extends StateNotifier<ThemeState> {
ThemeNotifier() : super(const ThemeState()) {
_loadTheme();
}
/// Theme is always forced to dark — no loading from preferences
Future<void> _loadTheme() async {}
/// Set theme mode and persist to SharedPreferences
Future<void> setThemeMode(AppThemeMode mode) async {
state = state.copyWith(
appThemeMode: mode,
themeMode: _mapToThemeMode(mode),
);
try {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_ThemeKeys.themeMode, mode.name);
} catch (e) {
debugPrint('Error saving theme: $e');
}
}
/// Quick toggle between light and dark (skip system)
Future<void> toggleTheme() async {
final newMode = state.appThemeMode == AppThemeMode.dark
? AppThemeMode.light
: AppThemeMode.dark;
await setThemeMode(newMode);
}
/// Check if currently in dark mode
bool get isDarkMode {
return state.themeMode == ThemeMode.dark ||
(state.themeMode == ThemeMode.system &&
WidgetsBinding.instance.platformDispatcher.platformBrightness == Brightness.dark);
}
/// Map AppThemeMode to Flutter's ThemeMode
ThemeMode _mapToThemeMode(AppThemeMode mode) {
switch (mode) {
case AppThemeMode.system:
return ThemeMode.system;
case AppThemeMode.light:
return ThemeMode.light;
case AppThemeMode.dark:
return ThemeMode.dark;
}
}
}
/// Provider for theme state
final themeProvider = StateNotifierProvider<ThemeNotifier, ThemeState>((ref) {
return ThemeNotifier();
});