import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:geolocator/geolocator.dart'; import '../../homes/providers/homes_providers.dart'; import '../../shared/providers/core_providers.dart'; import '../models/app_theme_preset.dart'; import '../models/geofence_system_state.dart'; import '../models/notification_permission_status.dart'; final initialAppThemePresetProvider = Provider( (ref) => AppThemePreset.fallback, ); final appThemeProvider = NotifierProvider( AppThemeNotifier.new, ); class AppThemeNotifier extends Notifier { @override AppThemePreset build() => ref.read(initialAppThemePresetProvider); Future setTheme(AppThemePreset preset) async { if (state == preset) { return; } state = preset; await ref.read(settingsServiceProvider).setAppThemePreset(preset); } } abstract class GeofenceSystemStatusService { Future inspect({ required bool hasActiveHome, required bool hasCoordinates, }); } class DeviceGeofenceSystemStatusService implements GeofenceSystemStatusService { @override Future inspect({ required bool hasActiveHome, required bool hasCoordinates, }) async { if (!hasActiveHome) { return const GeofenceSystemState(GeofenceSystemIssue.noActiveHome); } if (!hasCoordinates) { return const GeofenceSystemState(GeofenceSystemIssue.missingCoordinates); } if (!await Geolocator.isLocationServiceEnabled()) { return const GeofenceSystemState( GeofenceSystemIssue.locationServicesDisabled, ); } final permission = await Geolocator.checkPermission(); return switch (permission) { LocationPermission.denied => const GeofenceSystemState( GeofenceSystemIssue.permissionDenied, ), LocationPermission.deniedForever => const GeofenceSystemState( GeofenceSystemIssue.permissionDeniedForever, ), LocationPermission.whileInUse => const GeofenceSystemState( GeofenceSystemIssue.backgroundPermissionRequired, ), LocationPermission.always => const GeofenceSystemState( GeofenceSystemIssue.ready, ), _ => const GeofenceSystemState(GeofenceSystemIssue.permissionDenied), }; } } final geofenceSystemStatusServiceProvider = Provider( (ref) => DeviceGeofenceSystemStatusService(), ); final geofenceSystemStatusProvider = FutureProvider(( ref, ) async { final currentHome = ref.watch(currentHomeProvider); return ref .watch(geofenceSystemStatusServiceProvider) .inspect( hasActiveHome: currentHome != null, hasCoordinates: currentHome?.hasCoordinates == true, ); }); abstract class NotificationPermissionStatusService { Future inspect(); Future openSettings(); } class DeviceNotificationPermissionStatusService implements NotificationPermissionStatusService { static const _channel = MethodChannel('ignis/geofence_automation'); @override Future inspect() async { try { final value = await _channel.invokeMethod( 'getNotificationPermissionStatus', ); return NotificationPermissionStatus.fromPlatformValue(value); } on MissingPluginException { return NotificationPermissionStatus.unsupported; } } @override Future openSettings() async { try { await _channel.invokeMethod('openNotificationSettings'); } on MissingPluginException { return; } } } final notificationPermissionStatusServiceProvider = Provider( (ref) => DeviceNotificationPermissionStatusService(), ); final notificationPermissionStatusProvider = FutureProvider((ref) async { return ref.watch(notificationPermissionStatusServiceProvider).inspect(); });