Settings, correção de light/darkmode do dispositivo (e adição da escolha entre modos nas settings) e correção do tipo de letra no textfield do chatbot
This commit is contained in:
85
lib/core/providers/theme_provider.dart
Normal file
85
lib/core/providers/theme_provider.dart
Normal file
@@ -0,0 +1,85 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../services/theme_service.dart';
|
||||
|
||||
/// Provider for theme management
|
||||
final themeProvider = StateNotifierProvider<ThemeNotifier, ThemeMode>((ref) {
|
||||
return ThemeNotifier();
|
||||
});
|
||||
|
||||
/// Notifier for managing theme state
|
||||
class ThemeNotifier extends StateNotifier<ThemeMode> {
|
||||
ThemeNotifier() : super(ThemeMode.light) {
|
||||
_initializeTheme();
|
||||
}
|
||||
|
||||
/// Initialize theme from storage
|
||||
Future<void> _initializeTheme() async {
|
||||
try {
|
||||
final storedTheme = await ThemeService.getThemeMode();
|
||||
state = storedTheme;
|
||||
} catch (e) {
|
||||
state = ThemeMode.light;
|
||||
}
|
||||
}
|
||||
|
||||
/// Change theme mode
|
||||
Future<void> setThemeMode(ThemeMode themeMode) async {
|
||||
// For now, only allow light mode
|
||||
// Future: Allow dark mode when available
|
||||
if (themeMode == ThemeMode.light || ThemeService.isDarkModeAvailable()) {
|
||||
state = themeMode;
|
||||
await ThemeService.setThemeMode(themeMode);
|
||||
}
|
||||
}
|
||||
|
||||
/// Toggle between light and dark mode (for future use)
|
||||
Future<void> toggleTheme() async {
|
||||
if (ThemeService.isDarkModeAvailable()) {
|
||||
final newTheme = state == ThemeMode.light
|
||||
? ThemeMode.dark
|
||||
: ThemeMode.light;
|
||||
await setThemeMode(newTheme);
|
||||
}
|
||||
}
|
||||
|
||||
/// Reset to default theme
|
||||
Future<void> resetTheme() async {
|
||||
await setThemeMode(ThemeMode.light);
|
||||
}
|
||||
|
||||
/// Check if current theme is dark
|
||||
bool isDarkMode() {
|
||||
return state == ThemeMode.dark;
|
||||
}
|
||||
|
||||
/// Check if current theme is light
|
||||
bool isLightMode() {
|
||||
return state == ThemeMode.light;
|
||||
}
|
||||
|
||||
/// Get current theme as string
|
||||
String get currentThemeString {
|
||||
return ThemeService.getThemeModeString(state);
|
||||
}
|
||||
|
||||
/// Initialize theme from storage (for future use)
|
||||
Future<void> initializeTheme() async {
|
||||
final storedTheme = await ThemeService.getStoredThemeMode();
|
||||
// Only set if dark mode is available or if it's light mode
|
||||
if (storedTheme == ThemeMode.light || ThemeService.isDarkModeAvailable()) {
|
||||
state = storedTheme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Provider for checking if dark mode is available
|
||||
final isDarkModeAvailableProvider = Provider<bool>((ref) {
|
||||
return ThemeService.isDarkModeAvailable();
|
||||
});
|
||||
|
||||
/// Provider for current theme string
|
||||
final themeStringProvider = Provider<String>((ref) {
|
||||
final theme = ref.watch(themeProvider);
|
||||
return ThemeService.getThemeModeString(theme);
|
||||
});
|
||||
@@ -1,5 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import '../../shared/presentation/pages/not_found_page.dart';
|
||||
import '../../features/settings/presentation/pages/settings_page.dart';
|
||||
import '../../features/settings/presentation/pages/profile_edit_page.dart';
|
||||
import '../../features/settings/presentation/pages/help_page.dart';
|
||||
import '../../features/auth/presentation/pages/login_page.dart';
|
||||
import '../../features/auth/presentation/pages/signup_page.dart';
|
||||
import '../../features/dashboard/presentation/pages/student_dashboard_page.dart';
|
||||
@@ -10,7 +14,6 @@ import '../../features/quiz/presentation/pages/quiz_page.dart';
|
||||
import '../../features/profile/presentation/pages/profile_page.dart';
|
||||
import '../../features/splash/presentation/pages/splash_page.dart';
|
||||
import '../../features/auth/presentation/pages/role_selection_page.dart';
|
||||
import '../../shared/presentation/pages/not_found_page.dart';
|
||||
|
||||
/// App Router Configuration
|
||||
class AppRouter {
|
||||
@@ -24,6 +27,7 @@ class AppRouter {
|
||||
static const String quizList = '/quiz';
|
||||
static const String quiz = '/quiz/:quizId';
|
||||
static const String profile = '/profile';
|
||||
static const String settings = '/settings';
|
||||
|
||||
// Nested route paths (without leading slash)
|
||||
static const String tutorNested = 'tutor';
|
||||
@@ -50,53 +54,28 @@ class AppRouter {
|
||||
builder: (context, state) => const RoleSelectionPage(),
|
||||
),
|
||||
|
||||
// Authentication Routes
|
||||
// Login
|
||||
GoRoute(
|
||||
path: login,
|
||||
name: 'login',
|
||||
builder: (context, state) {
|
||||
final selectedRole = state.uri.queryParameters['role'];
|
||||
return LoginPage(selectedRole: selectedRole);
|
||||
},
|
||||
builder: (context, state) => const LoginPage(),
|
||||
),
|
||||
|
||||
// Signup
|
||||
GoRoute(
|
||||
path: signup,
|
||||
name: 'signup',
|
||||
builder: (context, state) {
|
||||
final selectedRole = state.uri.queryParameters['role'];
|
||||
return SignupPage(selectedRole: selectedRole);
|
||||
},
|
||||
builder: (context, state) => const SignupPage(),
|
||||
),
|
||||
|
||||
// Dashboard Routes
|
||||
// Student Dashboard
|
||||
GoRoute(
|
||||
path: studentDashboard,
|
||||
name: 'studentDashboard',
|
||||
builder: (context, state) => const StudentDashboardPage(),
|
||||
routes: [
|
||||
// Nested routes for student features
|
||||
GoRoute(
|
||||
path: tutorNested,
|
||||
name: 'studentTutor',
|
||||
builder: (context, state) => const TutorChatPageSimple(),
|
||||
),
|
||||
GoRoute(
|
||||
path: quizListNested,
|
||||
name: 'quizList',
|
||||
builder: (context, state) => const QuizListPage(),
|
||||
),
|
||||
GoRoute(
|
||||
path: quizNested,
|
||||
name: 'quiz',
|
||||
builder: (context, state) {
|
||||
final quizId = state.pathParameters['quizId']!;
|
||||
return QuizPage(quizId: quizId);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// Teacher Dashboard
|
||||
GoRoute(
|
||||
path: teacherDashboard,
|
||||
name: 'teacherDashboard',
|
||||
@@ -131,6 +110,27 @@ class AppRouter {
|
||||
builder: (context, state) => const ProfilePage(),
|
||||
),
|
||||
|
||||
// Settings Route
|
||||
GoRoute(
|
||||
path: settings,
|
||||
name: 'settings',
|
||||
builder: (context, state) => const SettingsPage(),
|
||||
routes: [
|
||||
// Profile Edit Route
|
||||
GoRoute(
|
||||
path: 'profile-edit',
|
||||
name: 'profileEdit',
|
||||
builder: (context, state) => const ProfileEditPage(),
|
||||
),
|
||||
// Help Route
|
||||
GoRoute(
|
||||
path: 'help',
|
||||
name: 'help',
|
||||
builder: (context, state) => const HelpPage(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// AI Tutor Route (independent)
|
||||
GoRoute(
|
||||
path: tutor,
|
||||
@@ -179,6 +179,10 @@ class AppRouter {
|
||||
context.go(profile);
|
||||
}
|
||||
|
||||
static void goToSettings(BuildContext context) {
|
||||
context.go(settings);
|
||||
}
|
||||
|
||||
static void goBack(BuildContext context) {
|
||||
context.pop();
|
||||
}
|
||||
|
||||
95
lib/core/services/theme_service.dart
Normal file
95
lib/core/services/theme_service.dart
Normal file
@@ -0,0 +1,95 @@
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../utils/logger.dart';
|
||||
|
||||
/// Service for managing app theme preferences
|
||||
class ThemeService {
|
||||
static const String _themeKey = 'app_theme_mode';
|
||||
static const ThemeMode _defaultTheme = ThemeMode.light;
|
||||
|
||||
/// Get current theme mode from storage
|
||||
static Future<ThemeMode> getThemeMode() async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final themeString = prefs.getString(_themeKey);
|
||||
|
||||
if (themeString == null) {
|
||||
return _defaultTheme;
|
||||
}
|
||||
|
||||
switch (themeString) {
|
||||
case 'ThemeMode.light':
|
||||
return ThemeMode.light;
|
||||
case 'ThemeMode.dark':
|
||||
return ThemeMode.dark;
|
||||
case 'ThemeMode.system':
|
||||
return ThemeMode.system;
|
||||
default:
|
||||
return _defaultTheme;
|
||||
}
|
||||
} catch (e) {
|
||||
Logger.error('Error getting theme mode: $e');
|
||||
return _defaultTheme;
|
||||
}
|
||||
}
|
||||
|
||||
/// Save theme mode to storage
|
||||
static Future<void> setThemeMode(ThemeMode themeMode) async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(_themeKey, themeMode.toString());
|
||||
Logger.info('Theme mode saved: ${themeMode.toString()}');
|
||||
} catch (e) {
|
||||
Logger.error('Error saving theme mode: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Get theme mode from storage (for future use)
|
||||
static Future<ThemeMode> getStoredThemeMode() async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final themeString = prefs.getString(_themeKey);
|
||||
|
||||
if (themeString == null) {
|
||||
return _defaultTheme;
|
||||
}
|
||||
|
||||
switch (themeString) {
|
||||
case 'ThemeMode.light':
|
||||
return ThemeMode.light;
|
||||
case 'ThemeMode.dark':
|
||||
return ThemeMode.dark;
|
||||
case 'ThemeMode.system':
|
||||
return ThemeMode.system;
|
||||
default:
|
||||
return _defaultTheme;
|
||||
}
|
||||
} catch (e) {
|
||||
Logger.error('Error getting stored theme mode: $e');
|
||||
return _defaultTheme;
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if dark mode is available (for future settings)
|
||||
static bool isDarkModeAvailable() {
|
||||
// Dark mode is now available
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Get theme mode string for display
|
||||
static String getThemeModeString(ThemeMode themeMode) {
|
||||
switch (themeMode) {
|
||||
case ThemeMode.light:
|
||||
return 'Light Mode';
|
||||
case ThemeMode.dark:
|
||||
return 'Dark Mode';
|
||||
case ThemeMode.system:
|
||||
return 'System Default';
|
||||
}
|
||||
}
|
||||
|
||||
/// Reset theme to default
|
||||
static Future<void> resetTheme() async {
|
||||
await setThemeMode(_defaultTheme);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user