Skip to content

Commit

Permalink
refactor: Improve alarm handler
Browse files Browse the repository at this point in the history
  • Loading branch information
Myzel394 committed Sep 24, 2023
1 parent a498beb commit 9e433ab
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 170 deletions.
2 changes: 0 additions & 2 deletions lib/screens/LocationsOverviewScreen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,6 @@ class _LocationsOverviewScreenState extends State<LocationsOverviewScreen>
}

void _initLiveLocationUpdate() {
final settings = context.read<SettingsService>();

if (_positionStream != null) {
return;
}
Expand Down
162 changes: 82 additions & 80 deletions lib/services/manager_service/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,87 +122,90 @@ Future<void> checkViewAlarms({
);

for (final view in views) {
await view.checkAlarm(
userLocation: userLocation,
onTrigger: (alarm, location, _) async {
final notifications = FlutterLocalNotificationsPlugin();
final id = int.parse(
"${location.createdAt.millisecond}${location.createdAt.microsecond}",
);

if (alarm is GeoLocationAlarm) {
notifications.show(
id,
StringUtils.truncate(
alarm.type == LocationRadiusBasedTriggerType.whenEnter
? l10n
.locationAlarm_radiusBasedRegion_notificationTitle_whenEnter(
view.name,
alarm.zoneName,
)
: l10n
.locationAlarm_radiusBasedRegion_notificationTitle_whenLeave(
view.name,
alarm.zoneName,
),
76,
),
l10n.locationAlarm_notification_description,
NotificationDetails(
android: AndroidNotificationDetails(
AndroidChannelIDs.locationAlarms.name,
l10n.androidNotificationChannel_locationAlarms_name,
channelDescription:
l10n.androidNotificationChannel_locationAlarms_description,
importance: Importance.high,
priority: Priority.high,
),
),
payload: jsonEncode({
"type": NotificationActionType.openTaskView.index,
"taskViewID": view.id,
}),
);
return;
}

if (alarm is ProximityLocationAlarm) {
notifications.show(
id,
StringUtils.truncate(
alarm.type == LocationRadiusBasedTriggerType.whenEnter
? l10n
.locationAlarm_proximityLocation_notificationTitle_whenEnter(
view.name,
alarm.radius.round(),
)
: l10n
.locationAlarm_proximityLocation_notificationTitle_whenLeave(
view.name,
alarm.radius.round(),
),
76,
final data = await view.alarmHandler.checkAlarm(
userLocation,
);
final triggerResponse = data.$1;
final alarm = data.$2;
final location = data.$3;

if (triggerResponse == LocationAlarmTriggerType.yes) {
final notifications = FlutterLocalNotificationsPlugin();
final id = int.parse(
"${view.id}-${alarm!.id}",
);

if (alarm is GeoLocationAlarm) {
notifications.show(
id,
StringUtils.truncate(
alarm.type == LocationRadiusBasedTriggerType.whenEnter
? l10n
.locationAlarm_radiusBasedRegion_notificationTitle_whenEnter(
view.name,
alarm.zoneName,
)
: l10n
.locationAlarm_radiusBasedRegion_notificationTitle_whenLeave(
view.name,
alarm.zoneName,
),
76,
),
l10n.locationAlarm_notification_description,
NotificationDetails(
android: AndroidNotificationDetails(
AndroidChannelIDs.locationAlarms.name,
l10n.androidNotificationChannel_locationAlarms_name,
channelDescription:
l10n.androidNotificationChannel_locationAlarms_description,
importance: Importance.high,
priority: Priority.high,
),
l10n.locationAlarm_notification_description,
NotificationDetails(
android: AndroidNotificationDetails(
AndroidChannelIDs.locationAlarms.name,
l10n.androidNotificationChannel_locationAlarms_name,
channelDescription:
l10n.androidNotificationChannel_locationAlarms_description,
importance: Importance.max,
priority: Priority.max,
),
),
payload: jsonEncode({
"type": NotificationActionType.openTaskView.index,
"taskViewID": view.id,
}),
);
return;
}

if (alarm is ProximityLocationAlarm) {
notifications.show(
id,
StringUtils.truncate(
alarm.type == LocationRadiusBasedTriggerType.whenEnter
? l10n
.locationAlarm_proximityLocation_notificationTitle_whenEnter(
view.name,
alarm.radius.round(),
)
: l10n
.locationAlarm_proximityLocation_notificationTitle_whenLeave(
view.name,
alarm.radius.round(),
),
76,
),
l10n.locationAlarm_notification_description,
NotificationDetails(
android: AndroidNotificationDetails(
AndroidChannelIDs.locationAlarms.name,
l10n.androidNotificationChannel_locationAlarms_name,
channelDescription:
l10n.androidNotificationChannel_locationAlarms_description,
importance: Importance.max,
priority: Priority.max,
),
payload: jsonEncode({
"type": NotificationActionType.openTaskView.index,
"taskViewID": view.id,
}),
);
}
},
onMaybeTrigger: (alarm, _, __) async {},
);
),
payload: jsonEncode({
"type": NotificationActionType.openTaskView.index,
"taskViewID": view.id,
}),
);
}
}
}

FlutterLogs.logInfo(
Expand All @@ -225,7 +228,6 @@ Future<void> checkViewAlarmsFromBackground(
required final AppLocalizations l10n,
}) async {
final viewService = await ViewService.restore();
final settings = await SettingsService.restore();

if (viewService.viewsWithAlarms.isEmpty) {
return;
Expand Down
89 changes: 89 additions & 0 deletions lib/services/view_service/alarm_handler.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import 'package:flutter_logs/flutter_logs.dart';
import 'package:locus/constants/values.dart';
import 'package:locus/services/location_alarm_service/LocationAlarmServiceBase.dart';
import 'package:locus/services/location_alarm_service/enums.dart';
import 'package:locus/services/location_fetcher_service/Fetcher.dart';
import 'package:locus/services/location_point_service.dart';
import 'package:locus/services/view_service/index.dart';
import 'package:locus/utils/nostr_fetcher/NostrSocket.dart';
import 'package:nostr/nostr.dart';

class AlarmHandler {
final TaskView view;

const AlarmHandler(this.view);

Future<
(LocationAlarmTriggerType, LocationAlarmServiceBase?, LocationPointService?)> checkAlarm(
final LocationPointService userLocation,) async {
FlutterLogs.logInfo(
LOG_TAG,
"Headless Task; Check View Alarms",
"Checking view ${view.name} from ${view.lastAlarmCheck}...",
);

final fetcher = Fetcher(view);
await fetcher.fetchCustom(
Request(
generate64RandomHexChars(),
[
NostrSocket.createNostrRequestDataFromTask(
view,
from: view.lastAlarmCheck,
),
],
),
);
final locations = fetcher.sortedLocations;

view.lastAlarmCheck = DateTime.now();

FlutterLogs.logInfo(
LOG_TAG,
"Headless Task; Check View Alarms",
" -> ${locations.length} locations",
);

if (locations.isEmpty) {
FlutterLogs.logInfo(
LOG_TAG,
"Headless Task; Check View Alarms",
" -> No locations",
);

return (LocationAlarmTriggerType.no, null, null);
}

locations.sort((a, b) => a.createdAt.compareTo(b.createdAt));

LocationPointService oldLocation = locations.first;

// Iterate over each location but the first one
// Iterating backwards to check the last locations first,
// if we miss an old location, it's not that bad, newer data
// is more important
// Return on first found to not spam the user with multiple alarms
for (final location in locations
.skip(1)
.toList()
.reversed) {
for (final alarm in view.alarms) {
final checkResult = alarm.check(
location,
oldLocation,
userLocation: userLocation,
);

if (checkResult == LocationAlarmTriggerType.yes) {
return (LocationAlarmTriggerType.yes, alarm, location);
} else if (checkResult == LocationAlarmTriggerType.maybe) {
return (LocationAlarmTriggerType.maybe, alarm, location);
}
}

oldLocation = location;
}

return (LocationAlarmTriggerType.no, null, null);
}
}
Loading

0 comments on commit 9e433ab

Please sign in to comment.