Files
worker/APP_SETTINGS.md
2025-12-01 11:31:26 +07:00

257 lines
6.5 KiB
Markdown

# App Settings & Theme System
## Overview
The app uses a centralized `AppSettingsBox` (Hive) for storing all app-level settings. This includes theme preferences, language settings, notification preferences, and other user configurations.
---
## AppSettingsBox
**Location**: `lib/core/database/app_settings_box.dart`
### Initialization
```dart
// In main.dart - call before runApp()
await AppSettingsBox.init();
```
### Storage Keys
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| **Theme** |
| `seed_color_id` | String | `'blue'` | Selected theme color ID |
| `theme_mode` | int | `0` | 0=system, 1=light, 2=dark |
| **Language** |
| `language_code` | String | `'vi'` | Language code (vi, en) |
| **Notifications** |
| `notifications_enabled` | bool | `true` | Master notification toggle |
| `order_notifications` | bool | `true` | Order status notifications |
| `promotion_notifications` | bool | `true` | Promotion notifications |
| `chat_notifications` | bool | `true` | Chat message notifications |
| **User Preferences** |
| `onboarding_completed` | bool | `false` | Onboarding flow completed |
| `biometric_enabled` | bool | `false` | Biometric login enabled |
| `remember_login` | bool | `false` | Remember login credentials |
| **App State** |
| `last_sync_time` | String | - | Last data sync timestamp |
| `app_version` | String | - | Last launched app version |
| `first_launch_date` | String | - | First app launch date |
### Usage
```dart
// Generic get/set
AppSettingsBox.get<String>('key', defaultValue: 'default');
await AppSettingsBox.set('key', value);
// Helper methods
AppSettingsBox.getSeedColorId(); // Returns 'blue', 'teal', etc.
await AppSettingsBox.setSeedColorId('teal');
AppSettingsBox.getThemeModeIndex(); // Returns 0, 1, or 2
await AppSettingsBox.setThemeModeIndex(1);
AppSettingsBox.getLanguageCode(); // Returns 'vi' or 'en'
await AppSettingsBox.setLanguageCode('en');
AppSettingsBox.areNotificationsEnabled(); // Returns true/false
AppSettingsBox.isOnboardingCompleted();
AppSettingsBox.isBiometricEnabled();
```
---
## Theme System
### Architecture
```
colors.dart → Seed color options & status colors
app_theme.dart → ThemeData generation from seed color
theme_provider.dart → Riverpod state management
```
### Available Seed Colors
| ID | Name | Color |
|----|------|-------|
| `blue` | Xanh dương | `#005B9A` (default) |
| `teal` | Xanh ngọc | `#009688` |
| `green` | Xanh lá | `#4CAF50` |
| `purple` | Tím | `#673AB7` |
| `indigo` | Chàm | `#3F51B5` |
| `orange` | Cam | `#FF5722` |
| `red` | Đỏ | `#E53935` |
| `pink` | Hồng | `#E91E63` |
### Providers
```dart
// Main theme settings provider (persisted)
themeSettingsProvider
// Convenience providers
currentSeedColorProvider // Color - current seed color
seedColorOptionsProvider // List<SeedColorOption> - all options
```
### Usage in App
```dart
// app.dart - Dynamic theme
class MyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final settings = ref.watch(themeSettingsProvider);
return MaterialApp(
theme: AppTheme.lightTheme(settings.seedColor),
darkTheme: AppTheme.darkTheme(settings.seedColor),
themeMode: settings.themeMode,
// ...
);
}
}
```
### Changing Theme
```dart
// Change seed color
ref.read(themeSettingsProvider.notifier).setSeedColor('teal');
// Change theme mode
ref.read(themeSettingsProvider.notifier).setThemeMode(ThemeMode.dark);
// Toggle light/dark
ref.read(themeSettingsProvider.notifier).toggleThemeMode();
```
### Color Picker Widget Example
```dart
class ColorPickerWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final options = ref.watch(seedColorOptionsProvider);
final current = ref.watch(themeSettingsProvider);
return Wrap(
spacing: 8,
children: options.map((option) {
final isSelected = option.id == current.seedColorId;
return GestureDetector(
onTap: () => ref
.read(themeSettingsProvider.notifier)
.setSeedColor(option.id),
child: Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: option.color,
shape: BoxShape.circle,
border: isSelected
? Border.all(color: Colors.white, width: 3)
: null,
),
child: isSelected
? const Icon(Icons.check, color: Colors.white)
: null,
),
);
}).toList(),
);
}
}
```
---
## Using ColorScheme
With the `fromSeed()` approach, always use `Theme.of(context).colorScheme` for colors:
```dart
// Via context extension (recommended)
final cs = context.colorScheme;
// Common color usage
cs.primary // Main brand color (buttons, links)
cs.onPrimary // Text/icons on primary color
cs.primaryContainer // Softer brand background
cs.onPrimaryContainer // Text on primaryContainer
cs.secondary // Secondary accent
cs.tertiary // Third accent color
cs.surface // Card/container backgrounds
cs.onSurface // Primary text color
cs.onSurfaceVariant // Secondary text color
cs.outline // Borders, dividers
cs.outlineVariant // Lighter borders
cs.error // Error states
cs.onError // Text on error
// Example widget
Container(
color: cs.primaryContainer,
child: Text(
'Hello',
style: TextStyle(color: cs.onPrimaryContainer),
),
)
```
### Status Colors (Fixed)
These colors don't change with theme (from backend):
```dart
AppColors.success // #28a745 - Green
AppColors.warning // #ffc107 - Yellow
AppColors.danger // #dc3545 - Red
AppColors.info // #17a2b8 - Blue
```
---
## Files Reference
| File | Purpose |
|------|---------|
| `lib/core/database/app_settings_box.dart` | Hive storage for all app settings |
| `lib/core/theme/colors.dart` | Seed colors, status colors, gradients |
| `lib/core/theme/app_theme.dart` | ThemeData generation |
| `lib/core/theme/theme_provider.dart` | Riverpod providers for theme |
| `lib/core/theme/typography.dart` | Text styles |
---
## Initialization Order
```dart
// main.dart
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// 1. Initialize Hive
await Hive.initFlutter();
// 2. Initialize AppSettingsBox
await AppSettingsBox.init();
// 3. Initialize other boxes...
runApp(
ProviderScope(
child: MyApp(),
),
);
}
```