From 6af8cb63e644847712930950737cf136e0341ae9 Mon Sep 17 00:00:00 2001 From: Sven Carstensen Date: Mon, 5 Feb 2024 13:59:01 +0100 Subject: [PATCH] Erweiterungen --- lib/content_views/accepted_jobs_page.dart | 4 +- lib/content_views/finished_jobs_page.dart | 4 +- lib/content_views/main_page.dart | 18 ++--- lib/content_views/tour_details_page.dart | 4 +- lib/content_views/tour_list_page.dart | 4 +- lib/main.dart | 14 ++-- lib/tools/message_service.dart | 92 +++++++++++++++++++++++ lib/tools/mqtt_core.dart | 18 ++--- pubspec.lock | 8 -- pubspec.yaml | 1 - 10 files changed, 125 insertions(+), 42 deletions(-) create mode 100644 lib/tools/message_service.dart diff --git a/lib/content_views/accepted_jobs_page.dart b/lib/content_views/accepted_jobs_page.dart index 331220a..fbc1cdc 100644 --- a/lib/content_views/accepted_jobs_page.dart +++ b/lib/content_views/accepted_jobs_page.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:flutter_broadcast_receiver/flutter_broadcast_receiver.dart'; import 'package:isar/isar.dart'; import 'package:stadtbote/content_views/tour_list_page.dart'; import 'package:stadtbote/content_views/utils/content_view_widget.dart'; import 'package:stadtbote/content_views/utils/header_info.dart'; import 'package:intl/intl.dart'; +import 'package:stadtbote/tools/message_service.dart'; import '../main.dart'; import '../model/job.dart'; @@ -131,6 +131,6 @@ class _AcceptedJobsPageState extends State { } void _clicked(Job job) { - BroadcastReceiver().publish(Constants.messageTopicPushContentView, arguments: TourListPage(job: job)); + MessageService().publish(Constants.messageTopicPushContentView, arguments: TourListPage(job: job)); } } diff --git a/lib/content_views/finished_jobs_page.dart b/lib/content_views/finished_jobs_page.dart index bfe94a8..cd538c6 100644 --- a/lib/content_views/finished_jobs_page.dart +++ b/lib/content_views/finished_jobs_page.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:flutter_broadcast_receiver/flutter_broadcast_receiver.dart'; import 'package:isar/isar.dart'; import 'package:stadtbote/content_views/tour_list_page.dart'; import 'package:stadtbote/content_views/utils/content_view_widget.dart'; import 'package:stadtbote/content_views/utils/header_info.dart'; import 'package:intl/intl.dart'; +import 'package:stadtbote/tools/message_service.dart'; import '../main.dart'; import '../model/job.dart'; @@ -131,6 +131,6 @@ class _FinishedJobsPageState extends State { } void _clicked(Job job) { - BroadcastReceiver().publish(Constants.messageTopicPushContentView, arguments: TourListPage(job: job, readOnly: true,)); + MessageService().publish(Constants.messageTopicPushContentView, arguments: TourListPage(job: job, readOnly: true,)); } } diff --git a/lib/content_views/main_page.dart b/lib/content_views/main_page.dart index 2253a52..97b8d33 100644 --- a/lib/content_views/main_page.dart +++ b/lib/content_views/main_page.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_broadcast_receiver/flutter_broadcast_receiver.dart'; import 'package:isar/isar.dart'; import 'package:stadtbote/content_views/accepted_jobs_page.dart'; import 'package:stadtbote/content_views/assigned_jobs_page.dart'; @@ -11,6 +10,7 @@ import 'package:stadtbote/model/job.dart'; import 'package:stadtbote/model/status.dart'; import 'package:stadtbote/popups/accept_jobs_popup.dart'; import 'package:stadtbote/popups/infos_popup.dart'; +import 'package:stadtbote/tools/message_service.dart'; import 'package:stadtbote/tools/messages/job_received_message.dart'; import 'package:stadtbote/tools/messages/session_info_update.dart'; import 'package:badges/badges.dart' as badges; @@ -131,7 +131,7 @@ class _MainPageState extends State { child: getDefaultButton( 'Zugewiesene Aufträge', image: Image.asset('assets/zugewiesene_auftraege.png', width: 30, height: 30), - () => {BroadcastReceiver() + () => {MessageService() .publish(Constants.messageTopicPushContentView, arguments: const AssignedJobsPage())}), ); }, @@ -161,7 +161,7 @@ class _MainPageState extends State { 'Angenommene Aufträge', image: Image.asset('assets/angenommene_auftraege.png', width: 30, height: 30), () => { - BroadcastReceiver() + MessageService() .publish(Constants.messageTopicPushContentView, arguments: const AcceptedJobsPage()) })); }, @@ -170,7 +170,7 @@ class _MainPageState extends State { getDefaultButton( 'Erledigte Aufträge', image: Image.asset('assets/erledigte_auftraege.png', width: 30, height: 30), - () => {BroadcastReceiver().publish(Constants.messageTopicPushContentView, arguments: const FinishedJobsPage())}), + () => {MessageService().publish(Constants.messageTopicPushContentView, arguments: const FinishedJobsPage())}), const SizedBox(height: 20), ValueListenableBuilder( valueListenable: _messagesValueNotifier, @@ -196,7 +196,7 @@ class _MainPageState extends State { 'Nachrichten', image: Image.asset('assets/nachrichten.png', width: 30, height: 30), () => { - BroadcastReceiver().publish(Constants.messageTopicPushContentView, arguments: const MessagesPage()) + MessageService().publish(Constants.messageTopicPushContentView, arguments: const MessagesPage()) })); }, ), @@ -252,19 +252,19 @@ class _MainPageState extends State { }*/ _initMessages() { - BroadcastReceiver().subscribe(Constants.messageTopicStatusInfoUpdate, (statusInfoUpdateMessage) { + MessageService().subscribe(Constants.messageTopicStatusInfoUpdate, (statusInfoUpdateMessage) { widget.sidValueNotifier.value = statusInfoUpdateMessage.status.sid; }); - BroadcastReceiver().subscribe(Constants.messageTopicJobReceived, (JobReceivedMessage jobReceivedMessage) { + MessageService().subscribe(Constants.messageTopicJobReceived, (JobReceivedMessage jobReceivedMessage) { _jobReceived(jobReceivedMessage.job); }); } void _exitMessages() { - BroadcastReceiver().unsubscribe(Constants.messageTopicStatusInfoUpdate); + MessageService().unsubscribe(Constants.messageTopicStatusInfoUpdate); - BroadcastReceiver().unsubscribe(Constants.messageTopicJobReceived); + MessageService().unsubscribe(Constants.messageTopicJobReceived); } void _refreshBadges() async { diff --git a/lib/content_views/tour_details_page.dart b/lib/content_views/tour_details_page.dart index 18b2c5f..90ad3c2 100644 --- a/lib/content_views/tour_details_page.dart +++ b/lib/content_views/tour_details_page.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:flutter_broadcast_receiver/flutter_broadcast_receiver.dart'; import 'package:stadtbote/content_views/task_list_page.dart'; import 'package:stadtbote/content_views/utils/content_view_widget.dart'; import 'package:stadtbote/content_views/utils/header_info.dart'; import 'package:stadtbote/model/job_tour.dart'; +import 'package:stadtbote/tools/message_service.dart'; import '../model/job.dart'; import '../popups/map_popup.dart'; @@ -142,7 +142,7 @@ class _TourDetailsPageState extends State { const SizedBox(height: 10), getDefaultButton('Weiter', () => { - BroadcastReceiver().publish(Constants.messageTopicPushContentView, arguments: TaskListPage(tour: widget.tour, readOnly: widget.readOnly)) + MessageService().publish(Constants.messageTopicPushContentView, arguments: TaskListPage(tour: widget.tour, readOnly: widget.readOnly)) }), ], ), diff --git a/lib/content_views/tour_list_page.dart b/lib/content_views/tour_list_page.dart index 0f36b5d..ab954dc 100644 --- a/lib/content_views/tour_list_page.dart +++ b/lib/content_views/tour_list_page.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:flutter_broadcast_receiver/flutter_broadcast_receiver.dart'; import 'package:stadtbote/content_views/tour_details_page.dart'; import 'package:stadtbote/content_views/utils/content_view_widget.dart'; import 'package:stadtbote/content_views/utils/header_info.dart'; import 'package:stadtbote/model/job_tour.dart'; import 'package:stadtbote/popups/map_popup.dart'; +import 'package:stadtbote/tools/message_service.dart'; import '../model/job.dart'; import '../tools/constants.dart'; @@ -194,7 +194,7 @@ class _TourListPageState extends State { void _clicked(JobTour tour) { if (tour.state == 0) { - BroadcastReceiver().publish(Constants.messageTopicPushContentView, arguments: TourDetailsPage(job: widget.job, tour: tour, readOnly: widget.readOnly)); + MessageService().publish(Constants.messageTopicPushContentView, arguments: TourDetailsPage(job: widget.job, tour: tour, readOnly: widget.readOnly)); } } } diff --git a/lib/main.dart b/lib/main.dart index fd1aff8..0f71b41 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; -import 'package:flutter_broadcast_receiver/flutter_broadcast_receiver.dart'; import 'package:geolocator/geolocator.dart'; import 'package:isar/isar.dart'; import 'package:path_provider/path_provider.dart'; @@ -11,6 +10,7 @@ import 'package:stadtbote/popups/accept_jobs_popup.dart'; import 'package:stadtbote/tools/colored_safe_area.dart'; import 'package:stadtbote/model/status.dart'; import 'package:stadtbote/tools/connection_status.dart'; +import 'package:stadtbote/tools/message_service.dart'; import 'package:stadtbote/tools/messages/job_received_message.dart'; import 'tools/mqtt_core.dart'; @@ -304,22 +304,22 @@ class _MainState extends State
with SingleTickerProviderStateMixin { } void _initMessages() { - BroadcastReceiver().subscribe(Constants.messageTopicPushContentView, (ContentViewWidget widget) { + MessageService().subscribe(Constants.messageTopicPushContentView, (ContentViewWidget widget) { _pushContentView(widget); }); - BroadcastReceiver().subscribe(Constants.messageTopicPopContentView, (ContentViewWidget widget) { + MessageService().subscribe(Constants.messageTopicPopContentView, (ContentViewWidget widget) { _popContentView(); }); - BroadcastReceiver().subscribe(Constants.messageTopicReplaceContentView, (ContentViewWidget widget) { + MessageService().subscribe(Constants.messageTopicReplaceContentView, (ContentViewWidget widget) { _replaceContentView(widget); }); - BroadcastReceiver().subscribe(Constants.messageTopicHideRightButton, (hideButton) { + MessageService().subscribe(Constants.messageTopicHideRightButton, (hideButton) { _hideRightButton(hideButton); }); - BroadcastReceiver().subscribe(Constants.messageTopicConnectionStatusChanged, (ConnectionStatus connectionStatus) { + MessageService().subscribe(Constants.messageTopicConnectionStatusChanged, (ConnectionStatus connectionStatus) { _connectionStatusChanged(connectionStatus); }); - BroadcastReceiver().subscribe(Constants.messageTopicJobReceived, (JobReceivedMessage jobReceivedMessage) { + MessageService().subscribe(Constants.messageTopicJobReceived, (JobReceivedMessage jobReceivedMessage) { _jobReceived(jobReceivedMessage.job); }); } diff --git a/lib/tools/message_service.dart b/lib/tools/message_service.dart new file mode 100644 index 0000000..8507a82 --- /dev/null +++ b/lib/tools/message_service.dart @@ -0,0 +1,92 @@ +typedef EventHandler = void Function(T args); + +/// The Custom Events Service that can publish data +/// from one module/component to another. +class MessageService { + static final MessageService _singleton = new MessageService._internal(); + + Map _callbackMaps = Map(); + + factory MessageService() { + return _singleton; + } + + MessageService._internal(); + + /// Subscribe to an event topic. Events that + /// get posted to that topic will trigger + /// the provided handler + /// * [topic] The topic to subscribe to + /// * [handler] The event handler + subscribe(String topic, EventHandler? handler) { + List>? handlers = _callbackMaps[topic]; + if (handler == null) { + _callbackMaps.remove(topic); + return; + } + if (handlers == null) { + handlers = []; + _callbackMaps[topic] = handlers; + } + handlers.add(handler); + } + + /// Unsubscribe from the given topic. Your handler + /// will no longer recieve events published to this + /// topic + /// * [topic] The topic to unsubscribe from + /// * [handler] The event handler + unsubscribe(String topic, {EventHandler? handler}) { + if (handler == null) { + _callbackMaps.remove(topic); + return; + } + + final handlers = _callbackMaps[topic]; + if (handlers == null) { + return; + } + + // We now need to remove specific handler + final handlerIndex = handlers.indexOf(handler); + + if (handlerIndex >= 0) { + handlers.removeAt(handlerIndex); + if (handlers.length == 0) { + _callbackMaps.remove(topic); + } + } + } + + /// Publish an Event to given topic. + /// * [topic] The topic to publish to + /// * [arguments] The arguments to pass to + /// the handlers. It's better if custom + /// Structure is used. + publish(String topic, {T? arguments}) { + List>? handlers; + try { + handlers = _callbackMaps[topic]; + } catch (_) { + throw FormatException( + 'Type mismatch between Publisher Arguments and what Subscriber Expects'); + } + + if (handlers == null || handlers.isEmpty) { + return; + } + + handlers.forEach((EventHandler handler) { + try { + if (arguments != null) { + handler(arguments); + } else { + throw 'arguments null'; + } + } catch (_) { + print('Error Occured while executing handler for topic $topic'); + print(_); + } + }); + } +} diff --git a/lib/tools/mqtt_core.dart b/lib/tools/mqtt_core.dart index 7078f8e..9c3cea3 100644 --- a/lib/tools/mqtt_core.dart +++ b/lib/tools/mqtt_core.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:math'; -import 'package:flutter_broadcast_receiver/flutter_broadcast_receiver.dart'; import 'package:isar/isar.dart'; import 'package:mqtt_client/mqtt_client.dart'; import 'package:mqtt_client/mqtt_server_client.dart'; @@ -16,6 +15,7 @@ import 'package:stadtbote/protocoll_messages/payload_container.dart'; import 'package:stadtbote/protocoll_messages/start_session_message.dart'; import 'package:stadtbote/protocoll_messages/sync_jobs_message.dart'; import 'package:stadtbote/tools/connection_status.dart'; +import 'package:stadtbote/tools/message_service.dart'; import 'package:stadtbote/tools/messages/job_deleted_message.dart'; import 'package:stadtbote/tools/messages/job_received_message.dart'; import 'package:stadtbote/tools/messages/message_message.dart'; @@ -90,7 +90,7 @@ class MqttCore { } else { Util.logInfo('Verbindung zum MQTT-Broker fehlgeschlagen!'); - BroadcastReceiver().publish(Constants.messageTopicConnectionStatusChanged, arguments: ConnectionStatus(status: ConnectionStatusEnum.notConnected)); + MessageService().publish(Constants.messageTopicConnectionStatusChanged, arguments: ConnectionStatus(status: ConnectionStatusEnum.notConnected)); _startReconnectTimer(); } @@ -100,7 +100,7 @@ class MqttCore { Util.logInfo('Verbindung zum MQTT-Broker fehlgeschlagen!: $ex'); - BroadcastReceiver().publish(Constants.messageTopicConnectionStatusChanged, arguments: ConnectionStatus(status: ConnectionStatusEnum.notConnected)); + MessageService().publish(Constants.messageTopicConnectionStatusChanged, arguments: ConnectionStatus(status: ConnectionStatusEnum.notConnected)); } } @@ -194,7 +194,7 @@ class MqttCore { _mqttClient.subscribe(_fromServerTopic, MqttQos.exactlyOnce); Util.logInfo('subscribed to topic: $_fromServerTopic'); - BroadcastReceiver().publish(Constants.messageTopicConnectionStatusChanged, arguments: ConnectionStatus(status: ConnectionStatusEnum.connected)); + MessageService().publish(Constants.messageTopicConnectionStatusChanged, arguments: ConnectionStatus(status: ConnectionStatusEnum.connected)); } void _sessionMessageReceived(payloadData) async { @@ -208,7 +208,7 @@ class MqttCore { await MyApp.isarInstance.status.put(statusMessage); }); - BroadcastReceiver().publish(Constants.messageTopicStatusInfoUpdate, arguments: StatusInfoUpdate(status: statusMessage)); + MessageService().publish(Constants.messageTopicStatusInfoUpdate, arguments: StatusInfoUpdate(status: statusMessage)); } void _rankingMessageReceived(payloadData) async { @@ -231,7 +231,7 @@ class MqttCore { MyApp.isarInstance.jobs.putSync(newJob); }); - BroadcastReceiver().publish(Constants.messageTopicJobReceived, arguments: JobReceivedMessage(job: newJob)); + MessageService().publish(Constants.messageTopicJobReceived, arguments: JobReceivedMessage(job: newJob)); } } @@ -245,7 +245,7 @@ class MqttCore { await MyApp.isarInstance.jobs.delete(jobId); }); - BroadcastReceiver().publish(Constants.messageTopicJobDeleted, arguments: JobDeletedMessage(jobId: jobId)); + MessageService().publish(Constants.messageTopicJobDeleted, arguments: JobDeletedMessage(jobId: jobId)); } } @@ -270,7 +270,7 @@ class MqttCore { await MyApp.isarInstance.messages.put(newMessage); }); - BroadcastReceiver().publish(Constants.messageTopicMessageReceived, arguments: MessageReceivedMessage(message: newMessage)); + MessageService().publish(Constants.messageTopicMessageReceived, arguments: MessageReceivedMessage(message: newMessage)); } void _startReconnectTimer() { @@ -290,7 +290,7 @@ class MqttCore { Util.logInfo("_clientDisconnected called"); - BroadcastReceiver().publish(Constants.messageTopicConnectionStatusChanged, arguments: ConnectionStatus(status: ConnectionStatusEnum.notConnected)); + MessageService().publish(Constants.messageTopicConnectionStatusChanged, arguments: ConnectionStatus(status: ConnectionStatusEnum.notConnected)); _startReconnectTimer(); } diff --git a/pubspec.lock b/pubspec.lock index c3fe380..593d335 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -374,14 +374,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" - flutter_broadcast_receiver: - dependency: "direct main" - description: - name: flutter_broadcast_receiver - sha256: "710f3be5b55098bb85dc4eca3f5a33c007f0849a153f0aa338929ff4e5d36c1b" - url: "https://pub.dev" - source: hosted - version: "1.0.0+2" flutter_chat_types: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 1a9e079..18e1b32 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -50,7 +50,6 @@ dependencies: json_annotation: ^4.8.1 shared_preferences: ^2.1.1 badges: ^3.1.1 - flutter_broadcast_receiver: ^1.0.0+2 intl: ^0.18.0 another_stepper: ^1.2.2 easy_stepper: ^0.6.0