feat: harden geofence and distance diagnostics
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
|
||||
class GeofenceNotificationsService {
|
||||
final FlutterLocalNotificationsPlugin _plugin;
|
||||
|
||||
GeofenceNotificationsService({FlutterLocalNotificationsPlugin? plugin})
|
||||
: _plugin = plugin ?? FlutterLocalNotificationsPlugin();
|
||||
|
||||
Future<void> initialize() async {
|
||||
if (kIsWeb || defaultTargetPlatform != TargetPlatform.android) {
|
||||
return;
|
||||
}
|
||||
|
||||
const settings = InitializationSettings(
|
||||
android: AndroidInitializationSettings('@mipmap/ic_launcher'),
|
||||
);
|
||||
await _plugin.initialize(settings);
|
||||
}
|
||||
|
||||
Future<bool> areNotificationsEnabled() async {
|
||||
if (kIsWeb || defaultTargetPlatform != TargetPlatform.android) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
final android = _plugin
|
||||
.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin
|
||||
>();
|
||||
return await android?.areNotificationsEnabled() ?? true;
|
||||
} catch (_) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> requestNotificationsPermission() async {
|
||||
if (kIsWeb || defaultTargetPlatform != TargetPlatform.android) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
final android = _plugin
|
||||
.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin
|
||||
>();
|
||||
final granted = await android?.requestNotificationsPermission();
|
||||
return granted ?? await areNotificationsEnabled();
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
53
lib/features/homes/services/geofence_runtime_store.dart
Normal file
53
lib/features/homes/services/geofence_runtime_store.dart
Normal file
@@ -0,0 +1,53 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../models/geofence_runtime_state.dart';
|
||||
|
||||
class GeofenceRuntimeStore {
|
||||
static const String _runtimeKey = 'ignis_geofence_runtime';
|
||||
|
||||
Future<GeofenceRuntimeState> load() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final raw = prefs.getString(_runtimeKey);
|
||||
if (raw == null || raw.isEmpty) {
|
||||
return const GeofenceRuntimeState();
|
||||
}
|
||||
|
||||
final decoded = jsonDecode(raw);
|
||||
if (decoded is! Map<String, dynamic>) {
|
||||
return const GeofenceRuntimeState();
|
||||
}
|
||||
|
||||
return GeofenceRuntimeState.fromJson(decoded);
|
||||
}
|
||||
|
||||
Future<void> save(GeofenceRuntimeState state) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final data = state.toJson();
|
||||
if (data.isEmpty) {
|
||||
await prefs.remove(_runtimeKey);
|
||||
return;
|
||||
}
|
||||
|
||||
await prefs.setString(_runtimeKey, jsonEncode(data));
|
||||
}
|
||||
|
||||
Future<GeofenceRuntimeState> armForHome(String homeId) async {
|
||||
final next = (await load()).armForHome(homeId);
|
||||
await save(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
Future<GeofenceRuntimeState> disarm() async {
|
||||
final next = (await load()).disarm();
|
||||
await save(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
Future<GeofenceRuntimeState> removeHome(String homeId) async {
|
||||
final next = (await load()).removeHome(homeId);
|
||||
await save(next);
|
||||
return next;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user