diff --git a/lib/services/incoming_bus_reminder_service.dart b/lib/services/incoming_bus_reminder_service.dart index e315fd5..3515b32 100644 --- a/lib/services/incoming_bus_reminder_service.dart +++ b/lib/services/incoming_bus_reminder_service.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:bluebus/constants.dart'; import 'package:bluebus/services/notification_service.dart'; +import 'package:flutter/material.dart'; import 'package:flutter/semantics.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; @@ -84,6 +85,21 @@ class IncomingBusReminderService { final token = _serverToken(); if (token == null) throw Exception("missing token"); await _modifyReminders(token: token, modifications: modifications); + + // List for checking if every reminder modification has been set + List added = List.generate(modifications.length, (i) => modifications[i] is RemoveReminder); + + for (final reminder in await _activeReminders(token: token)) { + for (int i = 0; i < modifications.length; ++i) { + if (reminder.stpid == modifications[i].stopID && reminder.rtid == modifications[i].routeID) { + if (modifications[i] is RemoveReminder) throw Exception("backend not updated"); + added[i] = modifications[i] is AddReminder; + break; + } + } + } + + if (added.contains(false)) throw Exception("backend not updated"); } static Future isActiveReminder(String stpid, String rtid) async { @@ -225,6 +241,8 @@ Future _notifyMeLater({required String token}) async { /// Used in the `modifyReminders` method of `IncomingBusReminderService` sealed class RemindersModification { + String get stopID; + String get routeID; Map encode(); } @@ -234,6 +252,14 @@ class AddReminder extends RemindersModification { String stpid, rtid; int thresh; + @override + String get stopID => stpid; + + @override + String get routeID => rtid; + + int get threshold => thresh; + @override Map encode() { return {"action": "set", "stpid": stpid, "rtid": rtid, "thresh": thresh}; @@ -244,6 +270,8 @@ class RemoveReminder extends RemindersModification { RemoveReminder({required this.stpid, required this.rtid}); String stpid, rtid; + String get stopID => stpid; + String get routeID => rtid; @override Map encode() { diff --git a/lib/widgets/stop_sheet.dart b/lib/widgets/stop_sheet.dart index a8ef262..5282dd1 100644 --- a/lib/widgets/stop_sheet.dart +++ b/lib/widgets/stop_sheet.dart @@ -6,6 +6,7 @@ import 'package:bluebus/widgets/dialog.dart'; import 'package:bluebus/widgets/refresh_button.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import '../constants.dart'; import '../services/route_color_service.dart'; import '../models/bus_stop.dart'; @@ -263,34 +264,33 @@ class _StopSheetState extends State { void initState() { super.initState(); loadedStopData = fetchStopData(widget.stopID); - imageBusStop = - (widget.stopID == "C250") || - (widget.stopID == "N406") || - (widget.stopID == "N405") || - (widget.stopID == "N550") || - (widget.stopID == "N551") || - (widget.stopID == "N553") || - (widget.stopID == "C251"); - if (widget.stopID == "C250") { - imagePath = "assets/CCTC.jpg"; - } - if (widget.stopID == "C251") { - imagePath = "assets/CCTC_Ruthven.jpg"; - } - if (widget.stopID == "N406") { - imagePath = "assets/FXB_outbound.jpg"; - } - if (widget.stopID == "N405") { - imagePath = "assets/FXB_inbound.jpg"; - } - if (widget.stopID == "N550") { - imagePath = "assets/Pierpont.jpg"; - } - if (widget.stopID == "N551") { - imagePath = "assets/PierpontBursley.jpg"; - } - if (widget.stopID == "N553") { - imagePath = "assets/PierpontNorthwood.jpg"; + imageBusStop = true; + + switch (widget.stopID) { + case "C250": + imagePath = "assets/CCTC.jpg"; + break; + case "C251": + imagePath = "assets/CCTC_Ruthven.jpg"; + break; + case "N406": + imagePath = "assets/FXB_outbound.jpg"; + break; + case "N405": + imagePath = "assets/FXB_inbound.jpg"; + break; + case "N550": + imagePath = "assets/Pierpont.jpg"; + break; + case "N551": + imagePath = "assets/PierpontBursley.jpg"; + break; + case "N553": + imagePath = "assets/PierpontNorthwood.jpg"; + break; + default: + imageBusStop = false; + break; } } @@ -837,14 +837,36 @@ class _ReminderFormState extends State { Set activeRtids = {}; /// ones that have been selected to be added / removed Set rtidsToChange = {}; - int reminderThresh = 5; + int reminderThresh = -1; // exists to ensure the notification button isn't pressed multiple times // while waiting for the response bool _isProcessing = false; + // Save reminder threshold to persistent storage + Future _saveReminderThreshold() async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setInt('reminder_thresh', reminderThresh); + } + + // Load reminder threshold from persistent storage + Future _loadReminderThreshold() async { + final prefs = await SharedPreferences.getInstance(); + final savedThresh = prefs.getInt('reminder_thresh') ?? 5; + return savedThresh; + } + @override Widget build(BuildContext context) { + if (reminderThresh < 0) { + _loadReminderThreshold().then((int savedThresh) { + setState(() { + reminderThresh = savedThresh; + }); + }).catchError((error, stack) { + + }); + } return FutureBuilder( future: reminderInfoFuture, builder: (context, snapshot) { @@ -1076,6 +1098,7 @@ class _ReminderFormState extends State { onPressed: _isProcessing ? null : () async { // is processing lets us make sure no one spams the button setState(() => _isProcessing = true); + await _saveReminderThreshold(); List modifications = []; for (String rtid in routesToShow) { @@ -1094,11 +1117,11 @@ class _ReminderFormState extends State { await IncomingBusReminderService.modifyReminders(modifications); if (!context.mounted) return; Navigator.pop(context); - } on Exception catch (e) { - showDialog( - context: context, - builder: (context) => SimpleDialog( - title: Text("Failed!\n${e.toString()}")), + } on Exception { + showMaizebusOKDialog( + contextIn: context, + title: Text("Failed to set reminders"), + content: Text("If this error is persistent, please send us feedback through the feedback form in the settings page"), ); } setState(() => _isProcessing = false);