Files
deflock-app/lib/app_state.dart
2025-08-21 18:39:09 -05:00

212 lines
5.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:latlong2/latlong.dart';
import 'models/camera_profile.dart';
import 'models/pending_upload.dart';
import 'services/offline_area_service.dart';
import 'state/auth_state.dart';
import 'state/profile_state.dart';
import 'state/session_state.dart';
import 'state/settings_state.dart';
import 'state/upload_queue_state.dart';
// Re-export types for backward compatibility
export 'state/settings_state.dart' show UploadMode;
export 'state/session_state.dart' show AddCameraSession;
// ------------------ AppState ------------------
class AppState extends ChangeNotifier {
static late AppState instance;
// State modules
late final AuthState _authState;
late final ProfileState _profileState;
late final SessionState _sessionState;
late final SettingsState _settingsState;
late final UploadQueueState _uploadQueueState;
bool _isInitialized = false;
AppState() {
instance = this;
_authState = AuthState();
_profileState = ProfileState();
_sessionState = SessionState();
_settingsState = SettingsState();
_uploadQueueState = UploadQueueState();
// Set up state change listeners
_authState.addListener(_onStateChanged);
_profileState.addListener(_onStateChanged);
_sessionState.addListener(_onStateChanged);
_settingsState.addListener(_onStateChanged);
_uploadQueueState.addListener(_onStateChanged);
_init();
}
// Getters that delegate to individual state modules
bool get isInitialized => _isInitialized;
// Auth state
bool get isLoggedIn => _authState.isLoggedIn;
String get username => _authState.username;
// Profile state
List<CameraProfile> get profiles => _profileState.profiles;
List<CameraProfile> get enabledProfiles => _profileState.enabledProfiles;
bool isEnabled(CameraProfile p) => _profileState.isEnabled(p);
// Session state
AddCameraSession? get session => _sessionState.session;
// Settings state
bool get offlineMode => _settingsState.offlineMode;
int get maxCameras => _settingsState.maxCameras;
UploadMode get uploadMode => _settingsState.uploadMode;
// Upload queue state
int get pendingCount => _uploadQueueState.pendingCount;
List<PendingUpload> get pendingUploads => _uploadQueueState.pendingUploads;
void _onStateChanged() {
notifyListeners();
}
// ---------- Init ----------
Future<void> _init() async {
// Initialize all state modules
await _settingsState.init();
await _profileState.init();
await _uploadQueueState.init();
await _authState.init(_settingsState.uploadMode);
// Initialize OfflineAreaService to ensure offline areas are loaded
await OfflineAreaService().ensureInitialized();
// Start uploader if conditions are met
_startUploader();
_isInitialized = true;
notifyListeners();
}
// ---------- Auth Methods ----------
Future<void> login() async {
await _authState.login();
}
Future<void> logout() async {
await _authState.logout();
}
Future<void> refreshAuthState() async {
await _authState.refreshAuthState();
}
Future<void> forceLogin() async {
await _authState.forceLogin();
}
Future<bool> validateToken() async {
return await _authState.validateToken();
}
// ---------- Profile Methods ----------
void toggleProfile(CameraProfile p, bool e) {
_profileState.toggleProfile(p, e);
}
void addOrUpdateProfile(CameraProfile p) {
_profileState.addOrUpdateProfile(p);
}
void deleteProfile(CameraProfile p) {
_profileState.deleteProfile(p);
}
// ---------- Session Methods ----------
void startAddSession() {
_sessionState.startAddSession(enabledProfiles);
}
void updateSession({
double? directionDeg,
CameraProfile? profile,
LatLng? target,
}) {
_sessionState.updateSession(
directionDeg: directionDeg,
profile: profile,
target: target,
);
}
void cancelSession() {
_sessionState.cancelSession();
}
void commitSession() {
final session = _sessionState.commitSession();
if (session != null) {
_uploadQueueState.addFromSession(session);
_startUploader();
}
}
// ---------- Settings Methods ----------
Future<void> setOfflineMode(bool enabled) async {
await _settingsState.setOfflineMode(enabled);
if (!enabled) {
_startUploader(); // Resume upload queue processing as we leave offline mode
} else {
_uploadQueueState.stopUploader(); // Stop uploader in offline mode
}
}
set maxCameras(int n) {
_settingsState.maxCameras = n;
}
Future<void> setUploadMode(UploadMode mode) async {
await _settingsState.setUploadMode(mode);
await _authState.onUploadModeChanged(mode);
_startUploader(); // Restart uploader with new mode
}
// ---------- Queue Methods ----------
void clearQueue() {
_uploadQueueState.clearQueue();
}
void removeFromQueue(PendingUpload upload) {
_uploadQueueState.removeFromQueue(upload);
}
void retryUpload(PendingUpload upload) {
_uploadQueueState.retryUpload(upload);
_startUploader(); // resume uploader if not busy
}
// ---------- Private Methods ----------
void _startUploader() {
_uploadQueueState.startUploader(
offlineMode: offlineMode,
uploadMode: uploadMode,
getAccessToken: _authState.getAccessToken,
);
}
@override
void dispose() {
_authState.removeListener(_onStateChanged);
_profileState.removeListener(_onStateChanged);
_sessionState.removeListener(_onStateChanged);
_settingsState.removeListener(_onStateChanged);
_uploadQueueState.removeListener(_onStateChanged);
_uploadQueueState.dispose();
super.dispose();
}
}