From 654225360e3180fd178a9b246bfda4f5aee1dc31 Mon Sep 17 00:00:00 2001 From: TomAndTheCats <64748532+Nnanyere@users.noreply.github.com> Date: Wed, 25 Mar 2026 14:29:50 -0400 Subject: [PATCH 1/4] Beginner function --- .../incoming_bus_reminder_service.dart | 24 +++++++++++++++++++ lib/widgets/stop_sheet.dart | 3 ++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/services/incoming_bus_reminder_service.dart b/lib/services/incoming_bus_reminder_service.dart index e315fd5..8bd0012 100644 --- a/lib/services/incoming_bus_reminder_service.dart +++ b/lib/services/incoming_bus_reminder_service.dart @@ -76,6 +76,30 @@ class IncomingBusReminderService { await _unsetReminder(token: token, stpid: stpid, rtid: rtid); } + static Future checkReminders( + List modifications, + ) async { + // TODO: avoid excessive setup work + await _completeSetup(); + final token = _serverToken(); + if (token == null) throw Exception("missing token"); + + // 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].encode()["stpid"] && reminder.rtid == modifications[i].encode()["rtid"]) { + added[i] = modifications[i] is AddReminder; + if (added[i] is RemoveReminder) throw Exception("backend not updated"); + break; + } + } + } + + if (added.contains(false)) throw Exception("backend not updated"); + } + static Future modifyReminders( List modifications, ) async { diff --git a/lib/widgets/stop_sheet.dart b/lib/widgets/stop_sheet.dart index a8ef262..a9f5e3a 100644 --- a/lib/widgets/stop_sheet.dart +++ b/lib/widgets/stop_sheet.dart @@ -1092,13 +1092,14 @@ class _ReminderFormState extends State { try { await IncomingBusReminderService.modifyReminders(modifications); + await IncomingBusReminderService.checkReminders(modifications); if (!context.mounted) return; Navigator.pop(context); } on Exception catch (e) { showDialog( context: context, builder: (context) => SimpleDialog( - title: Text("Failed!\n${e.toString()}")), + title: Text("Notification request couldn't be sent\n")), ); } setState(() => _isProcessing = false); From 06ef714c293c7e2c282818f11e27644dd67e3354 Mon Sep 17 00:00:00 2001 From: TomAndTheCats <64748532+Nnanyere@users.noreply.github.com> Date: Wed, 25 Mar 2026 16:40:11 -0400 Subject: [PATCH 2/4] Update stop_sheet.dart --- lib/widgets/stop_sheet.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/widgets/stop_sheet.dart b/lib/widgets/stop_sheet.dart index a9f5e3a..81c172c 100644 --- a/lib/widgets/stop_sheet.dart +++ b/lib/widgets/stop_sheet.dart @@ -1095,11 +1095,11 @@ class _ReminderFormState extends State { await IncomingBusReminderService.checkReminders(modifications); if (!context.mounted) return; Navigator.pop(context); - } on Exception catch (e) { + } on Exception { showDialog( context: context, builder: (context) => SimpleDialog( - title: Text("Notification request couldn't be sent\n")), + title: Text("Notification request\n couldn't be sent\n", textAlign: TextAlign.center,)), ); } setState(() => _isProcessing = false); From a1e863db0ed1745b10b8b38c0367285027e4e3c6 Mon Sep 17 00:00:00 2001 From: TomAndTheCats <64748532+Nnanyere@users.noreply.github.com> Date: Wed, 25 Mar 2026 17:29:59 -0400 Subject: [PATCH 3/4] Shortened to one function instead of two --- lib/services/incoming_bus_reminder_service.dart | 16 ++++------------ lib/widgets/stop_sheet.dart | 1 - 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/lib/services/incoming_bus_reminder_service.dart b/lib/services/incoming_bus_reminder_service.dart index 8bd0012..c750afe 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; @@ -76,13 +77,14 @@ class IncomingBusReminderService { await _unsetReminder(token: token, stpid: stpid, rtid: rtid); } - static Future checkReminders( + static Future modifyReminders( List modifications, ) async { // TODO: avoid excessive setup work await _completeSetup(); 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); @@ -90,8 +92,8 @@ class IncomingBusReminderService { for (final reminder in await _activeReminders(token: token)) { for (int i = 0; i < modifications.length; ++i) { if (reminder.stpid == modifications[i].encode()["stpid"] && reminder.rtid == modifications[i].encode()["rtid"]) { - added[i] = modifications[i] is AddReminder; if (added[i] is RemoveReminder) throw Exception("backend not updated"); + added[i] = modifications[i] is AddReminder; break; } } @@ -100,16 +102,6 @@ class IncomingBusReminderService { if (added.contains(false)) throw Exception("backend not updated"); } - static Future modifyReminders( - List modifications, - ) async { - // TODO: avoid excessive setup work - await _completeSetup(); - final token = _serverToken(); - if (token == null) throw Exception("missing token"); - await _modifyReminders(token: token, modifications: modifications); - } - static Future isActiveReminder(String stpid, String rtid) async { final activeReminders = await getActiveReminders(); return activeReminders.contains((stpid: stpid, rtid: rtid)); diff --git a/lib/widgets/stop_sheet.dart b/lib/widgets/stop_sheet.dart index 81c172c..bcd2852 100644 --- a/lib/widgets/stop_sheet.dart +++ b/lib/widgets/stop_sheet.dart @@ -1092,7 +1092,6 @@ class _ReminderFormState extends State { try { await IncomingBusReminderService.modifyReminders(modifications); - await IncomingBusReminderService.checkReminders(modifications); if (!context.mounted) return; Navigator.pop(context); } on Exception { From 8e31b7afd4660205c3e2c5f63ffaf34e23aff927 Mon Sep 17 00:00:00 2001 From: TomAndTheCats <64748532+Nnanyere@users.noreply.github.com> Date: Sat, 28 Mar 2026 17:05:45 -0400 Subject: [PATCH 4/4] feat(widget), perf(widget): Changed dialog type and saved slider location When notification requests are not sent to the backend, a MaizebusOKDialog box is shown instead of a default Dialog one. Additionally, the initial slider position for the reminder threshold is saved after a notification is set. --- .../incoming_bus_reminder_service.dart | 16 +++- lib/widgets/stop_sheet.dart | 89 ++++++++++++------- 2 files changed, 70 insertions(+), 35 deletions(-) diff --git a/lib/services/incoming_bus_reminder_service.dart b/lib/services/incoming_bus_reminder_service.dart index c750afe..3515b32 100644 --- a/lib/services/incoming_bus_reminder_service.dart +++ b/lib/services/incoming_bus_reminder_service.dart @@ -91,8 +91,8 @@ class IncomingBusReminderService { for (final reminder in await _activeReminders(token: token)) { for (int i = 0; i < modifications.length; ++i) { - if (reminder.stpid == modifications[i].encode()["stpid"] && reminder.rtid == modifications[i].encode()["rtid"]) { - if (added[i] is RemoveReminder) throw Exception("backend not updated"); + 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; } @@ -241,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(); } @@ -250,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}; @@ -260,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 bcd2852..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) { @@ -1095,10 +1118,10 @@ class _ReminderFormState extends State { if (!context.mounted) return; Navigator.pop(context); } on Exception { - showDialog( - context: context, - builder: (context) => SimpleDialog( - title: Text("Notification request\n couldn't be sent\n", textAlign: TextAlign.center,)), + 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);