Files
kooltab/lib/viewmodels/settings_view_model.dart
T
2026-10-08 04:12:36 +02:00

138 lines
3.5 KiB
Dart

import 'package:flutter/foundation.dart';
import 'package:ota_update/ota_update.dart';
import '../models/app_error.dart';
import '../models/settings.dart';
import '../services/settings_service.dart';
import '../utils/app_config.dart';
import '../utils/app_update_util.dart';
class SettingsViewModel extends ChangeNotifier {
final SettingsService settingsService;
SettingsViewModel({required this.settingsService});
AppSettings _settings = AppSettings.defaults;
bool _isLoading = false;
bool _hasLoaded = false;
AppError? _error;
final AppUpdateUtil _updater = AppUpdateUtil(serverUrl: kUpdateServerUrl);
bool _checkingForUpdates = false;
bool get checkingForUpdates => _checkingForUpdates;
AppSettings get settings => _settings;
bool get isLoading => _isLoading;
bool get hasLoaded => _hasLoaded;
AppError? get error => _error;
Future<void> ensureLoaded() async {
if (_hasLoaded || _isLoading) return;
await load();
}
Future<void> load() async {
if (_isLoading) return;
_isLoading = true;
_error = null;
notifyListeners();
try {
_settings = await settingsService.getSettings();
} catch (e) {
debugPrint('SettingsViewModel: load error: $e');
_error = AppError.loadSettings;
} finally {
_hasLoaded = true;
_isLoading = false;
notifyListeners();
}
}
Future<UpdateInfo?> checkForUpdates() async {
if (_checkingForUpdates) return null;
_checkingForUpdates = true;
notifyListeners();
try {
return await _updater.checkForUpdate();
} finally {
_checkingForUpdates = false;
notifyListeners();
}
}
Future<void> installUpdate(
UpdateInfo update, {
void Function(double progress)? onProgress,
}) async {
final url = update.download.startsWith('http')
? update.download
: '$kUpdateServerUrl${update.download}';
debugPrint('Download Url: $url');
final stream = OtaUpdate().execute(
url,
destinationFilename: 'update.apk',
sha256checksum: update.sha256,
);
await for (final event in stream) {
debugPrint('OTA: ${event.status} ${event.value}');
if (event.status == OtaStatus.DOWNLOADING) {
final progress = double.tryParse(event.value ?? '0') ?? 0;
onProgress?.call(progress / 100);
}
if (event.status == OtaStatus.DOWNLOAD_ERROR) {
throw Exception('Download failed: ${event.value}');
}
if (event.status == OtaStatus.INSTALLATION_ERROR) {
throw Exception('Installation failed: ${event.value}');
}
}
}
Future<void> updatePinRequired(bool value) =>
_save(_settings.copyWith(pinRequired: value));
Future<void> updateAutoLockEnabled(bool value) =>
_save(_settings.copyWith(autoLockEnabled: value));
Future<void> updateThemeMode(AppThemeMode mode) =>
_save(_settings.copyWith(themeMode: mode));
Future<void> updateLanguage(AppLanguage language) =>
_save(_settings.copyWith(language: language));
Future<void> updateBarGridRows(int rows) =>
_save(_settings.copyWith(barGridRows: rows.clamp(2, 6).toInt()));
Future<void> _save(AppSettings updated) async {
final previous = _settings;
_settings = updated;
_error = null;
notifyListeners();
try {
await settingsService.saveSettings(updated);
} catch (e) {
debugPrint('SettingsViewModel: save error: $e');
_settings = previous;
_error = AppError.saveSettings;
notifyListeners();
}
}
}