diff --git a/ios/Classes/SwiftAirshipPlugin.swift b/ios/Classes/SwiftAirshipPlugin.swift index 71d2dc77..35802db2 100644 --- a/ios/Classes/SwiftAirshipPlugin.swift +++ b/ios/Classes/SwiftAirshipPlugin.swift @@ -285,6 +285,10 @@ public class SwiftAirshipPlugin: NSObject, FlutterPlugin { case "inApp#getDisplayInterval": return try AirshipProxy.shared.inApp.getDisplayInterval() + case "inApp#resendEmbeddedEvent": + AirshipProxy.shared.inApp.resendLastEmbeddedEvent() + return nil + // Analytics case "analytics#trackScreen": try AirshipProxy.shared.analytics.trackScreen( @@ -457,6 +461,7 @@ public class SwiftAirshipPlugin: NSObject, FlutterPlugin { try AirshipProxy.shared.featureFlagManager.trackInteraction(flag: featureFlagProxy) return nil + default: return FlutterError( code:"UNAVAILABLE", @@ -542,13 +547,9 @@ extension FlutterMethodCall { } } -protocol AirshipEventStreamHandlerDelegate: AnyObject { - func handlerWasRemoved(_ handler: AirshipEventStreamHandler) -} class AirshipEventStreamHandler: NSObject, FlutterStreamHandler { private var eventSink: FlutterEventSink? - weak var delegate: AirshipEventStreamHandlerDelegate? func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { self.eventSink = events @@ -557,7 +558,6 @@ class AirshipEventStreamHandler: NSObject, FlutterStreamHandler { func onCancel(withArguments arguments: Any?) -> FlutterError? { self.eventSink = nil - delegate?.handlerWasRemoved(self) return nil } @@ -570,7 +570,7 @@ class AirshipEventStreamHandler: NSObject, FlutterStreamHandler { } } -class AirshipEventStream: NSObject, AirshipEventStreamHandlerDelegate { +class AirshipEventStream: NSObject { private let eventType: AirshipProxyEventType private let name: String private let lock = AirshipLock() @@ -587,7 +587,6 @@ class AirshipEventStream: NSObject, AirshipEventStreamHandlerDelegate { binaryMessenger: registrar.messenger() ) let handler = AirshipEventStreamHandler() - handler.delegate = self eventChannel.setStreamHandler(handler) lock.sync { @@ -617,10 +616,4 @@ class AirshipEventStream: NSObject, AirshipEventStreamHandlerDelegate { } return result } - - func handlerWasRemoved(_ handler: AirshipEventStreamHandler) { - lock.sync { - handlers.removeAll { $0 === handler } - } - } } diff --git a/lib/src/airship_in_app.dart b/lib/src/airship_in_app.dart index 8aee9117..f5ea13b5 100644 --- a/lib/src/airship_in_app.dart +++ b/lib/src/airship_in_app.dart @@ -4,64 +4,63 @@ import 'dart:async'; class AirshipInApp { final AirshipModule _module; - final Map> _isEmbeddedAvailableControllers = - {}; List _embeddedInfos = []; - late final StreamController + late final StreamController> _embeddedInfoUpdatedController; - late final StreamSubscription _subscription; - - List getEmbeddedInfos() => _embeddedInfos; + StreamSubscription? _eventSubscription; + bool _isFirstStream = true; AirshipInApp(this._module) { - _embeddedInfoUpdatedController = - StreamController.broadcast(); _setupEventStream(); - _subscription = onEmbeddedInfoUpdated.listen(_updateEmbeddedIds); + _setupController(); } - /// A flag to determine if an embedded id is available that is not live updated + List getEmbeddedInfos() => _embeddedInfos; + bool isEmbeddedAvailable({required String embeddedId}) => _embeddedInfos.any((info) => info.embeddedId == embeddedId); - /// A live updated stream to determine if an embedded id is available Stream isEmbeddedAvailableStream({required String embeddedId}) => - (_isEmbeddedAvailableControllers[embeddedId] ??= - StreamController.broadcast() - ..add(isEmbeddedAvailable(embeddedId: embeddedId))) - .stream; + onEmbeddedInfoUpdated.map((embeddedInfos) => + embeddedInfos.any((info) => info.embeddedId == embeddedId)); - Stream get onEmbeddedInfoUpdated => + Stream> get onEmbeddedInfoUpdated => _embeddedInfoUpdatedController.stream; + void _setupController() { + _embeddedInfoUpdatedController = + StreamController>.broadcast(onListen: () { + if (_isFirstStream) { + _isFirstStream = false; + _resendLastEmbeddedUpdate(); + } + }); + } + void _setupEventStream() { - _module + _eventSubscription = _module .getEventStream("com.airship.flutter/event/pending_embedded_updated") .listen((event) { try { - _embeddedInfoUpdatedController - .add(EmbeddedInfoUpdatedEvent.fromJson(event)); + final updatedEvent = EmbeddedInfoUpdatedEvent.fromJson(event); + _embeddedInfos = updatedEvent.embeddedInfos; + _embeddedInfoUpdatedController.add(_embeddedInfos); } catch (e) { print("Error parsing EmbeddedInfoUpdatedEvent: $e"); } }); } - void _updateEmbeddedIds(EmbeddedInfoUpdatedEvent event) { - /// Update the embedded infos list - _embeddedInfos = event.embeddedInfos; - - /// Update stream controllers for each embedded id so everything remains synced - _isEmbeddedAvailableControllers.forEach((id, controller) => - controller.add(isEmbeddedAvailable(embeddedId: id))); + Future _resendLastEmbeddedUpdate() async { + try { + await _module.channel.invokeMethod("inApp#resendEmbeddedEvent"); + } catch (e) { + print("Error resending embedded update: $e"); + } } void dispose() { - _subscription.cancel(); - - /// Remove and close all stream controllers for each embedded id - _isEmbeddedAvailableControllers.values - .forEach((controller) => controller.close()); + _eventSubscription?.cancel(); _embeddedInfoUpdatedController.close(); } }