From 792589182ea43ebd58ead27dfa65fa3f65443a36 Mon Sep 17 00:00:00 2001
From: Jidong Chen <jidongchen93@gmail.com>
Date: Thu, 13 Jun 2019 20:17:54 +0800
Subject: [PATCH] broadcast 1,ios 2,dart

---
 ios/Classes/Boost/FlutterBoostPlugin.h        |  9 +++
 ios/Classes/Boost/FlutterBoostPlugin.m        | 25 ++++++-
 .../Boost/FlutterBoostPlugin_private.h        |  1 +
 .../handlers/NavigationService_closePage.mm   |  7 ++
 .../NavigationService_onFlutterPageResult.mm  |  6 ++
 ...vigationService_onShownContainerChanged.mm |  5 ++
 .../handlers/NavigationService_openPage.mm    |  6 ++
 .../handlers/NavigationService_pageOnStart.mm |  6 ++
 ios/Classes/Messaging/base/FLBBroadcastor.h   | 32 +++++++++
 ios/Classes/Messaging/base/FLBBroadcastor.m   | 72 +++++++++++++++++++
 .../Messaging/base/FLBMessageDispather.m      |  3 +-
 .../Messaging/base/FLBMessageHandlerImp.m     | 32 +++++----
 ios/flutter_boost.podspec                     |  1 +
 lib/flutter_boost.dart                        |  9 ++-
 lib/messaging/base/broadcastor.dart           | 66 +++++++++++++++++
 15 files changed, 264 insertions(+), 16 deletions(-)
 create mode 100644 ios/Classes/Messaging/base/FLBBroadcastor.h
 create mode 100644 ios/Classes/Messaging/base/FLBBroadcastor.m
 create mode 100644 lib/messaging/base/broadcastor.dart

diff --git a/ios/Classes/Boost/FlutterBoostPlugin.h b/ios/Classes/Boost/FlutterBoostPlugin.h
index 4654c66..9332a66 100755
--- a/ios/Classes/Boost/FlutterBoostPlugin.h
+++ b/ios/Classes/Boost/FlutterBoostPlugin.h
@@ -24,6 +24,7 @@
 #import <Flutter/Flutter.h>
 
 #import "FLB2Platform.h"
+#import "FLBBroadcastor.h"
 
 @interface FlutterBoostPlugin : NSObject<FlutterPlugin>
 
@@ -38,6 +39,14 @@
 - (BOOL)isRunning;
 - (FlutterViewController *)currentViewController;
 
+#pragma mark - broadcast event to/from flutter
+- (void)sendEvent:(NSString *)eventName
+        arguments:(NSDictionary *)arguments
+           result:(FlutterResult)result;
+
+- (FLBVoidCallback)addEventListener:(FLBEventListener)listner
+                            forName:(NSString *)name;
+
 #pragma mark - handing vc result.
 - (void)openPage:(NSString *)name
           params:(NSDictionary *)params
diff --git a/ios/Classes/Boost/FlutterBoostPlugin.m b/ios/Classes/Boost/FlutterBoostPlugin.m
index e4945f1..6afd976 100755
--- a/ios/Classes/Boost/FlutterBoostPlugin.m
+++ b/ios/Classes/Boost/FlutterBoostPlugin.m
@@ -47,14 +47,18 @@
                                      methodChannelWithName:@"flutter_boost"
                                      binaryMessenger:[registrar messenger]];
     FlutterBoostPlugin* instance = [self.class sharedInstance];
+    [instance registerHandlers];
     instance.methodChannel = channel;
+    instance.broadcastor = [[FLBBroadcastor alloc] initWithMethodChannel:channel];
     [registrar addMethodCallDelegate:instance channel:channel];
 }
 
 - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
     if ([@"getPlatformVersion" isEqualToString:call.method]) {
         result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
-    } else {
+    } else if([@"__event__" isEqual: call.method]){
+        [_broadcastor handleMethodCall:call result:result];
+    }else{
         FLBMessageImp *msg = FLBMessageImp.new;
         msg.name = call.method;
         msg.params = call.arguments;
@@ -94,7 +98,7 @@
 {
     if (self = [super init]) {
         _resultMediator = [FLBResultMediator new];
-        [self registerHandlers];
+        _dispatcher = FLBMessageDispather.new;
     }
     
     return self;
@@ -172,4 +176,21 @@
     [_resultMediator removeHandlerForKey:vcid];
 }
 
+#pragma mark - broadcast event to/from flutter
+- (void)sendEvent:(NSString *)eventName
+        arguments:(NSDictionary *)arguments
+           result:(FlutterResult)result
+{
+    [_broadcastor sendEvent:eventName
+                  arguments:arguments
+                     result:result];
+}
+
+- (FLBVoidCallback)addEventListener:(FLBEventListener)listner
+                            forName:(NSString *)name
+{
+    [_broadcastor addEventListener:listner
+                           forName:name];
+}
+
 @end
diff --git a/ios/Classes/Boost/FlutterBoostPlugin_private.h b/ios/Classes/Boost/FlutterBoostPlugin_private.h
index 8bdcd2c..5c2dbcc 100644
--- a/ios/Classes/Boost/FlutterBoostPlugin_private.h
+++ b/ios/Classes/Boost/FlutterBoostPlugin_private.h
@@ -38,6 +38,7 @@
 - (id<FLBAbstractFactory>)factory;
 
 @property (nonatomic,strong) FlutterMethodChannel *methodChannel;
+@property (nonatomic,strong) FLBBroadcastor *broadcastor;
 @property (nonatomic,copy) NSString *fPageId;
 @property (nonatomic,copy) NSString *fPagename;
 @property (nonatomic,strong) NSDictionary *fParams;
diff --git a/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_closePage.mm b/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_closePage.mm
index 902a28d..f39fba7 100755
--- a/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_closePage.mm
+++ b/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_closePage.mm
@@ -55,6 +55,7 @@
          pageName:args[@"pageName"]
            params:args[@"params"]
          animated:args[@"animated"]];
+    return YES;
  }
 
  - (NSString *)returnType
@@ -62,4 +63,10 @@
    return @"BOOL";
  }
 
+- (NSArray *)handledMessageNames
+{
+    return @[@"closePage"];
+}
+
+
  @end
diff --git a/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_onFlutterPageResult.mm b/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_onFlutterPageResult.mm
index efe729f..929ceb5 100755
--- a/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_onFlutterPageResult.mm
+++ b/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_onFlutterPageResult.mm
@@ -43,8 +43,14 @@
 {
     NSDictionary *args = msg.params;
      [self onCall:result uniqueId:args[@"uniqueId"] key:args[@"key"] resultData:args[@"resultData"] params:args[@"params"]];
+    return YES;
  }
 
+- (NSArray *)handledMessageNames
+{
+    return @[@"onFlutterPageResult"];
+}
+
  - (NSString *)returnType
  {
    return @"BOOL";
diff --git a/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_onShownContainerChanged.mm b/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_onShownContainerChanged.mm
index 0a0d382..655cd60 100755
--- a/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_onShownContainerChanged.mm
+++ b/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_onShownContainerChanged.mm
@@ -42,12 +42,17 @@
 {
      NSDictionary *args = msg.params;
      [self onCall:result newName:args[@"newName"] oldName:args[@"oldName"] params:args[@"params"]];
+    return YES;
  }
 
  - (NSString *)returnType
  {
    return @"BOOL";
  }
+- (NSArray *)handledMessageNames
+{
+    return @[@"onShownContainerChanged"];
+}
 
  
  @end
diff --git a/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_openPage.mm b/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_openPage.mm
index 71d20b8..f8285f8 100755
--- a/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_openPage.mm
+++ b/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_openPage.mm
@@ -48,11 +48,17 @@
     
     NSDictionary *args = msg.params;
      [self onCall:result pageName:args[@"pageName"] params:args[@"params"] animated:args[@"animated"]];
+    return YES;
  }
 
  - (NSString *)returnType
  {
    return @"BOOL";
  }
+
+- (NSArray *)handledMessageNames
+{
+    return @[@"openPage"];
+}
  
  @end
diff --git a/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_pageOnStart.mm b/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_pageOnStart.mm
index dc5d99e..5f5c0fc 100755
--- a/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_pageOnStart.mm
+++ b/ios/Classes/Messaging/Generated/NavigationService/handlers/NavigationService_pageOnStart.mm
@@ -45,6 +45,7 @@
 {
     NSDictionary *args = msg.params;
     [self onCall:result params:args[@"params"]];
+    return YES;
 }
 
  - (NSString *)returnType
@@ -52,4 +53,9 @@
    return @"NSDictionary *";
  }
 
+- (NSArray *)handledMessageNames
+{
+    return @[@"pageOnStart"];
+}
+
  @end
diff --git a/ios/Classes/Messaging/base/FLBBroadcastor.h b/ios/Classes/Messaging/base/FLBBroadcastor.h
new file mode 100644
index 0000000..8848f3a
--- /dev/null
+++ b/ios/Classes/Messaging/base/FLBBroadcastor.h
@@ -0,0 +1,32 @@
+//
+//  FLBBroadcastor.h
+//  flutter_boost
+//
+//  Created by Jidong Chen on 2019/6/13.
+//
+
+#import <Foundation/Foundation.h>
+#import <Flutter/Flutter.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void (^FLBEventListener) (NSString *name ,
+                                  NSDictionary *arguments);
+typedef void (^FLBVoidCallback)(void);
+
+@interface FLBBroadcastor : NSObject
+
+- (instancetype)initWithMethodChannel:(FlutterMethodChannel *)channel;
+
+- (void)sendEvent:(NSString *)eventName
+        arguments:(NSDictionary *)arguments
+           result:(FlutterResult)result;
+
+- (FLBVoidCallback)addEventListener:(FLBEventListener)listner
+                            forName:(NSString *)name;
+
+- (void)handleMethodCall:(FlutterMethodCall *)call
+                  result:(FlutterResult)result;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ios/Classes/Messaging/base/FLBBroadcastor.m b/ios/Classes/Messaging/base/FLBBroadcastor.m
new file mode 100644
index 0000000..de7ec6b
--- /dev/null
+++ b/ios/Classes/Messaging/base/FLBBroadcastor.m
@@ -0,0 +1,72 @@
+//
+//  FLBBroadcastor.m
+//  flutter_boost
+//
+//  Created by Jidong Chen on 2019/6/13.
+//
+
+#import "FLBBroadcastor.h"
+
+@interface FLBBroadcastor()
+@property (nonatomic,strong) FlutterMethodChannel *channel;
+@property (nonatomic,strong) NSMutableDictionary *lists;
+
+@end
+
+@implementation FLBBroadcastor
+
+- (instancetype)initWithMethodChannel:(FlutterMethodChannel *)channel
+{
+    if (self = [super init]) {
+        _channel = channel;
+        _lists = NSMutableDictionary.new;
+    }
+    return self;
+}
+
+- (void)sendEvent:(NSString *)eventName
+        arguments:(NSDictionary *)arguments
+           result:(void (^)(id _Nonnull))result
+{
+    if(!eventName) return;
+    NSMutableDictionary *msg = NSMutableDictionary.new;
+    msg[@"name"] = eventName;
+    msg[@"arguments"] = arguments;
+    [_channel invokeMethod:@"__event__"
+                 arguments:msg
+                    result:result];
+}
+
+- (FLBVoidCallback)addEventListener:(FLBEventListener)listner
+                            forName:(NSString *)name
+{
+    if(!name || !listner) return ^{};
+    
+    NSMutableArray *list = _lists[name];
+    if(!list){
+        list = NSMutableArray.new;
+        _lists[name] = list;
+    }
+    [list addObject:listner];
+    return ^{
+        [list removeObject:listner];
+    };
+}
+
+- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
+{
+    if([call.method isEqual:@"__event__"]){
+        NSString *name = call.arguments[@"name"];
+        NSDictionary *arguments = call.arguments[@"arguments"];
+        if(name){
+            NSMutableArray *list = _lists[name];
+            if(list){
+                for(FLBEventListener l in list){
+                    l(name,arguments);
+                }
+            }
+        }
+    }
+}
+
+@end
diff --git a/ios/Classes/Messaging/base/FLBMessageDispather.m b/ios/Classes/Messaging/base/FLBMessageDispather.m
index 5f22ea6..e9398b9 100755
--- a/ios/Classes/Messaging/base/FLBMessageDispather.m
+++ b/ios/Classes/Messaging/base/FLBMessageDispather.m
@@ -44,7 +44,8 @@
 {
     if (msg) {
         id<FLBMessageHandler> handler = _handlerMap[msg.name];
-        return [handler handle:msg result:result];
+        [handler handle:msg result:result];
+        return handler != nil;
     }else{
         return NO;
     }
diff --git a/ios/Classes/Messaging/base/FLBMessageHandlerImp.m b/ios/Classes/Messaging/base/FLBMessageHandlerImp.m
index 3cd06ef..4f85bd1 100755
--- a/ios/Classes/Messaging/base/FLBMessageHandlerImp.m
+++ b/ios/Classes/Messaging/base/FLBMessageHandlerImp.m
@@ -22,6 +22,7 @@
  * THE SOFTWARE.
  */
 #import "FLBMessageHandlerImp.h"
+#import "FLBMessageImp.h"
 
 typedef void (^SendResult)(NSObject *result);
 
@@ -76,21 +77,28 @@ typedef void (^SendResult)(NSObject *result);
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
     SEL method = @selector(call:result:);
-    if (_callHandlers[NSStringFromSelector(method)]) {
-        return;
-    }
+   
     
-    __weak typeof(self) weakSelf = self;
-    _callHandlers[NSStringFromSelector(method)] = ^(NSDictionary *args,SendResult result){
-        id resultBlock = [weakSelf getHandlerBlockForType:weakSelf.returnType result:result];
-        if (resultBlock && result) {
-            [weakSelf performSelector:method withObject:args withObject:resultBlock];
-        }else{
+    for(NSString *name in self.handledMessageNames){
+        if (_callHandlers[name]) {
+            continue;
+        }
+        __weak typeof(self) weakSelf = self;
+        _callHandlers[name] = ^(NSDictionary *args,SendResult result){
+            id resultBlock = [weakSelf getHandlerBlockForType:weakSelf.returnType result:result];
+            if (resultBlock && result) {
+                FLBMessageImp *msg = FLBMessageImp.new;
+                msg.name = name;
+                msg.params = args;
+                [weakSelf performSelector:method withObject:msg withObject:resultBlock];
+            }else{
 #if DEBUG
-            [NSException raise:@"invalid call" format:@"missing handler and result!"];
+                [NSException raise:@"invalid call" format:@"missing handler and result!"];
 #endif
-        }
-    };
+            }
+        };
+    }
+    
 #pragma clang diagnostic pop
 }
 
diff --git a/ios/flutter_boost.podspec b/ios/flutter_boost.podspec
index 3975ae2..64fd2ac 100755
--- a/ios/flutter_boost.podspec
+++ b/ios/flutter_boost.podspec
@@ -21,6 +21,7 @@ A new Flutter plugin make flutter better to use!
     'Classes/Boost/FLB2Platform.h',
     'Classes/Boost/FLBFlutterContainer.h',
     'Classes/Boost/FLBFlutterAppDelegate.h',
+    'Classes/Boost/FLBBroadcastor.h',
     'Classes/1.0/FLBFlutterViewContainer.h',
     'Classes/1.5/FLB2FlutterViewContainer.h'
 
diff --git a/lib/flutter_boost.dart b/lib/flutter_boost.dart
index 4985291..a313903 100755
--- a/lib/flutter_boost.dart
+++ b/lib/flutter_boost.dart
@@ -39,6 +39,7 @@ import 'messaging/handlers/on_native_page_result_handler.dart';
 import 'messaging/handlers/will_dealloc_page_container_handler.dart';
 import 'messaging/handlers/will_show_page_container_handler.dart';
 import 'messaging/handlers/will_disappear_page_container_handler.dart';
+import 'messaging/base/broadcastor.dart';
 import 'observers_holders.dart';
 
 export 'container/boost_container.dart';
@@ -64,6 +65,7 @@ class FlutterBoost {
 
   final MethodChannel _methodChannel = MethodChannel('flutter_boost');
   final MessageDispatcher _dispatcher = MessageDispatcher();
+  final Broadcastor _broadcastor = Broadcastor(_methodChannel);
 
   FlutterBoost() {
     _router.resultMediator = _resultMediator;
@@ -78,7 +80,12 @@ class FlutterBoost {
     _dispatcher.registerHandler(WillShowPageContainerHandler());
     _dispatcher.registerHandler(WillDisappearPageContainerHandler());
     _methodChannel.setMethodCallHandler((MethodCall call){
-      _dispatcher.dispatch(call);
+      if(call.method == "__event__"){
+        //Handler broadcast event.
+        return _broadcastor.handleCall(call);
+      }else{
+        return _dispatcher.dispatch(call);
+      }
     });
 
   }
diff --git a/lib/messaging/base/broadcastor.dart b/lib/messaging/base/broadcastor.dart
new file mode 100644
index 0000000..c3d3dd0
--- /dev/null
+++ b/lib/messaging/base/broadcastor.dart
@@ -0,0 +1,66 @@
+
+
+import 'package:flutter/services.dart';
+
+typedef void VoidCallback();
+typedef Future<dynamic> EventListener(String name , Map arguments);
+
+class Broadcastor{
+
+  MethodChannel _channel;
+  Map<String,List<EventListener>> _lists = Map();
+
+  Broadcastor(MethodChannel channel){
+    _channel = channel;
+  }
+
+  void sendEvent(String name , Map arguments){
+
+    if(name == null) {
+      return;
+    }
+
+    if(arguments == null){
+      arguments = Map();
+    }
+
+    Map msg = Map();
+    msg["name"] = name;
+    msg["arguments"] = arguments;
+    _channel.invokeMethod("__event__",msg);
+  }
+
+  VoidCallback addEventListener(String name , EventListener listener){
+    if(name == null || listener == null){
+      return (){};
+    }
+
+    List<EventListener> list = _lists[name];
+    if(list == null){
+      list = List();
+      _lists[name] = list;
+    }
+
+    list.add(listener);
+
+    return (){
+      list.remove(listener);
+    };
+  }
+
+  Future<dynamic> handleCall(MethodCall call){
+    if(!_lists.containsKey(call.method) || call.method != "__event__"){
+      return Future<dynamic>();
+    }
+
+    String name = call.arguments["name"];
+    String arg = call.arguments["arguments"];
+    List<EventListener> list = _lists[call.method];
+    for(EventListener l in list){
+      l(name,arg);
+    }
+
+    return Future<dynamic>();
+  }
+
+}
\ No newline at end of file
-- 
2.26.2