diff --git a/bytedesk_demo/ios/Runner.xcodeproj/project.pbxproj b/bytedesk_demo/ios/Runner.xcodeproj/project.pbxproj index 6eb878a..0f677eb 100644 --- a/bytedesk_demo/ios/Runner.xcodeproj/project.pbxproj +++ b/bytedesk_demo/ios/Runner.xcodeproj/project.pbxproj @@ -3,12 +3,14 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 3D8CAEDC2823D9A400EBA5BE /* Info-Release.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3D8CAEDA2823D9A400EBA5BE /* Info-Release.plist */; }; + 3D8CAEDD2823D9A400EBA5BE /* Info-Profile.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3D8CAEDB2823D9A400EBA5BE /* Info-Profile.plist */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -36,6 +38,8 @@ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 1BE257D15466126E85068C73 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3D8CAEDA2823D9A400EBA5BE /* Info-Release.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Release.plist"; sourceTree = ""; }; + 3D8CAEDB2823D9A400EBA5BE /* Info-Profile.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Profile.plist"; sourceTree = ""; }; 76314B5AB6122B6FE14148CA /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; @@ -47,7 +51,7 @@ 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info-Debug.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-Debug.plist"; sourceTree = ""; }; BA046583E3DEF9F4762795D2 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -70,7 +74,6 @@ BA046583E3DEF9F4762795D2 /* Pods-Runner.release.xcconfig */, 01F8337D7CF1E25D0170423C /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -112,7 +115,9 @@ 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, + 97C147021CF9000F007C117D /* Info-Debug.plist */, + 3D8CAEDB2823D9A400EBA5BE /* Info-Profile.plist */, + 3D8CAEDA2823D9A400EBA5BE /* Info-Release.plist */, 97C146F11CF9000F007C117D /* Supporting Files */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, @@ -199,8 +204,10 @@ buildActionMask = 2147483647; files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3D8CAEDC2823D9A400EBA5BE /* Info-Release.plist in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 3D8CAEDD2823D9A400EBA5BE /* Info-Profile.plist in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -368,7 +375,7 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = L5F47963M2; ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -492,7 +499,7 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = L5F47963M2; ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -511,7 +518,7 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = L5F47963M2; ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/bytedesk_demo/ios/Runner/Info-Debug.plist b/bytedesk_demo/ios/Runner/Info-Debug.plist new file mode 100644 index 0000000..05d7c7e --- /dev/null +++ b/bytedesk_demo/ios/Runner/Info-Debug.plist @@ -0,0 +1,82 @@ + + + + + CFBundleDevelopmentRegion + zh_CN + CFBundleDisplayName + 萝卜丝Demo + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + bytedesk_demo + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSAppleMusicUsageDescription + $(PRODUCT_NAME) 需要读取音乐 + NSCalendarsUsageDescription + $(PRODUCT_NAME) 需要读取日历 + NSCameraUsageDescription + $(PRODUCT_NAME) 拍照并发送图片 + NSContactsUsageDescription + $(PRODUCT_NAME) 需要读取联系人推荐好友 + NSLocationAlwaysAndWhenInUseUsageDescription + 地图功能需要您的定位服务,否则无法使用,如果您需要使用后台定位功能请选择“始终允许”。 + NSLocationAlwaysUsageDescription + 地图功能需要您的定位服务,否则无法使用。 + NSLocationWhenInUseUsageDescription + 地图功能需要您的定位服务,否则无法使用。 + NSMicrophoneUsageDescription + $(PRODUCT_NAME) 发送语音 + NSMotionUsageDescription + $(PRODUCT_NAME) 需要读取运动健身 + NSPhotoLibraryAddUsageDescription + $(PRODUCT_NAME) 发送图片 + NSPhotoLibraryUsageDescription + $(PRODUCT_NAME) 发送图片 + NSSpeechRecognitionUsageDescription + $(PRODUCT_NAME) 需要读取语音识别 + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + NSLocalNetworkUsageDescription + Allow flutter to access localhost + NSBonjourServices + + _dartobservatory._tcp + + + diff --git a/bytedesk_demo/ios/Runner/Info.plist b/bytedesk_demo/ios/Runner/Info-Profile.plist similarity index 100% rename from bytedesk_demo/ios/Runner/Info.plist rename to bytedesk_demo/ios/Runner/Info-Profile.plist diff --git a/bytedesk_demo/ios/Runner/Info-Release.plist b/bytedesk_demo/ios/Runner/Info-Release.plist new file mode 100644 index 0000000..6d1a01f --- /dev/null +++ b/bytedesk_demo/ios/Runner/Info-Release.plist @@ -0,0 +1,76 @@ + + + + + CFBundleDevelopmentRegion + zh_CN + CFBundleDisplayName + 萝卜丝Demo + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + bytedesk_demo + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSAppleMusicUsageDescription + $(PRODUCT_NAME) 需要读取音乐 + NSCalendarsUsageDescription + $(PRODUCT_NAME) 需要读取日历 + NSCameraUsageDescription + $(PRODUCT_NAME) 拍照并发送图片 + NSContactsUsageDescription + $(PRODUCT_NAME) 需要读取联系人推荐好友 + NSLocationAlwaysAndWhenInUseUsageDescription + 地图功能需要您的定位服务,否则无法使用,如果您需要使用后台定位功能请选择“始终允许”。 + NSLocationAlwaysUsageDescription + 地图功能需要您的定位服务,否则无法使用。 + NSLocationWhenInUseUsageDescription + 地图功能需要您的定位服务,否则无法使用。 + NSMicrophoneUsageDescription + $(PRODUCT_NAME) 发送语音 + NSMotionUsageDescription + $(PRODUCT_NAME) 需要读取运动健身 + NSPhotoLibraryAddUsageDescription + $(PRODUCT_NAME) 发送图片 + NSPhotoLibraryUsageDescription + $(PRODUCT_NAME) 发送图片 + NSSpeechRecognitionUsageDescription + $(PRODUCT_NAME) 需要读取语音识别 + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/bytedesk_demo/lib/main.dart b/bytedesk_demo/lib/main.dart index ae05be2..62de633 100644 --- a/bytedesk_demo/lib/main.dart +++ b/bytedesk_demo/lib/main.dart @@ -30,9 +30,9 @@ void main() { String _subDomain = "vip"; // 第一步:初始化 BytedeskKefu.init(_appKey, _subDomain); - // 注:如果需要多平台统一用户(用于同步聊天记录等),可使用: - // BytedeskKefu.initWithUsernameAndNicknameAndAvatar('myuniappusername', '我是美女', 'https://bytedesk.oss-cn-shenzhen.aliyuncs.com/avatars/girl.png', subDomain, appKey); - // BytedeskKefu.initWithUsername('myuniappusername',subDomain, appKey); // 其中:username为自定义用户名,可与开发者所在用户系统对接 + // 注:如果需要多平台统一用户(用于同步聊天记录等),可使用下列接口,其中:username只能包含数字或字母,不能含有汉字和特殊字符等,nickname可以使用汉字 + // BytedeskKefu.initWithUsernameAndNicknameAndAvatar('myflutterusername', '我是美女', 'https://bytedesk.oss-cn-shenzhen.aliyuncs.com/avatars/girl.png', _appKey, _subDomain); + // BytedeskKefu.initWithUsername('myflutterusername', _appKey, _subDomain); // 其中:username为自定义用户名,可与开发者所在用户系统对接 // 如果还需要自定义昵称/头像,可以使用 initWithUsernameAndNickname或initWithUsernameAndNicknameAndAvatar, // 具体参数可以参考 bytedesk_kefu/bytedesk_kefu.dart 文件 } @@ -228,7 +228,7 @@ class _MyAppState extends State with WidgetsBindingObserver { } else if (event.message.type == BytedeskConstants.MESSAGE_TYPE_FILE) { print('文件消息:' + event.message.fileUrl!); } else { - print('其他类型消息'); + print('其他类型消息:' + event.message.type!); } }); // token过期 diff --git a/bytedesk_demo/lib/page/chat_type_page.dart b/bytedesk_demo/lib/page/chat_type_page.dart index eb46538..132d669 100755 --- a/bytedesk_demo/lib/page/chat_type_page.dart +++ b/bytedesk_demo/lib/page/chat_type_page.dart @@ -204,10 +204,10 @@ class _ChatTypePageState extends State { title: const Text('H5网页会话'), trailing: const Icon(Icons.keyboard_arrow_right), onTap: () { - print('h5 chat'); + // print('h5 chat'); // 注意: 登录后台->客服管理->技能组(或客服账号)->获取客服代码 获取相应URL String url = - "https://h1.kefux.cn/chat/h5/index.html?sub=vip&uid=201808221551193&wid=201807171659201&type=workGroup&aid=&hidenav=1&ph=ph"; + "https://h2.kefux.cn/chat/h5/index.html?sub=vip&uid=201808221551193&wid=201807171659201&type=workGroup&aid=&hidenav=1&ph=ph"; String title = 'H5在线客服演示'; BytedeskKefu.startH5Chat(context, url, title); }, diff --git a/bytedesk_demo/pubspec.yaml b/bytedesk_demo/pubspec.yaml index 2575f0f..c241d60 100644 --- a/bytedesk_demo/pubspec.yaml +++ b/bytedesk_demo/pubspec.yaml @@ -46,7 +46,7 @@ dependencies: # 请在ios/Podfile中添加:use_frameworks! vibration: ^1.7.3 # 在线客服 https://pub.dev/packages/bytedesk_kefu - bytedesk_kefu: ^1.2.4 + bytedesk_kefu: ^1.2.5 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. diff --git a/bytedesk_kefu/CHANGELOG.md b/bytedesk_kefu/CHANGELOG.md index 35fba8e..f3b72af 100644 --- a/bytedesk_kefu/CHANGELOG.md +++ b/bytedesk_kefu/CHANGELOG.md @@ -1,5 +1,9 @@ # Upgrade Log +## 1.2.5 + +* optimize user experience + ## 1.2.4 * optimize user experience diff --git a/bytedesk_kefu/example/ios/Runner.xcodeproj/project.pbxproj b/bytedesk_kefu/example/ios/Runner.xcodeproj/project.pbxproj index b4052dc..b52c80e 100644 --- a/bytedesk_kefu/example/ios/Runner.xcodeproj/project.pbxproj +++ b/bytedesk_kefu/example/ios/Runner.xcodeproj/project.pbxproj @@ -34,6 +34,8 @@ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3D8CAED62823D79D00EBA5BE /* Info-Release.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Release.plist"; sourceTree = ""; }; + 3D8CAED82823D86F00EBA5BE /* Info-Profile.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Profile.plist"; sourceTree = ""; }; 483DAFF376EA336E70A1AF95 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 72FBC4611027C1F583CD56F7 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; @@ -46,7 +48,7 @@ 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info-Debug.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-Debug.plist"; sourceTree = ""; }; ACD77D260F2F57A568414FB9 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DB686996A5E8B0AF86E5C84F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -119,7 +121,9 @@ 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, + 97C147021CF9000F007C117D /* Info-Debug.plist */, + 3D8CAED82823D86F00EBA5BE /* Info-Profile.plist */, + 3D8CAED62823D79D00EBA5BE /* Info-Release.plist */, 97C146F11CF9000F007C117D /* Supporting Files */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, @@ -367,7 +371,7 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = L5F47963M2; ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -491,7 +495,7 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = L5F47963M2; ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -510,7 +514,7 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = L5F47963M2; ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/bytedesk_kefu/example/ios/Runner/Info-Debug.plist b/bytedesk_kefu/example/ios/Runner/Info-Debug.plist new file mode 100644 index 0000000..e8b5298 --- /dev/null +++ b/bytedesk_kefu/example/ios/Runner/Info-Debug.plist @@ -0,0 +1,80 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + 萝卜丝Demo + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSAppleMusicUsageDescription + $(PRODUCT_NAME) 需要读取音乐 + NSCalendarsUsageDescription + $(PRODUCT_NAME) 需要读取日历 + NSCameraUsageDescription + $(PRODUCT_NAME) 拍照并发送图片 + NSContactsUsageDescription + $(PRODUCT_NAME) 需要读取联系人推荐好友 + NSLocationAlwaysAndWhenInUseUsageDescription + 地图功能需要您的定位服务,否则无法使用,如果您需要使用后台定位功能请选择“始终允许”。 + NSLocationAlwaysUsageDescription + 地图功能需要您的定位服务,否则无法使用。 + NSLocationWhenInUseUsageDescription + 地图功能需要您的定位服务,否则无法使用。 + NSMicrophoneUsageDescription + $(PRODUCT_NAME) 发送语音 + NSMotionUsageDescription + $(PRODUCT_NAME) 需要读取运动健身 + NSPhotoLibraryAddUsageDescription + $(PRODUCT_NAME) 发送图片 + NSPhotoLibraryUsageDescription + $(PRODUCT_NAME) 发送图片 + NSSpeechRecognitionUsageDescription + $(PRODUCT_NAME) 需要读取语音识别 + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + NSLocalNetworkUsageDescription + allow flutter to access localhost network + NSBonjourServices + + _dartobservatory._tcp + + + diff --git a/bytedesk_kefu/example/ios/Runner/Info.plist b/bytedesk_kefu/example/ios/Runner/Info-Profile.plist similarity index 100% rename from bytedesk_kefu/example/ios/Runner/Info.plist rename to bytedesk_kefu/example/ios/Runner/Info-Profile.plist diff --git a/bytedesk_kefu/example/ios/Runner/Info-Release.plist b/bytedesk_kefu/example/ios/Runner/Info-Release.plist new file mode 100644 index 0000000..935ec6f --- /dev/null +++ b/bytedesk_kefu/example/ios/Runner/Info-Release.plist @@ -0,0 +1,74 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + 萝卜丝Demo + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSAppleMusicUsageDescription + $(PRODUCT_NAME) 需要读取音乐 + NSCalendarsUsageDescription + $(PRODUCT_NAME) 需要读取日历 + NSCameraUsageDescription + $(PRODUCT_NAME) 拍照并发送图片 + NSContactsUsageDescription + $(PRODUCT_NAME) 需要读取联系人推荐好友 + NSLocationAlwaysAndWhenInUseUsageDescription + 地图功能需要您的定位服务,否则无法使用,如果您需要使用后台定位功能请选择“始终允许”。 + NSLocationAlwaysUsageDescription + 地图功能需要您的定位服务,否则无法使用。 + NSLocationWhenInUseUsageDescription + 地图功能需要您的定位服务,否则无法使用。 + NSMicrophoneUsageDescription + $(PRODUCT_NAME) 发送语音 + NSMotionUsageDescription + $(PRODUCT_NAME) 需要读取运动健身 + NSPhotoLibraryAddUsageDescription + $(PRODUCT_NAME) 发送图片 + NSPhotoLibraryUsageDescription + $(PRODUCT_NAME) 发送图片 + NSSpeechRecognitionUsageDescription + $(PRODUCT_NAME) 需要读取语音识别 + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/bytedesk_kefu/example/lib/main.dart b/bytedesk_kefu/example/lib/main.dart index 34cc0c1..4a618ef 100644 --- a/bytedesk_kefu/example/lib/main.dart +++ b/bytedesk_kefu/example/lib/main.dart @@ -30,9 +30,9 @@ void main() { String _subDomain = "vip"; // 第一步:初始化 BytedeskKefu.init(_appKey, _subDomain); - // 注:如果需要多平台统一用户(用于同步聊天记录等),可使用: - // BytedeskKefu.initWithUsernameAndNicknameAndAvatar('myuniappusername', '我是美女', 'https://bytedesk.oss-cn-shenzhen.aliyuncs.com/avatars/girl.png', subDomain, appKey); - // BytedeskKefu.initWithUsername('myuniappusername',subDomain, appKey); // 其中:username为自定义用户名,可与开发者所在用户系统对接 + // 注:如果需要多平台统一用户(用于同步聊天记录等),可使用下列接口,其中:username只能包含数字或字母,不能含有汉字和特殊字符等,nickname可以使用汉字 + // BytedeskKefu.initWithUsernameAndNicknameAndAvatar('myflutterusername', '我是美女', 'https://bytedesk.oss-cn-shenzhen.aliyuncs.com/avatars/girl.png', _appKey, _subDomain); + // BytedeskKefu.initWithUsername('myflutterusername', _appKey, _subDomain); // 其中:username为自定义用户名,可与开发者所在用户系统对接 // 如果还需要自定义昵称/头像,可以使用 initWithUsernameAndNickname或initWithUsernameAndNicknameAndAvatar, // 具体参数可以参考 bytedesk_kefu/bytedesk_kefu.dart 文件 } @@ -134,6 +134,12 @@ class _MyAppState extends State with WidgetsBindingObserver { })); }, ), + // ListTile( + // title: Text('退出登录'), + // onTap: () { + // BytedeskKefu.logout(); + // }, + // ), ListTile( title: Text('技术支持: QQ-3群: 825257535'), ) @@ -227,7 +233,7 @@ class _MyAppState extends State with WidgetsBindingObserver { } else if (event.message.type == BytedeskConstants.MESSAGE_TYPE_FILE) { print('文件消息:' + event.message.fileUrl!); } else { - print('其他类型消息'); + print('其他类型消息:' + event.message.type!); } }); // token过期 diff --git a/bytedesk_kefu/example/lib/page/chat_type_page.dart b/bytedesk_kefu/example/lib/page/chat_type_page.dart index 6d85b05..47e0ee5 100755 --- a/bytedesk_kefu/example/lib/page/chat_type_page.dart +++ b/bytedesk_kefu/example/lib/page/chat_type_page.dart @@ -207,7 +207,7 @@ class _ChatTypePageState extends State { print('h5 chat'); // 注意: 登录后台->客服管理->技能组(或客服账号)->获取客服代码 获取相应URL String url = - "https://h1.kefux.cn/chat/h5/index.html?sub=vip&uid=201808221551193&wid=201807171659201&type=workGroup&aid=&hidenav=1&ph=ph"; + "https://h2.kefux.cn/chat/h5/index.html?sub=vip&uid=201808221551193&wid=201807171659201&type=workGroup&aid=&hidenav=1&ph=ph"; String title = 'H5在线客服演示'; BytedeskKefu.startH5Chat(context, url, title); }, diff --git a/bytedesk_kefu/lib/blocs/contact_bloc/contact_bloc.dart b/bytedesk_kefu/lib/blocs/contact_bloc/contact_bloc.dart index 8ad73ee..e9e3e03 100755 --- a/bytedesk_kefu/lib/blocs/contact_bloc/contact_bloc.dart +++ b/bytedesk_kefu/lib/blocs/contact_bloc/contact_bloc.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +// import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:bytedesk_kefu/blocs/contact_bloc/bloc.dart'; import 'package:bytedesk_kefu/repositories/contact_repository.dart'; @@ -6,31 +6,29 @@ import 'package:bytedesk_kefu/repositories/contact_repository.dart'; class ContactBloc extends Bloc { final ContactRepository contactRepository = new ContactRepository(); - // ContactBloc({@required this.contactRepository}); - ContactBloc() : super(ContactUninitialized()); + ContactBloc() : super(ContactUninitialized()) { + on(_mapRefreshContactToState); + } // @override - // ContactState get initialState => ContactUninitialized(); - - @override - Stream mapEventToState(ContactEvent event) async* { - // - if (event is RefreshContactEvent) { - yield* _mapRefreshContactToState(event); - } else { - // - } - } + // Stream mapEventToState(ContactEvent event) async* { + // // + // if (event is RefreshContactEvent) { + // yield* _mapRefreshContactToState(event); + // } else { + // // + // } + // } - Stream _mapRefreshContactToState( - RefreshContactEvent event) async* { - yield ContactLoading(); + void _mapRefreshContactToState( + RefreshContactEvent event, Emitter emit) async { + emit(ContactLoading()); try { // final List contactList = await contactRepository.getContacts(); // yield ContactLoadSuccess(contactList); } catch (error) { print(error); - yield ContactLoadError(); + emit(ContactLoadError()); } } } diff --git a/bytedesk_kefu/lib/blocs/feedback_bloc/feedback_bloc.dart b/bytedesk_kefu/lib/blocs/feedback_bloc/feedback_bloc.dart index ff3cf2c..34a508b 100755 --- a/bytedesk_kefu/lib/blocs/feedback_bloc/feedback_bloc.dart +++ b/bytedesk_kefu/lib/blocs/feedback_bloc/feedback_bloc.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +// import 'dart:async'; import 'package:bytedesk_kefu/blocs/feedback_bloc/bloc.dart'; import 'package:bytedesk_kefu/model/helpCategory.dart'; // import 'package:bytedesk_kefu/model/jsonResult.dart'; @@ -9,55 +9,58 @@ class FeedbackBloc extends Bloc { // final FeedbackRepository feedbackRepository = new FeedbackRepository(); - FeedbackBloc() : super(new UnFeedbackState()); - - @override - Stream mapEventToState( - FeedbackEvent event, - ) async* { - if (event is GetFeedbackCategoryEvent) { - yield* _mapGetFeedbackCategoryToState(event); - } else if (event is SubmitFeedbackEvent) { - yield* _mapSubmitFeedbackToState(event); - } else if (event is UploadImageEvent) { - yield* _mapUploadImageToState(event); - } + FeedbackBloc() : super(new UnFeedbackState()) { + on(_mapGetFeedbackCategoryToState); + on(_mapSubmitFeedbackToState); + on(_mapUploadImageToState); } - Stream _mapGetFeedbackCategoryToState( - GetFeedbackCategoryEvent event) async* { - yield FeedbackLoading(); + // @override + // void mapEventToState( + // FeedbackEvent event, + // ) async { + // if (event is GetFeedbackCategoryEvent) { + // yield* _mapGetFeedbackCategoryToState(event); + // } else if (event is SubmitFeedbackEvent) { + // yield* _mapSubmitFeedbackToState(event); + // } else if (event is UploadImageEvent) { + // yield* _mapUploadImageToState(event); + // } + // } + + void _mapGetFeedbackCategoryToState( + GetFeedbackCategoryEvent event, Emitter emit) async { + emit(FeedbackLoading()); try { final List categoryList = await feedbackRepository.getHelpFeedbackCategories(event.uid); - yield FeedbackCategoryState(categoryList); + emit(FeedbackCategoryState(categoryList)); } catch (error) { print(error); - yield FeedbackLoadError(); + emit(FeedbackLoadError()); } } - Stream _mapSubmitFeedbackToState( - SubmitFeedbackEvent event) async* { - yield FeedbackSubmiting(); + void _mapSubmitFeedbackToState( + SubmitFeedbackEvent event, Emitter emit) async { + emit(FeedbackSubmiting()); try { - // final JsonResult jsonResult = await feedbackRepository.submitFeedback(event.content, event.imageUrls); - yield FeedbackSubmitSuccess(); + emit(FeedbackSubmitSuccess()); } catch (error) { print(error); - yield FeedbackSubmitError(); + emit(FeedbackSubmitError()); } } - Stream _mapUploadImageToState(UploadImageEvent event) async* { - yield ImageUploading(); + void _mapUploadImageToState(UploadImageEvent event, Emitter emit) async { + emit(ImageUploading()); try { final String url = await feedbackRepository.upload(event.filePath); - yield UploadImageSuccess(url); + emit(UploadImageSuccess(url)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } } diff --git a/bytedesk_kefu/lib/blocs/friend_bloc/friend_bloc.dart b/bytedesk_kefu/lib/blocs/friend_bloc/friend_bloc.dart index 1ed659b..edb9c28 100755 --- a/bytedesk_kefu/lib/blocs/friend_bloc/friend_bloc.dart +++ b/bytedesk_kefu/lib/blocs/friend_bloc/friend_bloc.dart @@ -1,5 +1,4 @@ -import 'dart:async'; - +// import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:bytedesk_kefu/blocs/friend_bloc/bloc.dart'; import 'package:bytedesk_kefu/model/friend.dart'; @@ -8,84 +7,90 @@ import 'package:bytedesk_kefu/repositories/friend_repository.dart'; class FriendBloc extends Bloc { final FriendRepository friendRepository = new FriendRepository(); - FriendBloc() : super(UnFriendState()); - - @override - Stream mapEventToState(FriendEvent event) async* { - // - if (event is QueryFriendEvent) { - yield* _mapQueryFriendToState(event); - } else if (event is UploadFriendAddressEvent) { - yield* _mapUploadFriendAddressToState(event); - } else if (event is QueryFriendAddressEvent) { - yield* _mapQueryFriendAddressToState(event); - } else if (event is QueryFriendNearbyEvent) { - yield* _mapQueryFriendNearbyToState(event); - } else if (event is UpdateFriendNearbyEvent) { - yield* _mapUpdateFriendNearbyToState(event); - } + FriendBloc() : super(UnFriendState()) { + on(_mapQueryFriendToState); + on(_mapQueryFriendAddressToState); + on(_mapUploadFriendAddressToState); + on(_mapQueryFriendNearbyToState); + on(_mapUpdateFriendNearbyToState); } - Stream _mapQueryFriendToState(QueryFriendEvent event) async* { - yield FriendLoading(); + // @override + // void mapEventToState(FriendEvent event) async { + // // + // if (event is QueryFriendEvent) { + // yield* _mapQueryFriendToState(event); + // } else if (event is UploadFriendAddressEvent) { + // yield* _mapUploadFriendAddressToState(event); + // } else if (event is QueryFriendAddressEvent) { + // yield* _mapQueryFriendAddressToState(event); + // } else if (event is QueryFriendNearbyEvent) { + // yield* _mapQueryFriendNearbyToState(event); + // } else if (event is UpdateFriendNearbyEvent) { + // yield* _mapUpdateFriendNearbyToState(event); + // } + // } + + void _mapQueryFriendToState(QueryFriendEvent event, Emitter emit) async { + emit(FriendLoading()); try { final List friendList = await friendRepository.getFriends(event.page, event.size); - yield FriendLoadSuccess(friendList); + emit(FriendLoadSuccess(friendList)); } catch (error) { print(error); - yield ErrorFriendState('friend error'); + emit(ErrorFriendState('friend error')); } } - Stream _mapQueryFriendAddressToState( - QueryFriendAddressEvent event) async* { - yield FriendLoading(); + void _mapQueryFriendAddressToState( + QueryFriendAddressEvent event, Emitter emit) async { + emit(FriendLoading()); try { final List friendList = await friendRepository.getFriendsAddress(event.page, event.size); - yield FriendLoadSuccess(friendList); + emit(FriendLoadSuccess(friendList)); } catch (error) { print(error); - yield ErrorFriendState('friend error'); + emit(ErrorFriendState('friend error')); } } - Stream _mapUploadFriendAddressToState( - UploadFriendAddressEvent event) async* { - yield FriendLoading(); + void _mapUploadFriendAddressToState( + UploadFriendAddressEvent event, Emitter emit) async { + emit(FriendLoading()); try { final Friend friend = await friendRepository.uploadAddress(event.nickname, event.mobile); - yield FriendCreateSuccess(friend: friend); + emit(FriendCreateSuccess(friend: friend)); } catch (error) { print(error); - yield ErrorFriendState('friend error'); + emit(ErrorFriendState('friend error')); } } - Stream _mapQueryFriendNearbyToState( - QueryFriendNearbyEvent event) async* { - yield FriendLoading(); + void _mapQueryFriendNearbyToState( + QueryFriendNearbyEvent event, Emitter emit) async { + emit(FriendLoading()); try { final List friendList = await friendRepository.getFriendsNearby(event.page, event.size); - yield FriendLoadSuccess(friendList); + emit(FriendLoadSuccess(friendList)); } catch (error) { print(error); - yield ErrorFriendState('friend error'); + emit(ErrorFriendState('friend error')); } } - Stream _mapUpdateFriendNearbyToState( - UpdateFriendNearbyEvent event) async* { - yield FriendLoading(); + void _mapUpdateFriendNearbyToState( + UpdateFriendNearbyEvent event, Emitter emit) async { + emit(FriendLoading()); try { await friendRepository.updateLocation(event.latitude, event.longtitude); - yield FriendUpdateSuccess(); + emit(FriendUpdateSuccess()); } catch (error) { print(error); - yield ErrorFriendState('friend error'); + emit(ErrorFriendState('friend error')); } } } diff --git a/bytedesk_kefu/lib/blocs/group_bloc/group_bloc.dart b/bytedesk_kefu/lib/blocs/group_bloc/group_bloc.dart index 1ff9bc5..2a03faa 100755 --- a/bytedesk_kefu/lib/blocs/group_bloc/group_bloc.dart +++ b/bytedesk_kefu/lib/blocs/group_bloc/group_bloc.dart @@ -1,14 +1,17 @@ -import 'dart:async'; +// import 'dart:async'; import 'package:bloc/bloc.dart'; import './bloc.dart'; class GroupBloc extends Bloc { - GroupBloc() : super(InitialGroupState()); + + GroupBloc() : super(InitialGroupState()) { - @override - Stream mapEventToState( - GroupEvent event, - ) async* { - // TODO: Add Logic } + + // @override + // Stream mapEventToState( + // GroupEvent event, + // ) async* { + // // TODO: Add Logic + // } } diff --git a/bytedesk_kefu/lib/blocs/help_bloc/help_bloc.dart b/bytedesk_kefu/lib/blocs/help_bloc/help_bloc.dart index 38e0d1e..ddc10bf 100755 --- a/bytedesk_kefu/lib/blocs/help_bloc/help_bloc.dart +++ b/bytedesk_kefu/lib/blocs/help_bloc/help_bloc.dart @@ -9,39 +9,43 @@ class HelpBloc extends Bloc { // final HelpRepository helpRepository = new HelpRepository(); - HelpBloc() : super(new UnHelpState()); - - @override - Stream mapEventToState(HelpEvent event) async* { - if (event is GetHelpCategoryEvent) { - yield* _mapGetHelpCategoryToState(event); - } else if (event is GetHelpArticleEvent) { - yield* _mapGetHelpArticleState(event); - } + HelpBloc() : super(new UnHelpState()) { + on(_mapGetHelpCategoryToState); + on(_mapGetHelpArticleState); } - Stream _mapGetHelpCategoryToState( - GetHelpCategoryEvent event) async* { - yield HelpLoading(); + // @override + // Stream mapEventToState(HelpEvent event) async* { + // if (event is GetHelpCategoryEvent) { + // yield* _mapGetHelpCategoryToState(event); + // } else if (event is GetHelpArticleEvent) { + // yield* _mapGetHelpArticleState(event); + // } + // } + + void _mapGetHelpCategoryToState( + GetHelpCategoryEvent event, Emitter emit) async { + emit(HelpLoading()); try { final List categoryList = await helpRepository.getHelpCategories(event.uid); - yield HelpCategoryState(categoryList); + emit(HelpCategoryState(categoryList)); } catch (error) { print(error); - yield HelpLoadError(); + emit(HelpLoadError()); } } - Stream _mapGetHelpArticleState(GetHelpArticleEvent event) async* { - yield HelpLoading(); + void _mapGetHelpArticleState( + GetHelpArticleEvent event, Emitter emit) async { + emit(HelpLoading()); try { final List categoryList = await helpRepository.getCategoryArticles(event.categoryId); - yield HelpArticleState(categoryList); + emit(HelpArticleState(categoryList)); } catch (error) { print(error); - yield HelpLoadError(); + emit(HelpLoadError()); } } } diff --git a/bytedesk_kefu/lib/blocs/leavemsg_bloc/leavemsg_bloc.dart b/bytedesk_kefu/lib/blocs/leavemsg_bloc/leavemsg_bloc.dart index ade9d52..21930f6 100755 --- a/bytedesk_kefu/lib/blocs/leavemsg_bloc/leavemsg_bloc.dart +++ b/bytedesk_kefu/lib/blocs/leavemsg_bloc/leavemsg_bloc.dart @@ -7,56 +7,43 @@ class LeaveMsgBloc extends Bloc { // final LeaveMsgRepository leaveMsgRepository = new LeaveMsgRepository(); - LeaveMsgBloc() : super(new UnLeaveMsgState()); - - @override - Stream mapEventToState( - LeaveMsgEvent event, - ) async* { - // if (event is GetLeaveMsgCategoryEvent) { - // yield* _mapGetLeaveMsgCategoryToState(event); - // } else - if (event is SubmitLeaveMsgEvent) { - yield* _mapSubmitLeaveMsgToState(event); - } else if (event is UploadImageEvent) { - yield* _mapUploadImageToState(event); - } + LeaveMsgBloc() : super(new UnLeaveMsgState()) { + on(_mapSubmitLeaveMsgToState); + on(_mapUploadImageToState); } - // Stream _mapGetLeaveMsgCategoryToState( - // GetLeaveMsgCategoryEvent event) async* { - // yield LeaveMsgLoading(); - // try { - // final List categoryList = - // await leaveMsgRepository.getHelpLeaveMsgCategories(event.uid); - // yield LeaveMsgCategoryState(categoryList); - // } catch (error) { - // print(error); - // yield LeaveMsgLoadError(); + // @override + // Stream mapEventToState( + // LeaveMsgEvent event, + // ) async* { + // if (event is SubmitLeaveMsgEvent) { + // yield* _mapSubmitLeaveMsgToState(event); + // } else if (event is UploadImageEvent) { + // yield* _mapUploadImageToState(event); // } // } - Stream _mapSubmitLeaveMsgToState( - SubmitLeaveMsgEvent event) async* { - yield LeaveMsgSubmiting(); + void _mapSubmitLeaveMsgToState( + SubmitLeaveMsgEvent event, Emitter emit) async { + emit(LeaveMsgSubmiting()); try { // final JsonResult jsonResult = await leaveMsgRepository.submitLeaveMsg(event.content, event.imageUrls); - yield LeaveMsgSubmitSuccessState(); + emit(LeaveMsgSubmitSuccessState()); } catch (error) { print(error); - yield LeaveMsgSubmitError(); + emit(LeaveMsgSubmitError()); } } - Stream _mapUploadImageToState(UploadImageEvent event) async* { - yield ImageUploading(); + void _mapUploadImageToState(UploadImageEvent event, Emitter emit) async { + emit(ImageUploading()); try { final String url = await leaveMsgRepository.upload(event.filePath); - yield UploadImageSuccess(url); + emit(UploadImageSuccess(url)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } } diff --git a/bytedesk_kefu/lib/blocs/login_bloc/login_bloc.dart b/bytedesk_kefu/lib/blocs/login_bloc/login_bloc.dart index 5a0c3a4..dd13565 100755 --- a/bytedesk_kefu/lib/blocs/login_bloc/login_bloc.dart +++ b/bytedesk_kefu/lib/blocs/login_bloc/login_bloc.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +// import 'dart:async'; import 'package:bytedesk_kefu/model/codeResult.dart'; import 'package:bytedesk_kefu/model/jsonResult.dart'; import 'package:bytedesk_kefu/model/oauth.dart'; @@ -10,172 +10,179 @@ class LoginBloc extends Bloc { // final UserRepository _userRepository = new UserRepository(); - LoginBloc() : super(LoginInitial()); - - @override - Stream mapEventToState(LoginEvent event) async* { - // - if (event is LoginButtonPressed) { - yield* _mapLoginState(event); - } else if (event is SMSLoginButtonPressed) { - yield* _mapSMSLoginState(event); - } else if (event is RegisterButtonPressed) { - yield* _mapRegisterState(event); - } else if (event is RequestCodeButtonPressed) { - yield* _mapRequestCodeState(event); - } else if (event is BindMobileEvent) { - yield* _mapBindMobileState(event); - } else if (event is UnionidOAuthEvent) { - yield* _mapUnionidOAuthState(event); - } else if (event is ResetPasswordButtonPressed) { - yield* _mapResetPasswordState(event); - } else if (event is UpdatePasswordButtonPressed) { - yield* _mapUpdatePasswordState(event); - } + LoginBloc() : super(LoginInitial()) { + on(_mapLoginState); + on(_mapSMSLoginState); + on(_mapRegisterState); + on(_mapRequestCodeState); + on(_mapBindMobileState); + on(_mapUnionidOAuthState); + on(_mapResetPasswordState); + on(_mapUpdatePasswordState); } - Stream _mapLoginState(LoginButtonPressed event) async* { - yield LoginInProgress(); + // @override + // void mapEventToState(LoginEvent event, Emitter emit) async { + // // + // if (event is LoginButtonPressed) { + // yield* _mapLoginState(event); + // } else if (event is SMSLoginButtonPressed) { + // yield* _mapSMSLoginState(event); + // } else if (event is RegisterButtonPressed) { + // yield* _mapRegisterState(event); + // } else if (event is RequestCodeButtonPressed) { + // yield* _mapRequestCodeState(event); + // } else if (event is BindMobileEvent) { + // yield* _mapBindMobileState(event); + // } else if (event is UnionidOAuthEvent) { + // yield* _mapUnionidOAuthState(event); + // } else if (event is ResetPasswordButtonPressed) { + // yield* _mapResetPasswordState(event); + // } else if (event is UpdatePasswordButtonPressed) { + // yield* _mapUpdatePasswordState(event); + // } + // } + + void _mapLoginState(LoginButtonPressed event, Emitter emit) async { + emit(LoginInProgress()); try { OAuth oauth = await _userRepository.login(event.username, event.password); if (oauth.statusCode == 200) { // 用户名密码正确,登录成功 - yield LoginSuccess(); + emit(LoginSuccess()); } else { // 用户名密码错误,登录失败 - yield LoginError(); + emit(LoginError()); } } catch (error) { // 网络或其他错误 - yield LoginFailure(error: error.toString()); + emit(LoginFailure(error: error.toString())); } } - Stream _mapSMSLoginState(SMSLoginButtonPressed event) async* { - yield LoginInProgress(); + void _mapSMSLoginState(SMSLoginButtonPressed event, Emitter emit) async { + emit(LoginInProgress()); try { // OAuth oauth = await _userRepository.smsOAuth(event.mobile, event.code); if (oauth.statusCode == 200) { // 用户名密码正确,登录成功 - yield SMSLoginSuccess(); + emit(SMSLoginSuccess()); } else { // 用户名密码错误,登录失败 - yield LoginError(); + emit(LoginError()); } } catch (error) { // 网络或其他错误 - yield LoginFailure(error: error.toString()); + emit(LoginFailure(error: error.toString())); } } - Stream _mapRegisterState(RegisterButtonPressed event) async* { - yield RegisterInProgress(); + void _mapRegisterState(RegisterButtonPressed event, Emitter emit) async { + emit(RegisterInProgress()); try { // JsonResult jsonResult = await _userRepository.register(event.mobile, event.password); if (jsonResult.statusCode == 200) { - yield RegisterSuccess(); + emit(RegisterSuccess()); } else { - yield RegisterError( - message: jsonResult.message, statusCode: jsonResult.statusCode); + emit(RegisterError( + message: jsonResult.message, statusCode: jsonResult.statusCode)); } } catch (error) { // 网络或其他错误 - yield LoginFailure(error: error.toString()); + emit(LoginFailure(error: error.toString())); } } - Stream _mapRequestCodeState( - RequestCodeButtonPressed event) async* { - yield RequestCodeInProgress(); + void _mapRequestCodeState(RequestCodeButtonPressed event, Emitter emit) async { + emit(RequestCodeInProgress()); try { // CodeResult codeResult = await _userRepository.requestCode(event.mobile); if (codeResult.statusCode == 200) { - yield RequestCodeSuccess(codeResult: codeResult); + emit(RequestCodeSuccess(codeResult: codeResult)); } else { - yield RequestCodeError( - message: codeResult.message, statusCode: codeResult.statusCode); + emit(RequestCodeError( + message: codeResult.message, statusCode: codeResult.statusCode)); } } catch (error) { // 网络或其他错误 - yield LoginFailure(error: error.toString()); + emit(LoginFailure(error: error.toString())); } } - Stream _mapBindMobileState(BindMobileEvent event) async* { - yield BindMobileInProgress(); + void _mapBindMobileState(BindMobileEvent event, Emitter emit) async { + emit(BindMobileInProgress()); try { // JsonResult jsonResult = await _userRepository.bindMobile(event.mobile); if (jsonResult.statusCode == 200) { - yield BindMobileSuccess(jsonResult: jsonResult); + emit(BindMobileSuccess(jsonResult: jsonResult)); } else { - yield BindMobileError( - message: jsonResult.message, statusCode: jsonResult.statusCode); + emit(BindMobileError( + message: jsonResult.message, statusCode: jsonResult.statusCode)); } } catch (error) { // 网络或其他错误 - yield LoginFailure(error: error.toString()); + emit(LoginFailure(error: error.toString())); } } - Stream _mapUnionidOAuthState(UnionidOAuthEvent event) async* { - yield UnionidOAuthInProgress(); + void _mapUnionidOAuthState(UnionidOAuthEvent event, Emitter emit) async { + emit(UnionidOAuthInProgress()); try { // OAuth oauth = await _userRepository.unionIdOAuth(event.unionid); if (oauth.statusCode == 200) { // 登录成功 - yield UnionidLoginSuccess(); + emit(UnionidLoginSuccess()); } else { // 登录失败 - yield LoginError(); + emit(LoginError()); } } catch (error) { // 网络或其他错误 - yield LoginFailure(error: error.toString()); + emit(LoginFailure(error: error.toString())); } } - Stream _mapResetPasswordState( - ResetPasswordButtonPressed event) async* { - yield ResetPasswordInProgress(); + void _mapResetPasswordState(ResetPasswordButtonPressed event, Emitter emit) async { + emit(ResetPasswordInProgress()); try { // JsonResult jsonResult = await _userRepository.changePassword(event.mobile, event.password); if (jsonResult.statusCode == 200) { - yield ResetPasswordSuccess(); + emit(ResetPasswordSuccess()); } else { - yield ResetPasswordError( - message: jsonResult.message, statusCode: jsonResult.statusCode); + emit(ResetPasswordError( + message: jsonResult.message, statusCode: jsonResult.statusCode)); } } catch (error) { // 网络或其他错误 - yield LoginFailure(error: error.toString()); + emit(LoginFailure(error: error.toString())); } } - Stream _mapUpdatePasswordState( - UpdatePasswordButtonPressed event) async* { + void _mapUpdatePasswordState(UpdatePasswordButtonPressed event, Emitter emit) async { // - yield UpdatePasswordInProgress(); + emit(UpdatePasswordInProgress()); try { // JsonResult jsonResult = await _userRepository.changePassword(event.mobile, event.password); if (jsonResult.statusCode == 200) { - yield UpdatePasswordSuccess(); + emit(UpdatePasswordSuccess()); } else { - yield UpdatePasswordError( - message: jsonResult.message, statusCode: jsonResult.statusCode); + emit(UpdatePasswordError( + message: jsonResult.message, statusCode: jsonResult.statusCode)); } } catch (error) { // 网络或其他错误 - yield LoginFailure(error: error.toString()); + emit(LoginFailure(error: error.toString())); } } + } diff --git a/bytedesk_kefu/lib/blocs/message_bloc/message_bloc.dart b/bytedesk_kefu/lib/blocs/message_bloc/message_bloc.dart index 890d396..37aa5fd 100755 --- a/bytedesk_kefu/lib/blocs/message_bloc/message_bloc.dart +++ b/bytedesk_kefu/lib/blocs/message_bloc/message_bloc.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +// import 'dart:async'; import 'package:bytedesk_kefu/model/jsonResult.dart'; import 'package:bytedesk_kefu/model/message.dart'; import 'package:bytedesk_kefu/model/requestAnswer.dart'; @@ -11,154 +11,160 @@ class MessageBloc extends Bloc { // final MessageRepository messageRepository = new MessageRepository(); - MessageBloc() : super(InitialMessageState()); + MessageBloc() : super(InitialMessageState()) { + on(_mapRefreshCourseToState); + on(_mapUploadImageToState); + on(_mapUploadVideoToState); + on(_mapSendMessageRestToState); + on(_mapLoadHistoryMessageToState); + on(_mapLoadTopicMessageToState); - @override - Stream mapEventToState(MessageEvent event) async* { - if (event is ReceiveMessageEvent) { - yield* _mapRefreshCourseToState(event); - } else if (event is UploadImageEvent) { - yield* _mapUploadImageToState(event); - } else if (event is UploadVideoEvent) { - yield* _mapUploadVideoToState(event); - } else if (event is QueryAnswerEvent) { - yield* _mapQueryAnswerToState(event); - } else if (event is MessageAnswerEvent) { - yield* _mapMessageAnswerToState(event); - } else if (event is RateAnswerEvent) { - yield* _mapRateAnswerToState(event); - } else if (event is LoadHistoryMessageEvent) { - yield* _mapLoadHistoryMessageToState(event); - } else if (event is LoadTopicMessageEvent) { - yield* _mapLoadTopicMessageToState(event); - } else if (event is LoadChannelMessageEvent) { - yield* _mapLoadChannelMessageToState(event); - } else if (event is SendMessageRestEvent) { - yield* _mapSendMessageRestToState(event); - } + on(_mapLoadChannelMessageToState); + on(_mapQueryAnswerToState); + on(_mapMessageAnswerToState); + on(_mapRateAnswerToState); } - Stream _mapRefreshCourseToState( - ReceiveMessageEvent event) async* { + // @override + // void mapEventToState(MessageEvent event, Emitter emit) async { + // if (event is ReceiveMessageEvent) { + // yield* _mapRefreshCourseToState(event); + // } else if (event is UploadImageEvent) { + // yield* _mapUploadImageToState(event); + // } else if (event is UploadVideoEvent) { + // yield* _mapUploadVideoToState(event); + // } else if (event is QueryAnswerEvent) { + // yield* _mapQueryAnswerToState(event); + // } else if (event is MessageAnswerEvent) { + // yield* _mapMessageAnswerToState(event); + // } else if (event is RateAnswerEvent) { + // yield* _mapRateAnswerToState(event); + // } else if (event is LoadHistoryMessageEvent) { + // yield* _mapLoadHistoryMessageToState(event); + // } else if (event is LoadTopicMessageEvent) { + // yield* _mapLoadTopicMessageToState(event); + // } else if (event is LoadChannelMessageEvent) { + // yield* _mapLoadChannelMessageToState(event); + // } else if (event is SendMessageRestEvent) { + // yield* _mapSendMessageRestToState(event); + // } + // } + + void _mapRefreshCourseToState(ReceiveMessageEvent event, Emitter emit) async { try { - yield ReceiveMessageState(message: event.message); + emit(ReceiveMessageState(message: event.message)); } catch (error) { print(error); } } - Stream _mapUploadImageToState(UploadImageEvent event) async* { - yield MessageUpLoading(); + void _mapUploadImageToState(UploadImageEvent event, Emitter emit) async { + emit(MessageUpLoading()); try { final UploadJsonResult uploadJsonResult = await messageRepository.uploadImage(event.filePath); - yield UploadImageSuccess(uploadJsonResult); + emit(UploadImageSuccess(uploadJsonResult)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } - Stream _mapUploadVideoToState(UploadVideoEvent event) async* { - yield MessageUpLoading(); + void _mapUploadVideoToState(UploadVideoEvent event, Emitter emit) async { + emit(MessageUpLoading()); try { final UploadJsonResult uploadJsonResult = await messageRepository.uploadVideo(event.filePath); - yield UploadVideoSuccess(uploadJsonResult); + emit(UploadVideoSuccess(uploadJsonResult)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } - Stream _mapSendMessageRestToState( - SendMessageRestEvent event) async* { - yield RestMessageSending(); + void _mapSendMessageRestToState(SendMessageRestEvent event, Emitter emit) async { + emit(RestMessageSending()); try { final JsonResult jsonResult = await messageRepository.sendMessageRest(event.json); - yield SendMessageRestSuccess(jsonResult); + emit(SendMessageRestSuccess(jsonResult)); } catch (error) { print(error); - yield SendMessageRestError(); + emit(SendMessageRestError()); } } - Stream _mapLoadHistoryMessageToState( - LoadHistoryMessageEvent event) async* { - yield MessageLoading(); + void _mapLoadHistoryMessageToState(LoadHistoryMessageEvent event, Emitter emit) async { + emit(MessageLoading()); try { final List messageList = await messageRepository .loadHistoryMessages(event.uid, event.page, event.size); - yield LoadHistoryMessageSuccess(messageList: messageList); + emit(LoadHistoryMessageSuccess(messageList: messageList)); } catch (error) { print(error); - yield LoadHistoryMessageError(); + emit(LoadHistoryMessageError()); } } - Stream _mapLoadTopicMessageToState( - LoadTopicMessageEvent event) async* { - yield MessageLoading(); + void _mapLoadTopicMessageToState(LoadTopicMessageEvent event, Emitter emit) async { + emit(MessageLoading()); try { final List messageList = await messageRepository .loadTopicMessages(event.topic, event.page, event.size); - yield LoadTopicMessageSuccess(messageList: messageList); + emit(LoadTopicMessageSuccess(messageList: messageList)); } catch (error) { print(error); - yield LoadTopicMessageError(); + emit(LoadTopicMessageError()); } } - Stream _mapLoadChannelMessageToState( - LoadChannelMessageEvent event) async* { - yield MessageLoading(); + void _mapLoadChannelMessageToState(LoadChannelMessageEvent event, Emitter emit) async { + emit(MessageLoading()); try { final List messageList = await messageRepository .loadChannelMessages(event.cid, event.page, event.size); - yield LoadChannelMessageSuccess(messageList: messageList); + emit(LoadChannelMessageSuccess(messageList: messageList)); } catch (error) { print(error); - yield LoadChannelMessageError(); + emit(LoadChannelMessageError()); } } - Stream _mapQueryAnswerToState(QueryAnswerEvent event) async* { - yield MessageLoading(); + void _mapQueryAnswerToState(QueryAnswerEvent event, Emitter emit) async { + emit(MessageLoading()); try { final RequestAnswerResult requestAnswerResult = await messageRepository.queryAnswer(event.tid, event.aid); - yield QueryAnswerSuccess( - query: requestAnswerResult.query, answer: requestAnswerResult.anwser); + emit(QueryAnswerSuccess( + query: requestAnswerResult.query, answer: requestAnswerResult.anwser)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } - Stream _mapMessageAnswerToState( - MessageAnswerEvent event) async* { - yield MessageLoading(); + void _mapMessageAnswerToState(MessageAnswerEvent event, Emitter emit) async { + emit(MessageLoading()); try { final RequestAnswerResult requestAnswerResult = await messageRepository .messageAnswer(event.type, event.wid, event.aid, event.content); - yield MessageAnswerSuccess( - query: requestAnswerResult.query, answer: requestAnswerResult.anwser); + emit(MessageAnswerSuccess( + query: requestAnswerResult.query, answer: requestAnswerResult.anwser)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } - Stream _mapRateAnswerToState(RateAnswerEvent event) async* { - yield MessageLoading(); + void _mapRateAnswerToState(RateAnswerEvent event, Emitter emit) async { + emit(MessageLoading()); try { final RequestAnswerResult requestAnswerResult = await messageRepository.rateAnswer(event.aid, event.mid, event.rate); - yield RateAnswerSuccess(result: requestAnswerResult.anwser); + emit(RateAnswerSuccess(result: requestAnswerResult.anwser)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } } diff --git a/bytedesk_kefu/lib/blocs/profile_bloc/profile_bloc.dart b/bytedesk_kefu/lib/blocs/profile_bloc/profile_bloc.dart index a1015ce..3a893a5 100755 --- a/bytedesk_kefu/lib/blocs/profile_bloc/profile_bloc.dart +++ b/bytedesk_kefu/lib/blocs/profile_bloc/profile_bloc.dart @@ -9,172 +9,184 @@ class ProfileBloc extends Bloc { // final UserRepository userRepository = new UserRepository(); - ProfileBloc() : super(InitialProfileState()); - - @override - Stream mapEventToState(ProfileEvent event) async* { - // - if (event is GetProfileEvent) { - yield* _mapProfileState(); - } else if (event is UploadImageEvent) { - yield* _mapUploadImageToState(event); - } else if (event is UpdateAvatarEvent) { - yield* _mapUpdateAvatarToState(event); - } else if (event is UpdateNicknameEvent) { - yield* _mapUpdateNicknameToState(event); - } else if (event is UpdateDescriptionEvent) { - yield* _mapUpdateDescriptionToState(event); - } else if (event is UpdateMobileEvent) { - yield* _mapUpdateMobileToState(event); - } else if (event is UpdateSexEvent) { - yield* _mapUpdateSexToState(event); - } else if (event is UpdateLocationEvent) { - yield* _mapUpdateLocationToState(event); - } else if (event is UpdateBirthdayEvent) { - yield* _mapUpdateBirthdayToState(event); - } else if (event is QueryFollowEvent) { - yield* _mapQueryFollowToState(event); - } else if (event is UserFollowEvent) { - yield* _mapUserFollowToState(event); - } else if (event is UserUnfollowEvent) { - yield* _mapUserUnfollowToState(event); - } + ProfileBloc() : super(InitialProfileState()) { + on(_mapProfileState); + on(_mapUploadImageToState); + on(_mapUpdateAvatarToState); + on(_mapUpdateNicknameToState); + on(_mapUpdateDescriptionToState); + on(_mapUpdateMobileToState); + + on(_mapUpdateSexToState); + on(_mapUpdateLocationToState); + on(_mapUpdateBirthdayToState); + on(_mapQueryFollowToState); + on(_mapUserFollowToState); + + on(_mapUserUnfollowToState); + } - Stream _mapProfileState() async* { - yield ProfileInProgress(); + // @override + // void mapEventToState(ProfileEvent event, Emitter emit) async { + // // + // if (event is GetProfileEvent) { + // yield* _mapProfileState(); + // } else if (event is UploadImageEvent) { + // yield* _mapUploadImageToState(event); + // } else if (event is UpdateAvatarEvent) { + // yield* _mapUpdateAvatarToState(event); + // } else if (event is UpdateNicknameEvent) { + // yield* _mapUpdateNicknameToState(event); + // } else if (event is UpdateDescriptionEvent) { + // yield* _mapUpdateDescriptionToState(event); + // } else if (event is UpdateMobileEvent) { + // yield* _mapUpdateMobileToState(event); + // } else if (event is UpdateSexEvent) { + // yield* _mapUpdateSexToState(event); + // } else if (event is UpdateLocationEvent) { + // yield* _mapUpdateLocationToState(event); + // } else if (event is UpdateBirthdayEvent) { + // yield* _mapUpdateBirthdayToState(event); + // } else if (event is QueryFollowEvent) { + // yield* _mapQueryFollowToState(event); + // } else if (event is UserFollowEvent) { + // yield* _mapUserFollowToState(event); + // } else if (event is UserUnfollowEvent) { + // yield* _mapUserUnfollowToState(event); + // } + // } + + void _mapProfileState(GetProfileEvent event, Emitter emit) async { + emit(ProfileInProgress()); try { User user = await userRepository.getProfile(); - yield ProfileSuccess(user: user); + emit(ProfileSuccess(user: user)); } catch (error) { // 网络或其他错误 - yield ProfileFailure(error: error.toString()); + emit(ProfileFailure(error: error.toString())); } } - Stream _mapUploadImageToState(UploadImageEvent event) async* { - yield ProfileInProgress(); + void _mapUploadImageToState(UploadImageEvent event, Emitter emit) async { + emit(ProfileInProgress()); try { final String url = await userRepository.upload(event.filePath); - yield UploadImageSuccess(url); + emit(UploadImageSuccess(url)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } - Stream _mapUpdateAvatarToState(UpdateAvatarEvent event) async* { - yield ProfileInProgress(); + void _mapUpdateAvatarToState(UpdateAvatarEvent event, Emitter emit) async { + emit(ProfileInProgress()); try { final User user = await userRepository.updateAvatar(event.avatar); - yield UpdateAvatarSuccess(user); + emit(UpdateAvatarSuccess(user)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } - Stream _mapUpdateNicknameToState( - UpdateNicknameEvent event) async* { - yield ProfileInProgress(); + void _mapUpdateNicknameToState(UpdateNicknameEvent event, Emitter emit) async { + emit(ProfileInProgress()); try { final User user = await userRepository.updateNickname(event.nickname); - yield UpdateNicknameSuccess(user); + emit(UpdateNicknameSuccess(user)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } - Stream _mapUpdateDescriptionToState( - UpdateDescriptionEvent event) async* { - yield ProfileInProgress(); + void _mapUpdateDescriptionToState(UpdateDescriptionEvent event, Emitter emit) async { + emit(ProfileInProgress()); try { final User user = await userRepository.updateDescription(event.description); - yield UpdateDescriptionSuccess(user); + emit(UpdateDescriptionSuccess(user)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } - Stream _mapUpdateMobileToState(UpdateMobileEvent event) async* { - yield ProfileInProgress(); + void _mapUpdateMobileToState(UpdateMobileEvent event, Emitter emit) async { + emit(ProfileInProgress()); try { final User user = await userRepository.updateMobile(event.mobile); - yield UpdateMobileSuccess(user); + emit(UpdateMobileSuccess(user)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } - Stream _mapUpdateSexToState(UpdateSexEvent event) async* { - yield ProfileInProgress(); + void _mapUpdateSexToState(UpdateSexEvent event, Emitter emit) async { + emit(ProfileInProgress()); try { final User user = await userRepository.updateSex(event.sex); - yield UpdateSexSuccess(user); + emit(UpdateSexSuccess(user)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } - Stream _mapUpdateLocationToState( - UpdateLocationEvent event) async* { - yield ProfileInProgress(); + void _mapUpdateLocationToState(UpdateLocationEvent event, Emitter emit) async { + emit(ProfileInProgress()); try { final User user = await userRepository.updateLocation(event.location); - yield UpdateLocationSuccess(user); + emit(UpdateLocationSuccess(user)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } - Stream _mapUpdateBirthdayToState( - UpdateBirthdayEvent event) async* { - yield ProfileInProgress(); + void _mapUpdateBirthdayToState(UpdateBirthdayEvent event, Emitter emit) async { + emit(ProfileInProgress()); try { final User user = await userRepository.updateBirthday(event.birthday); - yield UpdateBirthdaySuccess(user); + emit(UpdateBirthdaySuccess(user)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } - Stream _mapQueryFollowToState(QueryFollowEvent event) async* { - yield QueryFollowing(); + void _mapQueryFollowToState(QueryFollowEvent event, Emitter emit) async { + emit(QueryFollowing()); try { final bool isFollowed = await userRepository.isFollowed(event.uid); - yield QueryFollowSuccess(isFollowed); + emit(QueryFollowSuccess(isFollowed)); } catch (error) { print(error); - yield QueryFollowError(); + emit(QueryFollowError()); } } - Stream _mapUserFollowToState(UserFollowEvent event) async* { - yield Following(); + void _mapUserFollowToState(UserFollowEvent event, Emitter emit) async { + emit(Following()); try { final JsonResult jsonResult = await userRepository.follow(event.uid); - yield FollowResultSuccess(jsonResult); + emit(FollowResultSuccess(jsonResult)); } catch (error) { print(error); - yield FollowError(); + emit(FollowError()); } } - Stream _mapUserUnfollowToState(UserUnfollowEvent event) async* { - yield Following(); + void _mapUserUnfollowToState(UserUnfollowEvent event, Emitter emit) async { + emit(Following()); try { final JsonResult jsonResult = await userRepository.unfollow(event.uid); - yield UnfollowResultSuccess(jsonResult); + emit(UnfollowResultSuccess(jsonResult)); } catch (error) { print(error); - yield UnFollowError(); + emit(UnFollowError()); } } } diff --git a/bytedesk_kefu/lib/blocs/thread_bloc/thread_bloc.dart b/bytedesk_kefu/lib/blocs/thread_bloc/thread_bloc.dart index 4342704..7a90f62 100755 --- a/bytedesk_kefu/lib/blocs/thread_bloc/thread_bloc.dart +++ b/bytedesk_kefu/lib/blocs/thread_bloc/thread_bloc.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +// import 'dart:async'; import 'package:bytedesk_kefu/model/markThread.dart'; import 'package:bloc/bloc.dart'; import './bloc.dart'; @@ -9,234 +9,219 @@ class ThreadBloc extends Bloc { // final ThreadRepository threadRepository = new ThreadRepository(); - ThreadBloc() : super(ThreadEmpty()); - - @override - Stream mapEventToState(ThreadEvent event) async* { - // - if (event is InitThreadEvent) { - yield InitialThreadState(); - } else if (event is RefreshThreadEvent) { - yield* _mapRefreshThreadToState(event); - } else if (event is RefreshHistoryThreadEvent) { - yield* _mapRefreshHistoryThreadToState(event); - } else if (event is RefreshVisitorThreadEvent) { - yield* _mapRefreshVisitorThreadToState(event); - } else if (event is RefreshVisitorThreadAllEvent) { - yield* _mapRefreshVisitorThreadAllToState(event); - } else if (event is RequestThreadEvent) { - yield* _mapRequestThreadToState(event); - } else if (event is RequestAgentEvent) { - yield* _mapRequestAgentToState(event); - } else if (event is RequestContactThreadEvent) { - yield* _mapRequestContactThreadToState(event); - } else if (event is RequestGroupThreadEvent) { - yield* _mapRequestGroupThreadToState(event); - } else if (event is MarkTopThreadEvent) { - yield* _mapMarkTopThreadEventToState(event); - } else if (event is UnMarkTopThreadEvent) { - yield* _mapUnMarkTopThreadEventToState(event); - } else if (event is MarkNodisturbThreadEvent) { - yield* _mapMarkNodisturbThreadEventToState(event); - } else if (event is UnMarkNodisturbThreadEvent) { - yield* _mapUnMarkNodisturbThreadEventToState(event); - } else if (event is MarkUnreadThreadEvent) { - yield* _mapMarkUnreadThreadEventToState(event); - } else if (event is UnMarkUnreadThreadEvent) { - yield* _mapUnMarkUnreadThreadEventToState(event); - } else if (event is DeleteThreadEvent) { - yield* _mapDeleteThreadEventToState(event); - } + // ThreadBloc() : super(ThreadEmpty()); + + ThreadBloc() : super(ThreadEmpty()) { + // on(InitialThreadState); + on(_mapRefreshThreadToState); + on(_mapRefreshHistoryThreadToState); + on(_mapRefreshVisitorThreadToState); + on(_mapRefreshVisitorThreadAllToState); + on(_mapRequestThreadToState); + + on(_mapRequestAgentToState); + on(_mapRequestContactThreadToState); + on(_mapRequestGroupThreadToState); + on(_mapMarkTopThreadEventToState); + on(_mapUnMarkTopThreadEventToState); + + on(_mapMarkNodisturbThreadEventToState); + on(_mapUnMarkNodisturbThreadEventToState); + on(_mapMarkUnreadThreadEventToState); + on(_mapUnMarkUnreadThreadEventToState); + on(_mapDeleteThreadEventToState); } - Stream _mapRefreshThreadToState( - RefreshThreadEvent event) async* { - yield ThreadLoading(); + void _mapRefreshThreadToState( + RefreshThreadEvent event, Emitter emit) async { + emit(ThreadLoading()); try { final List threadList = await threadRepository.getThreads(); - yield ThreadLoadSuccess(threadList); + emit(ThreadLoadSuccess(threadList)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } - Stream _mapRefreshHistoryThreadToState( - RefreshHistoryThreadEvent event) async* { - yield ThreadHistoryLoading(); + void _mapRefreshHistoryThreadToState( + RefreshHistoryThreadEvent event, Emitter emit) async { + emit(ThreadHistoryLoading()); try { final List threadList = await threadRepository.getHistoryThreads(event.page, event.size); - yield ThreadLoadSuccess(threadList); + emit(ThreadLoadSuccess(threadList)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } - Stream _mapRefreshVisitorThreadToState( - RefreshVisitorThreadEvent event) async* { - yield ThreadVisitorLoading(); + void _mapRefreshVisitorThreadToState( + RefreshVisitorThreadEvent event, Emitter emit) async { + emit(ThreadVisitorLoading()); try { final List threadList = await threadRepository.getVisitorThreads(event.page, event.size); - yield ThreadLoadSuccess(threadList); + emit(ThreadLoadSuccess(threadList)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } - Stream _mapRefreshVisitorThreadAllToState( - RefreshVisitorThreadAllEvent event) async* { - yield ThreadLoading(); + void _mapRefreshVisitorThreadAllToState( + RefreshVisitorThreadAllEvent event, Emitter emit) async { + emit(ThreadLoading()); try { final List threadList = await threadRepository.getVisitorThreadsAll(); - yield ThreadLoadSuccess(threadList); + emit(ThreadLoadSuccess(threadList)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } - Stream _mapRequestThreadToState( - RequestThreadEvent event) async* { - yield RequestThreading(); + void _mapRequestThreadToState( + RequestThreadEvent event, Emitter emit) async { + print('RequestThreadEvent'); + emit(RequestThreading()); try { final RequestThreadResult thread = await threadRepository.requestThread( event.wid, event.type, event.aid); - yield RequestThreadSuccess(thread); + emit(RequestThreadSuccess(thread)); } catch (error) { print(error); - yield RequestThreadError(); + emit(RequestThreadError()); } } - Stream _mapRequestAgentToState(RequestAgentEvent event) async* { - yield RequestAgentThreading(); + void _mapRequestAgentToState( + RequestAgentEvent event, Emitter emit) async { + emit(RequestAgentThreading()); try { final RequestThreadResult thread = await threadRepository.requestAgent(event.wid, event.type, event.aid); - yield RequestAgentSuccess(thread); + emit(RequestAgentSuccess(thread)); } catch (error) { print(error); - yield RequestAgentThreadError(); + emit(RequestAgentThreadError()); } } - Stream _mapRequestContactThreadToState( - RequestContactThreadEvent event) async* { - yield ThreadLoading(); + void _mapRequestContactThreadToState( + RequestContactThreadEvent event, Emitter emit) async { + emit(ThreadLoading()); try { final RequestThreadResult thread = await threadRepository.requestContactThread(event.cid); - yield RequestContactThreadSuccess(thread); + emit(RequestContactThreadSuccess(thread)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } - Stream _mapRequestGroupThreadToState( - RequestGroupThreadEvent event) async* { - yield ThreadLoading(); + void _mapRequestGroupThreadToState( + RequestGroupThreadEvent event, Emitter emit) async { + emit(ThreadLoading()); try { final RequestThreadResult thread = await threadRepository.requestGroupThread(event.gid); - yield RequestGroupThreadSuccess(thread); + emit(RequestGroupThreadSuccess(thread)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } - Stream _mapMarkTopThreadEventToState( - MarkTopThreadEvent event) async* { - yield ThreadLoading(); + void _mapMarkTopThreadEventToState( + MarkTopThreadEvent event, Emitter emit) async { + emit(ThreadLoading()); try { final MarkThreadResult thread = await threadRepository.markTop(event.tid); - yield MarkTopThreadSuccess(thread); + emit(MarkTopThreadSuccess(thread)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } - Stream _mapUnMarkTopThreadEventToState( - UnMarkTopThreadEvent event) async* { - yield ThreadLoading(); + void _mapUnMarkTopThreadEventToState( + UnMarkTopThreadEvent event, Emitter emit) async { + emit(ThreadLoading()); try { final MarkThreadResult thread = await threadRepository.unmarkTop(event.tid); - yield UnMarkTopThreadSuccess(thread); + emit(UnMarkTopThreadSuccess(thread)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } - Stream _mapMarkNodisturbThreadEventToState( - MarkNodisturbThreadEvent event) async* { - yield ThreadLoading(); + void _mapMarkNodisturbThreadEventToState( + MarkNodisturbThreadEvent event, Emitter emit) async { + emit(ThreadLoading()); try { final MarkThreadResult thread = await threadRepository.markNodisturb(event.tid); - yield MarkNodisturbThreadSuccess(thread); + emit(MarkNodisturbThreadSuccess(thread)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } - Stream _mapUnMarkNodisturbThreadEventToState( - UnMarkNodisturbThreadEvent event) async* { - yield ThreadLoading(); + void _mapUnMarkNodisturbThreadEventToState( + UnMarkNodisturbThreadEvent event, Emitter emit) async { + emit(ThreadLoading()); try { final MarkThreadResult thread = await threadRepository.unmarkNodisturb(event.tid); - yield UnMarkNodisturbThreadSuccess(thread); + emit(UnMarkNodisturbThreadSuccess(thread)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } - Stream _mapMarkUnreadThreadEventToState( - MarkUnreadThreadEvent event) async* { - yield ThreadLoading(); + void _mapMarkUnreadThreadEventToState( + MarkUnreadThreadEvent event, Emitter emit) async { + emit(ThreadLoading()); try { final MarkThreadResult thread = await threadRepository.markUnread(event.tid); - yield MarkUnreadThreadSuccess(thread); + emit(MarkUnreadThreadSuccess(thread)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } - Stream _mapUnMarkUnreadThreadEventToState( - UnMarkUnreadThreadEvent event) async* { - yield ThreadLoading(); + void _mapUnMarkUnreadThreadEventToState( + UnMarkUnreadThreadEvent event, Emitter emit) async { + emit(ThreadLoading()); try { final MarkThreadResult thread = await threadRepository.unmarkUnread(event.tid); - yield UnMarkUnreadThreadSuccess(thread); + emit(UnMarkUnreadThreadSuccess(thread)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } - Stream _mapDeleteThreadEventToState( - DeleteThreadEvent event) async* { - yield ThreadLoading(); + void _mapDeleteThreadEventToState( + DeleteThreadEvent event, Emitter emit) async { + emit(ThreadLoading()); try { final MarkThreadResult thread = await threadRepository.delete(event.tid); - yield DeleteThreadSuccess(thread); + emit(DeleteThreadSuccess(thread)); } catch (error) { print(error); - yield ThreadLoadError(); + emit(ThreadLoadError()); } } } diff --git a/bytedesk_kefu/lib/blocs/thread_bloc/thread_event.dart b/bytedesk_kefu/lib/blocs/thread_bloc/thread_event.dart index 283f157..17aa8c8 100755 --- a/bytedesk_kefu/lib/blocs/thread_bloc/thread_event.dart +++ b/bytedesk_kefu/lib/blocs/thread_bloc/thread_event.dart @@ -9,7 +9,7 @@ abstract class ThreadEvent extends Equatable { List get props => []; } -class InitThreadEvent extends ThreadEvent {} +// class InitThreadEvent extends ThreadEvent {} class RefreshThreadEvent extends ThreadEvent {} diff --git a/bytedesk_kefu/lib/blocs/ticket_bloc/ticket_bloc.dart b/bytedesk_kefu/lib/blocs/ticket_bloc/ticket_bloc.dart index 3e21f90..f2cc81c 100755 --- a/bytedesk_kefu/lib/blocs/ticket_bloc/ticket_bloc.dart +++ b/bytedesk_kefu/lib/blocs/ticket_bloc/ticket_bloc.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +// import 'dart:async'; import 'package:bytedesk_kefu/blocs/ticket_bloc/bloc.dart'; import 'package:bloc/bloc.dart'; import 'package:bytedesk_kefu/repositories/ticket_repository.dart'; @@ -7,54 +7,57 @@ class TicketBloc extends Bloc { // final TicketRepository feedbackRepository = new TicketRepository(); - TicketBloc() : super(new UnTicketState()); - - @override - Stream mapEventToState( - TicketEvent event, - ) async* { - if (event is GetTicketCategoryEvent) { - yield* _mapGetTicketCategoryToState(event); - } else if (event is SubmitTicketEvent) { - yield* _mapSubmitTicketToState(event); - } else if (event is UploadImageEvent) { - yield* _mapUploadImageToState(event); - } + TicketBloc() : super(new UnTicketState()) { + on(_mapGetTicketCategoryToState); + on(_mapSubmitTicketToState); + on(_mapUploadImageToState); } - Stream _mapGetTicketCategoryToState( - GetTicketCategoryEvent event) async* { - yield TicketLoading(); + // @override + // void mapEventToState( + // TicketEvent event, + // ) async* { + // if (event is GetTicketCategoryEvent) { + // yield* _mapGetTicketCategoryToState(event); + // } else if (event is SubmitTicketEvent) { + // yield* _mapSubmitTicketToState(event); + // } else if (event is UploadImageEvent) { + // yield* _mapUploadImageToState(event); + // } + // } + + void _mapGetTicketCategoryToState(GetTicketCategoryEvent event, Emitter emit) async { + emit(TicketLoading()); try { // final List categoryList = // await feedbackRepository.getHelpTicketCategories(); - // yield TicketCategoryState(categoryList); + // emit(TicketCategoryState(categoryList); } catch (error) { print(error); - yield TicketLoadError(); + emit(TicketLoadError()); } } - Stream _mapSubmitTicketToState(SubmitTicketEvent event) async* { - yield TicketLoading(); + void _mapSubmitTicketToState(SubmitTicketEvent event, Emitter emit) async { + emit(TicketLoading()); try { // final List categoryList = // await feedbackRepository.getHelpTicketCategories(); - // yield TicketCategoryState(categoryList); + // emit(TicketCategoryState(categoryList); } catch (error) { print(error); - yield TicketLoadError(); + emit(TicketLoadError()); } } - Stream _mapUploadImageToState(UploadImageEvent event) async* { - yield TicketLoading(); + void _mapUploadImageToState(UploadImageEvent event, Emitter emit) async { + emit(TicketLoading()); try { final String url = await feedbackRepository.upload(event.filePath); - yield UploadImageSuccess(url); + emit(UploadImageSuccess(url)); } catch (error) { print(error); - yield UpLoadImageError(); + emit(UpLoadImageError()); } } } diff --git a/bytedesk_kefu/lib/bytedesk_kefu.dart b/bytedesk_kefu/lib/bytedesk_kefu.dart index 4103425..27cb725 100644 --- a/bytedesk_kefu/lib/bytedesk_kefu.dart +++ b/bytedesk_kefu/lib/bytedesk_kefu.dart @@ -54,28 +54,23 @@ class BytedeskKefu { static void initWithUsernameAndNicknameAndAvatar(String username, String nickname, String avatar, String appKey, String subDomain) async { - // anonymousLogin(appKey, subDomain); /// sp初始化 await SpUtil.getInstance(); // 首先检测是否是第一次,如果是第一此启动 String? spusername = SpUtil.getString(BytedeskConstants.username); - if (spusername!.isEmpty) { - // 第一此启动, 则调用注册接口,否则调用登录接口 + String? sppassword = SpUtil.getString(BytedeskConstants.password); + if (spusername!.isNotEmpty) { + // 登录 + userLogin(spusername, sppassword!, appKey, subDomain); + } else { + // 调用注册接口 + // 默认密码同用户名 String password = username; await BytedeskUserHttpApi() .registerUser(username, nickname, password, avatar, subDomain); - username = username + "@" + subDomain; - userLogin(username, password, appKey, subDomain); - } else if (spusername == username) { - // 同一个账号,直接登录 - String password = username; - username = username + "@" + subDomain; - userLogin(username, password, appKey, subDomain); - } else { - // TODO: 切换新用户登录, 首先判断用户是否已经存在,如不存在着注册;如存在则直接登录 - // String password = username; - // username = username + "@" + subDomain; - // userLogin(username, password, appKey, subDomain); + // 注册成功之后,调用登录接口 + String usernameCompose = username + "@" + subDomain; + userLogin(usernameCompose, password, appKey, subDomain); } } @@ -128,7 +123,7 @@ class BytedeskKefu { } await BytedeskUserHttpApi().oauth(username, password); // 登录成功之后,建立长连接 - BytedeskUtils.mqttConnect(); + connect(); // if (role == BytedeskConstants.ROLE_ADMIN) { // // TODO: 如果是客服账号,加载个人信息 // } @@ -141,7 +136,7 @@ class BytedeskKefu { // await BytedeskUserHttpApi().unionIdOAuth(unionid); // 登录成功之后,建立长连接 - BytedeskUtils.mqttConnect(); + connect(); // 上传设备信息 await BytedeskDeviceHttpApi().setDeviceInfo(); } @@ -149,7 +144,7 @@ class BytedeskKefu { // 直接建立长连接 static void otherOAuth() async { // 登录成功之后,建立长连接 - BytedeskUtils.mqttConnect(); + connect(); // 上传设备信息 await BytedeskDeviceHttpApi().setDeviceInfo(); } @@ -164,6 +159,11 @@ class BytedeskKefu { return BytedeskUtils.mqttReConnect(); } + // 断开 + static void disconnect() { + BytedeskUtils.mqttDisconnect(); + } + // 判断长连接状态 static bool isConnected() { return BytedeskUtils.isMqttConnected(); @@ -489,6 +489,9 @@ class BytedeskKefu { // 退出登录 static Future logout() { + // 断开长链接 + disconnect(); + // 通知服务器,并清空本地数据 return BytedeskUserHttpApi().logout(); } diff --git a/bytedesk_kefu/lib/http/bytedesk_user_api.dart b/bytedesk_kefu/lib/http/bytedesk_user_api.dart index c067912..2d57872 100755 --- a/bytedesk_kefu/lib/http/bytedesk_user_api.dart +++ b/bytedesk_kefu/lib/http/bytedesk_user_api.dart @@ -17,7 +17,6 @@ import 'package:http/http.dart' as http; class BytedeskUserHttpApi extends BytedeskBaseHttpApi { // 授权 Future oauth(String? username, String? password) async { - // final oauthUrl = '$baseUrl/oauth/token'; var oauthUrl = Uri.http(BytedeskConstants.host, '/oauth/token'); // print("http api client: oauthUrl $oauthUrl"); Map headers = { @@ -31,12 +30,13 @@ class BytedeskUserHttpApi extends BytedeskBaseHttpApi { }; final oauthResponse = await this.httpClient.post(oauthUrl, headers: headers, body: bodyMap); - // print('oauth result: $oauthResponse'); + print('oauth result: $oauthResponse'); // check the status code for the result int statusCode = oauthResponse.statusCode; // print("statusCode $statusCode"); // 200: 授权成功,否则授权失败 final oauthJson = jsonDecode(oauthResponse.body); + // print('oauthJson:' + oauthJson); SpUtil.putBool(BytedeskConstants.isLogin, true); SpUtil.putString(BytedeskConstants.accessToken, oauthJson['access_token']); // @@ -187,28 +187,35 @@ class BytedeskUserHttpApi extends BytedeskBaseHttpApi { Uri.http(BytedeskConstants.host, '/visitor/api/register/user'); final initResponse = await this.httpClient.post(initUrl, headers: headers, body: body); - //解决json解析中的乱码问题 Utf8Decoder utf8decoder = Utf8Decoder(); // fix 中文乱码 //将string类型数据 转换为json类型的数据 final responseJson = json.decode(utf8decoder.convert(initResponse.bodyBytes)); - // final responseJson = json.decode(initResponse.body); print("responseJson $responseJson"); - // return JsonResult.fromJson(responseJson); + // int statusCode = responseJson['status_code']; if (statusCode == 200) { - // User user = User.fromJson(responseJson['data']); // SpUtil.putString(BytedeskConstants.uid, user.uid!); SpUtil.putString(BytedeskConstants.username, user.username!); + SpUtil.putString(BytedeskConstants.password, password!); SpUtil.putString(BytedeskConstants.nickname, user.nickname!); SpUtil.putString(BytedeskConstants.avatar, user.avatar!); SpUtil.putString(BytedeskConstants.description, user.description!); SpUtil.putString(BytedeskConstants.subDomain, user.subDomain!); // 解析用户资料 return user; + } else { + // + SpUtil.putString(BytedeskConstants.uid, responseJson['data']); + SpUtil.putString(BytedeskConstants.username, username! + '@' + subDomain!); + SpUtil.putString(BytedeskConstants.password, password!); + SpUtil.putString(BytedeskConstants.nickname, nickname!); + SpUtil.putString(BytedeskConstants.avatar, avatar!); + SpUtil.putString(BytedeskConstants.description, ""); + SpUtil.putString(BytedeskConstants.subDomain, subDomain); } return new User(); } @@ -240,9 +247,6 @@ class BytedeskUserHttpApi extends BytedeskBaseHttpApi { Future requestCode(String? mobile) async { // Map headers = {"Content-Type": "application/json"}; - // - // final initUrl = - // '$baseUrl/sms/api/send/liangshibao?mobile=$mobile&client=$client'; final initUrl = Uri.http(BytedeskConstants.host, '/sms/api/send/liangshibao', {'mobile': mobile, 'client': client}); final initResponse = await this.httpClient.get(initUrl, headers: headers); @@ -263,10 +267,8 @@ class BytedeskUserHttpApi extends BytedeskBaseHttpApi { Future bindMobile(String? mobile) async { // String? uid = SpUtil.getString(BytedeskConstants.uid); - // var body = json.encode({"uid": uid, "mobile": mobile, "client": client}); // - // final initUrl = '$baseUrl/api/user/bind/mobile'; final initUrl = Uri.http(BytedeskConstants.host, '/api/user/bind/mobile'); final initResponse = await this.httpClient.post(initUrl, headers: getHeaders(), body: body); @@ -288,7 +290,6 @@ class BytedeskUserHttpApi extends BytedeskBaseHttpApi { /// 初始化 Future getProfile() async { // - // final initUrl = '$baseUrl/api/user/profile?client=$client'; final initUrl = Uri.http( BytedeskConstants.host, '/api/user/profile/simple', {'client': client}); final initResponse = @@ -317,8 +318,6 @@ class BytedeskUserHttpApi extends BytedeskBaseHttpApi { Future updateNickname(String? nickname) async { // var body = json.encode({"nickname": nickname, "client": client}); - // - // final initUrl = '$baseUrl/api/user/nickname'; final initUrl = Uri.http(BytedeskConstants.host, '/api/user/nickname'); final initResponse = await this.httpClient.post(initUrl, headers: getHeaders(), body: body); @@ -774,8 +773,6 @@ class BytedeskUserHttpApi extends BytedeskBaseHttpApi { Map headers = {"Content-Type": "application/json"}; var body = json.encode({"client": client}); - - // final initUrl = '$baseUrl/api/user/logout?access_token=$accessToken'; final initUrl = Uri.http(BytedeskConstants.host, '/api/user/logout', {'access_token': accessToken}); final initResponse = @@ -784,23 +781,6 @@ class BytedeskUserHttpApi extends BytedeskBaseHttpApi { final responseJson = json.decode(initResponse.body); print("responseJson $responseJson"); // - // Preference.clearAccessToken(); BytedeskUtils.clearUserCache(); - // - // SpUtil.putString(BytedeskConstants.uid, ''); - // SpUtil.putString(BytedeskConstants.username, ''); - // SpUtil.putString(BytedeskConstants.nickname, ''); - // SpUtil.putString(BytedeskConstants.avatar, ''); - // SpUtil.putString(BytedeskConstants.description, ''); - // SpUtil.putString(BytedeskConstants.subDomain, ''); - // SpUtil.putString(BytedeskConstants.role, ''); - // // - // SpUtil.putString(BytedeskConstants.unionid, ''); - // SpUtil.putString(BytedeskConstants.openid, ''); - // // - // SpUtil.putBool(BytedeskConstants.isLogin, false); - // SpUtil.putBool(BytedeskConstants.isAuthenticated, false); - // SpUtil.putString(BytedeskConstants.mobile, ''); - // SpUtil.putString(BytedeskConstants.accessToken, ''); } } diff --git a/bytedesk_kefu/lib/model/messageProvider.dart b/bytedesk_kefu/lib/model/messageProvider.dart index ed13da1..f8f2a56 100755 --- a/bytedesk_kefu/lib/model/messageProvider.dart +++ b/bytedesk_kefu/lib/model/messageProvider.dart @@ -67,7 +67,7 @@ class MessageProvider { version: 9, ); // database path:/Users/ningjinpeng/Library/Developer/CoreSimulator/Devices/715CBA02-A602-4DE1-8C57-75A64B53BF03/data/Containers/Data/Application/8F46273D-9492-4C42-A618-4DF3815562BA/Documents/bytedesk-message-v9.db - // print('database path:' + database!.path); + print('database path:' + database!.path); } Future insert(Message message) async { diff --git a/bytedesk_kefu/lib/mqtt/bytedesk_mqtt.dart b/bytedesk_kefu/lib/mqtt/bytedesk_mqtt.dart index 39cc64a..ec2131f 100755 --- a/bytedesk_kefu/lib/mqtt/bytedesk_mqtt.dart +++ b/bytedesk_kefu/lib/mqtt/bytedesk_mqtt.dart @@ -24,7 +24,7 @@ import 'package:bytedesk_kefu/protobuf/thread.pb.dart' as protothread; // ignore: import_of_legacy_library_into_null_safe import 'package:bytedesk_kefu/protobuf/user.pb.dart' as protouser; import 'package:flutter/services.dart'; -import 'package:fluttertoast/fluttertoast.dart'; +// import 'package:fluttertoast/fluttertoast.dart'; // import 'package:vibration/vibration.dart'; class BytedeskMqtt { @@ -46,13 +46,13 @@ class BytedeskMqtt { return _singleton; } BytedeskMqtt._internal() { - _connect(); - } - // - void _connect() async { - // + // _connect(); reconnect(); } + // + // void _connect() async { + // reconnect(); + // } void reconnect() async { // eventbus发送广播,连接中... @@ -60,8 +60,6 @@ class BytedeskMqtt { .fire(ConnectionEventBus(BytedeskConstants.USER_STATUS_CONNECTING)); // currentUid = SpUtil.getString(BytedeskConstants.uid); - // String role = SpUtil.getString(BytedeskConstants.role, - // defValue: BytedeskConstants.ROLE_VISITOR); client = BytedeskUtils.getClient(); clientId = "$currentUid/$client"; @@ -81,6 +79,11 @@ class BytedeskMqtt { MqttServerClient(BytedeskConstants.webSocketWssUrl, clientId!); mqttClient.useWebSocket = true; mqttClient.port = 443; + + /// You can also supply your own websocket protocol list or disable this feature using the websocketProtocols + /// setter, read the API docs for further details here, the vast majority of brokers will support the client default + /// list so in most cases you can ignore this. Mosquito needs the single default setting. + // mqttClient.websocketProtocols = MqttClientConstants.protocolsSingleDefault; } else { mqttClient = MqttServerClient(BytedeskConstants.mqttHost, clientId!); mqttClient.port = BytedeskConstants.mqttPort; @@ -92,6 +95,7 @@ class BytedeskMqtt { mqttClient.setProtocolV311(); /// Set logging on if needed, defaults to off + // mqttClient.logging(on: BytedeskConstants.isDebug); mqttClient.logging(on: false); // BytedeskConstants.isDebug /// If you intend to use a keep alive value in your connect message that is not the default(60s) /// you must set it here @@ -111,7 +115,7 @@ class BytedeskMqtt { /// client identifier, any supplied username/password, the default keepalive interval(60s) /// and clean session, an example of a specific one below. - final MqttConnectMessage connMess = MqttConnectMessage() + final MqttConnectMessage connMessage = MqttConnectMessage() .withClientIdentifier(clientId!) .authenticateAs('username', 'password'); // TODO: 服务器暂时不需要auth,随便填写 // .keepAliveFor(keepAlivePeriod); // Must agree with the keep alive set above or not set @@ -123,7 +127,7 @@ class BytedeskMqtt { if (BytedeskConstants.isDebug) { print('mqttClient connecting....'); } - mqttClient.connectionMessage = connMess; + mqttClient.connectionMessage = connMessage; /// Connect the client, any errors here are communicated by raising of the appropriate exception. Note /// in some circumstances the broker will just disconnect us, see the spec about this, we however eill @@ -162,7 +166,7 @@ class BytedeskMqtt { // print('Published notification:: topic is ${messageBinary.variableHeader.topicName}, with Qos ${messageBinary.header.qos}'); // protomsg.Message messageProto = - protomsg.Message.fromBuffer(messageBinary.payload.message!); + protomsg.Message.fromBuffer(messageBinary.payload.message); // FIXME: 自己发送的消息显示两条?此处根据mid去个重 var mid = messageProto.mid; if (midList.contains(mid)) { @@ -220,7 +224,8 @@ class BytedeskMqtt { isSend: uid == currentUid ? 1 : 0, currentUid: currentUid, thread: thread, - user: user); + user: user, + client: client); // 是否发送消息回执 // var autoReply = false; var sendReceipt = false; @@ -282,10 +287,15 @@ class BytedeskMqtt { message.content = messageProto.text.content; break; } + case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_QUEUE: + { + message.content = messageProto.text.content; + break; + } case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_QUEUE_ACCEPT: { // 替换 'joinQueueThread' - message.content = '接入队列会话'; + message.content = '接入队列会话'; // TODO: 国际化 break; } case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_AGENT_CLOSE: @@ -667,8 +677,7 @@ class BytedeskMqtt { currentThread, extraParam); } - void publish(String content, String type, Thread currentThread, - ExtraParam? extraParam) { + void publish(String content, String type, Thread currentThread, ExtraParam? extraParam) { // if (currentThread == null) { // print('连接客服失败,请退出页面重新进入。注意: 请在App启动的时候,调用init接口'); // Fluttertoast.showToast(msg: '连接客服失败,请退出页面重新进入'); @@ -699,7 +708,7 @@ class BytedeskMqtt { user.avatar = SpUtil.getString(BytedeskConstants.avatar)!; // msg protomsg.Message messageProto = new protomsg.Message(); - messageProto.mid = BytedeskUuid.generateV4(); + messageProto.mid = BytedeskUuid.uuid(); messageProto.type = type; messageProto.timestamp = BytedeskUtils.formatedDateNow(); messageProto.client = BytedeskUtils.getClient(); //BytedeskConstants.client; @@ -710,7 +719,7 @@ class BytedeskMqtt { message.mid = messageProto.mid; message.type = messageProto.type; message.timestamp = messageProto.timestamp; - // message.client + message.client = messageProto.client; message.nickname = user.nickname; message.avatar = user.avatar; message.topic = thread.topic; diff --git a/bytedesk_kefu/lib/mqtt/lib/mqtt_browser_client.dart b/bytedesk_kefu/lib/mqtt/lib/mqtt_browser_client.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/mqtt_client.dart b/bytedesk_kefu/lib/mqtt/lib/mqtt_client.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/mqtt_server_client.dart b/bytedesk_kefu/lib/mqtt/lib/mqtt_server_client.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/browser/mqtt_client_mqtt_browser_connection.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/browser/mqtt_client_mqtt_browser_connection.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/browser/mqtt_client_mqtt_browser_connection_handler.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/browser/mqtt_client_mqtt_browser_connection_handler.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/browser/mqtt_client_mqtt_browser_ws_connection.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/browser/mqtt_client_mqtt_browser_ws_connection.dart old mode 100755 new mode 100644 index ccf50d7..d8ead70 --- a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/browser/mqtt_client_mqtt_browser_ws_connection.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/browser/mqtt_client_mqtt_browser_ws_connection.dart @@ -52,8 +52,8 @@ class MqttBrowserWsConnection extends MqttBrowserConnection { client = WebSocket(uriString, protocols); client.binaryType = 'arraybuffer'; messageStream = MqttByteBuffer(typed.Uint8Buffer()); - var closeEvents; - var errorEvents; + dynamic closeEvents; + dynamic errorEvents; client.onOpen.listen((e) { MqttLogger.log('MqttBrowserWsConnection::connect - websocket is open'); closeEvents.cancel(); @@ -117,8 +117,8 @@ class MqttBrowserWsConnection extends MqttBrowserConnection { client = WebSocket(uriString, protocols); client.binaryType = 'arraybuffer'; messageStream = MqttByteBuffer(typed.Uint8Buffer()); - var closeEvents; - var errorEvents; + dynamic closeEvents; + dynamic errorEvents; client.onOpen.listen((e) { MqttLogger.log( 'MqttBrowserWsConnection::connectAuto - websocket is open'); @@ -181,4 +181,13 @@ class MqttBrowserWsConnection extends MqttBrowserConnection { client = null; } } + + /// Stops listening and closes the socket immediately. + @override + void stopListening() { + if (client != null) { + listener?.cancel(); + client.close(); + } + } } diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/browser/mqtt_client_synchronous_mqtt_browser_connection_handler.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/browser/mqtt_client_synchronous_mqtt_browser_connection_handler.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_connection_state.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_connection_state.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_imqtt_connection_handler.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_imqtt_connection_handler.dart old mode 100755 new mode 100644 index c8eae83..3ee6478 --- a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_imqtt_connection_handler.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_imqtt_connection_handler.dart @@ -49,6 +49,9 @@ abstract class IMqttConnectionHandler { /// Closes a connection. void close(); + /// Kills all listeners from old connections. + void stopListening(); + /// Connects to a message broker /// The broker server to connect to /// The port to connect to diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_mqtt_connection_base.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_mqtt_connection_base.dart old mode 100755 new mode 100644 index 10ab2a7..686250d --- a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_mqtt_connection_base.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_mqtt_connection_base.dart @@ -21,6 +21,10 @@ class MqttConnectionBase { @protected dynamic client; + /// The stream controller as returned when clients listen. + @protected + StreamSubscription? listener; + /// The read wrapper @protected ReadWrapper? readWrapper; @@ -75,12 +79,17 @@ class MqttConnectionBase { void _disconnect() { if (client != null) { - client.close(); + listener?.cancel(); client.destroy(); + client.close(); client = null; } } + /// Stops listening and closes the socket immediately, must be overridden in + /// connection classes + void stopListening() {} + /// User requested or auto disconnect disconnection @protected void disconnect({bool auto = false}) { diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_mqtt_connection_handler_base.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_mqtt_connection_handler_base.dart old mode 100755 new mode 100644 index f27680c..993447d --- a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_mqtt_connection_handler_base.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_mqtt_connection_handler_base.dart @@ -184,6 +184,11 @@ abstract class MqttConnectionHandlerBase implements IMqttConnectionHandler { } } + @override + void stopListening() { + connection.stopListening(); + } + /// Registers for the receipt of messages when they arrive. @override void registerForMessage( diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_mqtt_connection_keep_alive.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_mqtt_connection_keep_alive.dart old mode 100755 new mode 100644 index 9ec32bb..5af6ac8 --- a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_mqtt_connection_keep_alive.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_mqtt_connection_keep_alive.dart @@ -16,11 +16,16 @@ typedef PongCallback = void Function(); /// This class implements the keep alive by sending an MqttPingRequest /// to the broker if a message has not been sent or received /// within the keep alive period. +/// Optionally a disconnect on no response property can be set to force disconnect the client +/// if the broker does not respond to a ping request for a specified period of time. class MqttConnectionKeepAlive { /// Initializes a new instance of the MqttConnectionKeepAlive class. - MqttConnectionKeepAlive( - IMqttConnectionHandler connectionHandler, int keepAliveSeconds) { + MqttConnectionKeepAlive(IMqttConnectionHandler connectionHandler, + events.EventBus? eventBus, int keepAliveSeconds, + [int disconnectOnNoResponsePeriod = 0]) { _connectionHandler = connectionHandler; + _clientEventBus = eventBus; + this.disconnectOnNoResponsePeriod = disconnectOnNoResponsePeriod * 1000; keepAlivePeriod = keepAliveSeconds * 1000; // Register for message handling of ping request and response messages. connectionHandler.registerForMessage( @@ -31,15 +36,28 @@ class MqttConnectionKeepAlive { // Start the timer so we do a ping whenever required. pingTimer = Timer(Duration(milliseconds: keepAlivePeriod), pingRequired); MqttLogger.log( - 'MqttConnectionKeepAlive:: initialised with a keep alive value of $keepAliveSeconds seconds'); + 'MqttConnectionKeepAlive:: Initialised with a keep alive value of $keepAliveSeconds seconds'); + disconnectOnNoResponsePeriod == 0 + ? MqttLogger.log( + 'MqttConnectionKeepAlive:: Disconnect on no ping response is disabled') + : MqttLogger.log( + 'MqttConnectionKeepAlive:: Disconnect on no ping response is enabled with a value of $disconnectOnNoResponsePeriod seconds'); } /// The keep alive period in milliseconds late int keepAlivePeriod; + /// The period of time to wait if the broker does not respond to a ping request, in milliseconds. + /// If this time period is exceeded the client is forcibly disconnected. + /// The default is 0, which disables this functionality. + int disconnectOnNoResponsePeriod = 0; + /// The timer that manages the ping callbacks. Timer? pingTimer; + /// Timer that manages the disconnect on no ping response period. + Timer? disconnectTimer; + /// The connection handler late IMqttConnectionHandler _connectionHandler; @@ -49,6 +67,9 @@ class MqttConnectionKeepAlive { /// Ping response received callback PongCallback? pongCallback; + /// The event bus + events.EventBus? _clientEventBus; + /// Pings the message broker if there has been no activity for /// the specified amount of idle time. bool pingRequired() { @@ -73,6 +94,30 @@ class MqttConnectionKeepAlive { MqttLogger.log( 'MqttConnectionKeepAlive::pingRequired - restarting ping timer'); pingTimer = Timer(Duration(milliseconds: keepAlivePeriod), pingRequired); + if (disconnectOnNoResponsePeriod != 0) { + if (disconnectTimer == null) { + MqttLogger.log( + 'MqttConnectionKeepAlive::pingRequired - starting disconnect timer'); + if (pinged) { + disconnectTimer = Timer( + Duration(milliseconds: disconnectOnNoResponsePeriod), + noPingResponseReceived); + } + } else { + if (disconnectTimer != null && !disconnectTimer!.isActive) { + if (pinged) { + MqttLogger.log( + 'MqttConnectionKeepAlive::pingRequired - restarting disconnect timer'); + disconnectTimer = Timer( + Duration(milliseconds: disconnectOnNoResponsePeriod), + noPingResponseReceived); + } + } else { + MqttLogger.log( + 'MqttConnectionKeepAlive::pingRequired - disconnect timer is active, not restarting'); + } + } + } _shutdownPadlock = false; return pinged; } @@ -101,6 +146,8 @@ class MqttConnectionKeepAlive { if (pongCallback != null) { pongCallback!(); } + // Cancel the disconnect timer if needed. + disconnectTimer?.cancel(); return true; } @@ -111,5 +158,27 @@ class MqttConnectionKeepAlive { void stop() { MqttLogger.log('MqttConnectionKeepAlive::stop - stopping keep alive'); pingTimer!.cancel(); + disconnectTimer?.cancel(); + } + + /// Handle the disconnect timer timeout + void noPingResponseReceived() { + // Only disconnect if we are connected. + if (_connectionHandler.connectionStatus.state == + MqttConnectionState.connected) { + MqttLogger.log( + 'MqttConnectionKeepAlive::noPingResponseReceived - connected, attempting to disconnect'); + if (_clientEventBus != null) { + _clientEventBus!.fire(DisconnectOnNoPingResponse()); + MqttLogger.log( + 'MqttConnectionKeepAlive::noPingResponseReceived - OK - disconnect event fired'); + } else { + MqttLogger.log( + 'MqttConnectionKeepAlive::noPingResponseReceived - ERROR - disconnect event not fired, no event handler'); + } + } else { + MqttLogger.log( + 'MqttConnectionKeepAlive::noPingResponseReceived - not disconnecting, not connected'); + } } } diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_read_wrapper.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/mqtt_client_read_wrapper.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_connection.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_connection.dart old mode 100755 new mode 100644 index a768ecd..ec5454b --- a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_connection.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_connection.dart @@ -36,7 +36,7 @@ class MqttServerConnection extends MqttConnectionBase { void _startListening() { MqttLogger.log('MqttServerConnection::_startListening'); try { - client.listen(_onData, onError: onError, onDone: onDone); + listener = client.listen(_onData, onError: onError, onDone: onDone); } on Exception catch (e) { print('MqttServerConnection::_startListening - exception raised $e'); } @@ -94,4 +94,14 @@ class MqttServerConnection extends MqttConnectionBase { final messageBytes = message.read(message.length); client?.add(messageBytes.toList()); } + + /// Stops listening and closes the socket immediately. + @override + void stopListening() { + if (client != null) { + listener?.cancel(); + client.destroy(); + client.close(); + } + } } diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_connection_handler.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_connection_handler.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_normal_connection.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_normal_connection.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_secure_connection.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_secure_connection.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_ws2_connection.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_ws2_connection.dart old mode 100755 new mode 100644 index fd27c30..6480243 --- a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_ws2_connection.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_ws2_connection.dart @@ -151,7 +151,8 @@ class MqttServerWs2Connection extends MqttServerConnection { messageStream = MqttByteBuffer(typed.Uint8Buffer()); MqttLogger.log('MqttWs2Connection::connect - start listening'); _startListening(); - completer.complete(); + completer.complete(MqttClientConnectionStatus() + ..state = MqttConnectionState.connected); }).catchError((dynamic e) { onError(e); completer.completeError(e); @@ -242,6 +243,15 @@ class MqttServerWs2Connection extends MqttServerConnection { return completer.future; } + /// Stops listening and closes the socket immediately. + @override + void stopListening() { + if (client != null) { + listener?.cancel(); + client.close(); + } + } + Future _performWSHandshake(Socket socket, Uri uri) async { _response = ''; final c = Completer(); diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_ws_connection.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_ws_connection.dart old mode 100755 new mode 100644 index 6d27f0a..6f90221 --- a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_ws_connection.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_mqtt_server_ws_connection.dart @@ -146,4 +146,13 @@ class MqttServerWsConnection extends MqttServerConnection { client = null; } } + + /// Stops listening and closes the socket immediately. + @override + void stopListening() { + if (client != null) { + listener?.cancel(); + client.close(); + } + } } diff --git a/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_synchronous_mqtt_server_connection_handler.dart b/bytedesk_kefu/lib/mqtt/lib/src/connectionhandling/server/mqtt_client_synchronous_mqtt_server_connection_handler.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/dataconvertors/mqtt_client_ascii_payload_convertor.dart b/bytedesk_kefu/lib/mqtt/lib/src/dataconvertors/mqtt_client_ascii_payload_convertor.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/dataconvertors/mqtt_client_passthru_payload_convertor.dart b/bytedesk_kefu/lib/mqtt/lib/src/dataconvertors/mqtt_client_passthru_payload_convertor.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/dataconvertors/mqtt_client_payload_convertor.dart b/bytedesk_kefu/lib/mqtt/lib/src/dataconvertors/mqtt_client_payload_convertor.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/encoding/mqtt_client_mqtt_encoding.dart b/bytedesk_kefu/lib/mqtt/lib/src/encoding/mqtt_client_mqtt_encoding.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_client_identifier_exception.dart b/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_client_identifier_exception.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_connection_exception.dart b/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_connection_exception.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_incorrect_instantiation_exception.dart b/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_incorrect_instantiation_exception.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_invalid_header_exception.dart b/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_invalid_header_exception.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_invalid_message_exception.dart b/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_invalid_message_exception.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_invalid_payload_size_exception.dart b/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_invalid_payload_size_exception.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_invalid_topic_exception.dart b/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_invalid_topic_exception.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_noconnection_exception.dart b/bytedesk_kefu/lib/mqtt/lib/src/exception/mqtt_client_noconnection_exception.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/management/mqtt_client_topic_filter.dart b/bytedesk_kefu/lib/mqtt/lib/src/management/mqtt_client_topic_filter.dart old mode 100755 new mode 100644 index f3bfd1e..48ea069 --- a/bytedesk_kefu/lib/mqtt/lib/src/management/mqtt_client_topic_filter.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/management/mqtt_client_topic_filter.dart @@ -20,7 +20,7 @@ class MqttClientTopicFilter { _subscriptionTopic = SubscriptionTopic(_topic); _clientUpdates!.listen(_topicIn); _updates = - StreamController>>.broadcast( + StreamController>>.broadcast( sync: true); } diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/connect/mqtt_client_mqtt_connect_flags.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/connect/mqtt_client_mqtt_connect_flags.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/connect/mqtt_client_mqtt_connect_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/connect/mqtt_client_mqtt_connect_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/connect/mqtt_client_mqtt_connect_payload.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/connect/mqtt_client_mqtt_connect_payload.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/connect/mqtt_client_mqtt_connect_return_code.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/connect/mqtt_client_mqtt_connect_return_code.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/connect/mqtt_client_mqtt_connect_variable_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/connect/mqtt_client_mqtt_connect_variable_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/connectack/mqtt_client_mqtt_connect_ack_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/connectack/mqtt_client_mqtt_connect_ack_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/connectack/mqtt_client_mqtt_connect_ack_variable_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/connectack/mqtt_client_mqtt_connect_ack_variable_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/disconnect/mqtt_client_mqtt_disconnect_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/disconnect/mqtt_client_mqtt_disconnect_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/mqtt_client_mqtt_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/mqtt_client_mqtt_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/mqtt_client_mqtt_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/mqtt_client_mqtt_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/mqtt_client_mqtt_message_factory.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/mqtt_client_mqtt_message_factory.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/mqtt_client_mqtt_message_type.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/mqtt_client_mqtt_message_type.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/mqtt_client_mqtt_payload.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/mqtt_client_mqtt_payload.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/mqtt_client_mqtt_variable_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/mqtt_client_mqtt_variable_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/pingrequest/mqtt_client_mqtt_ping_request_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/pingrequest/mqtt_client_mqtt_ping_request_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/pingresponse/mqtt_client_mqtt_ping_response_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/pingresponse/mqtt_client_mqtt_ping_response_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/publish/mqtt_client_mqtt_publish_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/publish/mqtt_client_mqtt_publish_message.dart old mode 100755 new mode 100644 index fa60ecf..74577ad --- a/bytedesk_kefu/lib/mqtt/lib/src/messages/publish/mqtt_client_mqtt_publish_message.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/messages/publish/mqtt_client_mqtt_publish_message.dart @@ -58,7 +58,7 @@ class MqttPublishMessage extends MqttMessage { /// Appends data to publish to the end of the current message payload. MqttPublishMessage publishData(typed.Uint8Buffer data) { - payload.message!.addAll(data); + payload.message.addAll(data); return this; } @@ -76,7 +76,7 @@ class MqttPublishMessage extends MqttMessage { /// Removes the current published data. MqttPublishMessage clearPublishData() { - payload.message!.clear(); + payload.message.clear(); return this; } diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/publish/mqtt_client_mqtt_publish_payload.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/publish/mqtt_client_mqtt_publish_payload.dart old mode 100755 new mode 100644 index db22335..723eccc --- a/bytedesk_kefu/lib/mqtt/lib/src/messages/publish/mqtt_client_mqtt_publish_payload.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/messages/publish/mqtt_client_mqtt_publish_payload.dart @@ -27,7 +27,7 @@ class MqttPublishPayload extends MqttPayload { MqttPublishVariableHeader? variableHeader; /// The message that forms the payload of the publish message. - typed.Uint8Buffer? message; + late typed.Uint8Buffer message; /// Creates a payload from the specified header stream. @override @@ -48,11 +48,11 @@ class MqttPublishPayload extends MqttPayload { /// Gets the length of the payload in bytes when written to a stream. @override - int getWriteLength() => message!.length; + int getWriteLength() => message.length; @override String toString() => - 'Payload: {${message!.length} bytes={${bytesToString(message!)}'; + 'Payload: {${message.length} bytes={${bytesToString(message)}'; /// Converts an array of bytes to a byte string. static String bytesToString(typed.Uint8Buffer message) { diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/publish/mqtt_client_mqtt_publish_variable_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/publish/mqtt_client_mqtt_publish_variable_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/publishack/mqtt_client_mqtt_publish_ack_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/publishack/mqtt_client_mqtt_publish_ack_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/publishack/mqtt_client_mqtt_publish_ack_variable_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/publishack/mqtt_client_mqtt_publish_ack_variable_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/publishcomplete/mqtt_client_mqtt_publish_complete_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/publishcomplete/mqtt_client_mqtt_publish_complete_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/publishcomplete/mqtt_client_mqtt_publish_complete_variable_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/publishcomplete/mqtt_client_mqtt_publish_complete_variable_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/publishreceived/mqtt_client_mqtt_publish_received_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/publishreceived/mqtt_client_mqtt_publish_received_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/publishreceived/mqtt_client_mqtt_publish_received_variable_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/publishreceived/mqtt_client_mqtt_publish_received_variable_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/publishrelease/mqtt_client_mqtt_publish_release_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/publishrelease/mqtt_client_mqtt_publish_release_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/publishrelease/mqtt_client_mqtt_publish_release_variable_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/publishrelease/mqtt_client_mqtt_publish_release_variable_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/subscribe/mqtt_client_mqtt_subscribe_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/subscribe/mqtt_client_mqtt_subscribe_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/subscribe/mqtt_client_mqtt_subscribe_payload.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/subscribe/mqtt_client_mqtt_subscribe_payload.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/subscribe/mqtt_client_mqtt_subscribe_variable_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/subscribe/mqtt_client_mqtt_subscribe_variable_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/subscribeack/mqtt_client_mqtt_subscribe_ack_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/subscribeack/mqtt_client_mqtt_subscribe_ack_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/subscribeack/mqtt_client_mqtt_subscribe_ack_payload.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/subscribeack/mqtt_client_mqtt_subscribe_ack_payload.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/subscribeack/mqtt_client_mqtt_subscribe_ack_variable_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/subscribeack/mqtt_client_mqtt_subscribe_ack_variable_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/unsubscribe/mqtt_client_mqtt_unsubscribe_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/unsubscribe/mqtt_client_mqtt_unsubscribe_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/unsubscribe/mqtt_client_mqtt_unsubscribe_payload.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/unsubscribe/mqtt_client_mqtt_unsubscribe_payload.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/unsubscribe/mqtt_client_mqtt_unsubscribe_variable_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/unsubscribe/mqtt_client_mqtt_unsubscribe_variable_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/unsubscribeack/mqtt_client_mqtt_unsubscribe_ack_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/unsubscribeack/mqtt_client_mqtt_unsubscribe_ack_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/messages/unsubscribeack/mqtt_client_mqtt_unsubscribe_ack_variable_header.dart b/bytedesk_kefu/lib/mqtt/lib/src/messages/unsubscribeack/mqtt_client_mqtt_unsubscribe_ack_variable_header.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_browser_client.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_browser_client.dart old mode 100755 new mode 100644 index 1797d98..a303b2d --- a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_browser_client.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_browser_client.dart @@ -44,6 +44,9 @@ class MqttBrowserClient extends MqttClient { [String? username, String? password]) async { instantiationCorrect = true; clientEventBus = events.EventBus(); + clientEventBus + ?.on() + .listen(disconnectOnNoPingResponse); connectionHandler = SynchronousMqttBrowserConnectionHandler( clientEventBus, maxConnectionAttempts: maxConnectionAttempts, diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client.dart index 7094aa3..4d84070 100755 --- a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client.dart @@ -35,12 +35,14 @@ class MqttClient { /// Initializes a new instance of the MqttClient class using /// the supplied Mqtt Port. - /// The server hostname to connect to - /// The client identifier to use to connect with + /// The server/hostname to connect to. + /// The client identifier to use to connect with. /// The port to use MqttClient.withPort(this.server, this.clientIdentifier, this.port); - /// Server name + /// Server name. + /// Note that a server name that is a host name must conform to the name + /// syntax described in RFC952 [https://datatracker.ietf.org/doc/html/rfc952] String server; /// Port number @@ -129,6 +131,13 @@ class MqttClient { /// enable keep alive. int keepAlivePeriod = MqttClientConstants.defaultKeepAlive; + /// The period of time to wait if the broker does not respond to a ping request + /// from keep alive processing, in seconds. + /// If this time period is exceeded the client is forcibly disconnected. + /// The default is 0, which disables this functionality. + /// Thi setting has no effect if keep alive is disabled. + int disconnectOnNoResponsePeriod = 0; + /// Handles everything to do with publication management. @protected PublishingManager? publishingManager; @@ -273,7 +282,8 @@ class MqttClient { if (keepAlivePeriod != MqttClientConstants.defaultKeepAlive) { MqttLogger.log( 'MqttClient::connect - keep alive is enabled with a value of $keepAlivePeriod seconds'); - keepAlive = MqttConnectionKeepAlive(connectionHandler, keepAlivePeriod); + keepAlive = MqttConnectionKeepAlive(connectionHandler, clientEventBus, + keepAlivePeriod, disconnectOnNoResponsePeriod); if (pongCallback != null) { keepAlive!.pongCallback = pongCallback; } @@ -366,9 +376,12 @@ class MqttClient { } } - /// Unsubscribe from a topic - void unsubscribe(String topic) { - subscriptionsManager!.unsubscribe(topic); + /// Unsubscribe from a topic. + /// Some brokers(AWS for instance) need to have each un subscription acknowledged, use + /// the [expectAcknowledge] parameter for this, default is false. + void unsubscribe(String topic, {expectAcknowledge = false}) { + subscriptionsManager! + .unsubscribe(topic, expectAcknowledge: expectAcknowledge); } /// Gets the current status of a subscription. @@ -390,6 +403,17 @@ class MqttClient { _disconnect(unsolicited: false); } + /// Called when the keep alive mechanism has determined that + /// a ping response expected from the broker has not arrived in the + /// time period specified by [disconnectOnNoResponsePeriod]. + void disconnectOnNoPingResponse(DisconnectOnNoPingResponse event) { + MqttLogger.log( + 'MqttClient::_disconnectOnNoPingResponse - disconnecting, no ping request response for $disconnectOnNoResponsePeriod seconds'); + // Destroy the existing client socket + connectionHandler?.connection?.disconnect(); + internalDisconnect(); + } + /// Internal disconnect /// This is always passed to the connection handler to allow the /// client to close itself down correctly on disconnect. @@ -426,7 +450,9 @@ class MqttClient { if (!unsolicited) { connectionHandler?.disconnect(); disconnectOrigin = MqttDisconnectionOrigin.solicited; + connectionHandler?.stopListening(); } + publishingManager?.published.close(); publishingManager = null; subscriptionsManager = null; diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_connection_status.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_connection_status.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_constants.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_constants.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_events.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_events.dart old mode 100755 new mode 100644 index f673bdc..1d335cc --- a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_events.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_events.dart @@ -67,6 +67,12 @@ class Resubscribe { /// Constructor Resubscribe({this.fromAutoReconnect = false}); - /// If set re sunscribe has been triggered from auto reconnect. + /// If set re subscribe has been triggered from auto reconnect. bool fromAutoReconnect = false; } + +/// Disconnect on keep alive on no ping response event +class DisconnectOnNoPingResponse { + /// Constructor + DisconnectOnNoPingResponse(); +} diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_ipublishing_manager.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_ipublishing_manager.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_message_identifier_dispenser.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_message_identifier_dispenser.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_mqtt_qos.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_mqtt_qos.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_mqtt_received_message.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_mqtt_received_message.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_protocol.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_protocol.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_publication_topic.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_publication_topic.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_publishing_manager.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_publishing_manager.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_subscription.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_subscription.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_subscription_status.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_subscription_status.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_subscription_topic.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_subscription_topic.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_subscriptions_manager.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_subscriptions_manager.dart old mode 100755 new mode 100644 index 451cf22..10d8c18 --- a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_subscriptions_manager.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_subscriptions_manager.dart @@ -132,12 +132,17 @@ class SubscriptionsManager { _subscriptionNotifier.add([msg]); } - /// Unsubscribe from a topic - void unsubscribe(String topic) { + /// Unsubscribe from a topic. + /// Some brokers(AWS for instance) need to have each un subscription acknowledged, use + /// the [expectAcknowledge] parameter for this, default is false. + void unsubscribe(String topic, {expectAcknowledge = false}) { final unsubscribeMsg = MqttUnsubscribeMessage() .withMessageIdentifier( messageIdentifierDispenser.getNextMessageIdentifier()) .fromTopic(topic); + if (expectAcknowledge) { + unsubscribeMsg.expectAcknowledgement(); + } connectionHandler!.sendMessage(unsubscribeMsg); pendingUnsubscriptions[unsubscribeMsg.variableHeader!.messageIdentifier] = topic; diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_topic.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_client_topic.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_server_client.dart b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_server_client.dart old mode 100755 new mode 100644 index 385161d..6e386df --- a/bytedesk_kefu/lib/mqtt/lib/src/mqtt_server_client.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/mqtt_server_client.dart @@ -60,6 +60,9 @@ class MqttServerClient extends MqttClient { [String? username, String? password]) async { instantiationCorrect = true; clientEventBus = events.EventBus(); + clientEventBus + ?.on() + .listen(disconnectOnNoPingResponse); connectionHandler = SynchronousMqttServerConnectionHandler( clientEventBus, maxConnectionAttempts: maxConnectionAttempts, @@ -69,6 +72,9 @@ class MqttServerClient extends MqttClient { connectionHandler.useWebSocket = true; connectionHandler.useAlternateWebSocketImplementation = useAlternateWebSocketImplementation; + if (connectionHandler.useAlternateWebSocketImplementation) { + connectionHandler.securityContext = securityContext; + } if (websocketProtocolString != null) { connectionHandler.websocketProtocols = websocketProtocolString; } diff --git a/bytedesk_kefu/lib/mqtt/lib/src/observable/observable.dart b/bytedesk_kefu/lib/mqtt/lib/src/observable/observable.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/observable/src/change_notifier.dart b/bytedesk_kefu/lib/mqtt/lib/src/observable/src/change_notifier.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/observable/src/observable.dart b/bytedesk_kefu/lib/mqtt/lib/src/observable/src/observable.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/observable/src/records.dart b/bytedesk_kefu/lib/mqtt/lib/src/observable/src/records.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/utility/mqtt_client_byte_buffer.dart b/bytedesk_kefu/lib/mqtt/lib/src/utility/mqtt_client_byte_buffer.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/utility/mqtt_client_logger.dart b/bytedesk_kefu/lib/mqtt/lib/src/utility/mqtt_client_logger.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/lib/src/utility/mqtt_client_payload_builder.dart b/bytedesk_kefu/lib/mqtt/lib/src/utility/mqtt_client_payload_builder.dart old mode 100755 new mode 100644 index 916e28e..b628c23 --- a/bytedesk_kefu/lib/mqtt/lib/src/utility/mqtt_client_payload_builder.dart +++ b/bytedesk_kefu/lib/mqtt/lib/src/utility/mqtt_client_payload_builder.dart @@ -7,7 +7,8 @@ part of mqtt_client; -/// Utility class to assist with the build in of message topic payloads. +/// Utility class to assist with the building of message topic payloads. +/// Implements the builder pattern, i.e. returns itself to allow chaining. class MqttClientPayloadBuilder { /// Construction MqttClientPayloadBuilder() { @@ -23,70 +24,81 @@ class MqttClientPayloadBuilder { int get length => _payload!.length; /// Add a buffer - void addBuffer(typed.Uint8Buffer buffer) { + MqttClientPayloadBuilder addBuffer(typed.Uint8Buffer buffer) { _payload!.addAll(buffer); + return this; } /// Add byte, this will overflow on values > 2**8-1 - void addByte(int val) { + MqttClientPayloadBuilder addByte(int val) { _payload!.add(val); + return this; } /// Add a bool, true is 1, false is 0 - void addBool({required bool val}) { + MqttClientPayloadBuilder addBool({required bool val}) { val ? addByte(1) : addByte(0); + return this; } - /// Add a halfword, 16 bits, this will overflow on values > 2**16-1 - void addHalf(int val) { + /// Add a half word, 16 bits, this will overflow on values > 2**16-1 + MqttClientPayloadBuilder addHalf(int val) { final tmp = Uint16List.fromList([val]); _payload!.addAll(tmp.buffer.asInt8List()); + return this; } /// Add a word, 32 bits, this will overflow on values > 2**32-1 - void addWord(int val) { + MqttClientPayloadBuilder addWord(int val) { final tmp = Uint32List.fromList([val]); _payload!.addAll(tmp.buffer.asInt8List()); + return this; } /// Add a long word, 64 bits or a Dart int - void addInt(int val) { + MqttClientPayloadBuilder addInt(int val) { final tmp = Uint64List.fromList([val]); _payload!.addAll(tmp.buffer.asInt8List()); + return this; } /// Add a standard Dart string - void addString(String val) { + MqttClientPayloadBuilder addString(String val) { addUTF16String(val); + return this; } /// Add a UTF16 string, note Dart natively encodes strings as UTF16 - void addUTF16String(String val) { - for (final codeunit in val.codeUnits) { - if (codeunit <= 255 && codeunit >= 0) { - _payload!.add(codeunit); + MqttClientPayloadBuilder addUTF16String(String val) { + for (final codeUnit in val.codeUnits) { + if (codeUnit <= 255 && codeUnit >= 0) { + _payload!.add(codeUnit); } else { - addHalf(codeunit); + addHalf(codeUnit); } } + return this; } /// Add a UTF8 string - void addUTF8String(String val) { + MqttClientPayloadBuilder addUTF8String(String val) { const encoder = Utf8Encoder(); _payload!.addAll(encoder.convert(val)); + return this; } /// Add a 32 bit double - void addHalfDouble(double val) { + MqttClientPayloadBuilder addHalfDouble(double val) { final tmp = Float32List.fromList([val]); _payload!.addAll(tmp.buffer.asInt8List()); + return this; } /// Add a 64 bit double - void addDouble(double val) { + MqttClientPayloadBuilder addDouble(double val) { final tmp = Float64List.fromList([val]); _payload!.addAll(tmp.buffer.asInt8List()); + return this; } // added by jackning, 2019/12/03 @@ -95,5 +107,8 @@ class MqttClientPayloadBuilder { } /// Clear the buffer - void clear() => _payload!.clear(); + MqttClientPayloadBuilder clear() { + _payload!.clear(); + return this; + } } diff --git a/bytedesk_kefu/lib/mqtt/lib/src/utility/mqtt_client_utilities.dart b/bytedesk_kefu/lib/mqtt/lib/src/utility/mqtt_client_utilities.dart old mode 100755 new mode 100644 diff --git a/bytedesk_kefu/lib/mqtt/readme.md b/bytedesk_kefu/lib/mqtt/readme.md index 396a350..a48360f 100755 --- a/bytedesk_kefu/lib/mqtt/readme.md +++ b/bytedesk_kefu/lib/mqtt/readme.md @@ -1,6 +1,7 @@ # mqtt 说明 -- 当前版本9.3.1, 更新日期2021/05/24 +- +- 当前版本9.6.7, 更新日期2022/05/05 - 在mqtt/lib/src/utility/mqtt_client_payload_builder.dart添加 ```dart diff --git a/bytedesk_kefu/lib/ui/chat/page/chat_kf_page.dart b/bytedesk_kefu/lib/ui/chat/page/chat_kf_page.dart index e566254..e59d91a 100755 --- a/bytedesk_kefu/lib/ui/chat/page/chat_kf_page.dart +++ b/bytedesk_kefu/lib/ui/chat/page/chat_kf_page.dart @@ -590,7 +590,7 @@ class _ChatKFPageState extends State message.mid = mid; message.type = type; message.timestamp = timestamp; - // message.client = client; + message.client = client; message.avatar = _currentAvatar; message.topic = this._currentThread!.topic; message.status = BytedeskConstants.MESSAGE_STATUS_SENDING; @@ -670,19 +670,30 @@ class _ChatKFPageState extends State _listener() { // 更新消息状态 bytedeskEventBus.on().listen((event) { - // print('更新状态:' + event.status); - if (!this.mounted) { - return; - } - // 更新界面, FIXME: 只有插入新消息,才会更新? - for (var i = 0; i < _messages.length; i++) { - MessageWidget messageWidget = _messages[i]; - if (messageWidget.message!.mid == event.mid && - _messages[i].message!.status != - BytedeskConstants.MESSAGE_STATUS_READ) { - setState(() { - _messages[i].message!.status = event.status; - }); + // print('更新状态:' + event.mid + '-' + event.status); + if (this.mounted) { + // 更新界面 + for (var i = 0; i < _messages.length; i++) { + MessageWidget messageWidget = _messages[i]; + if (messageWidget.message!.mid == event.mid && + _messages[i].message!.status != + BytedeskConstants.MESSAGE_STATUS_READ) { + // print('do update status:' + messageWidget.message!.mid!); + // setState(() { + // _messages[i].message!.status = event.status; // 不更新 + // }); + // 必须重新创建一个messageWidget才会更新 + Message message = messageWidget.message!; + message.status = event.status; + MessageWidget messageWidget2 = new MessageWidget( + message: message, + customCallback: widget.customCallback, + animationController: new AnimationController( + vsync: this, duration: Duration(milliseconds: 500))); + setState(() { + _messages[i] = messageWidget2; + }); + } } } }); @@ -937,25 +948,60 @@ class _ChatKFPageState extends State // TODO: 从服务器加载聊天记录 // FIXME: 消息排序错乱 Future _getMessages(int page, int size) async { + // BlocProvider.of(context) + // ..add(LoadHistoryMessageEvent(uid: _currentUid, page: page, size: size)); // List messageList = await _messageProvider.getTopicMessages( _currentThread!.topic, _currentUid, page, size); // print(messageList.length); - messageList.forEach((message) { - // print('mid: ' + message.mid! + ' content:' + message.content!); + int length = messageList.length; + for (var i = 0; i < length; i++) { + Message message = messageList[i]; + if (message.type == + BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_FORM_REQUEST || + message.type == + BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_FORM_RESULT) { + // 暂时忽略表单消息 + } else if (message.type == + BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_THREAD_REENTRY) { + // 连续的 ‘继续会话’ 消息,只显示最后一条 + if (i + 1 < length) { + var nextmsg = messageList[i + 1]; + if (nextmsg.type == + BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_THREAD_REENTRY) { + continue; + } else { + pushToMessageArray(message); + } + } + } else { + pushToMessageArray(message); + } + } + // + _page += 1; + } + + void pushToMessageArray(Message message) { + if (this.mounted) { MessageWidget messageWidget = new MessageWidget( message: message, customCallback: widget.customCallback, animationController: new AnimationController( vsync: this, duration: Duration(milliseconds: 500))); - if (this.mounted) { - setState(() { - _messages.add(messageWidget); + setState(() { + _messages.add(messageWidget); + _messages.sort((a, b) { + return b.message!.timestamp!.compareTo(a.message!.timestamp!); }); + }); + } + if (message.status != BytedeskConstants.MESSAGE_STATUS_READ) { + // 发送已读回执 + if (message.isSend == 0) { + _bdMqtt.sendReceiptReadMessage(message.mid!, _currentThread!); } - }); - // - _page += 1; + } } Future _appendMessage(Message message) async { @@ -965,6 +1011,8 @@ class _ChatKFPageState extends State Message? element = _messages[i].message; if (element!.mid == message.mid) { contains = true; + // 更新消息状态 + _messageProvider.update(element.mid, message.status); } } if (!contains) { diff --git a/bytedesk_kefu/lib/util/bytedesk_constants.dart b/bytedesk_kefu/lib/util/bytedesk_constants.dart index 8541b37..1ad26e1 100755 --- a/bytedesk_kefu/lib/util/bytedesk_constants.dart +++ b/bytedesk_kefu/lib/util/bytedesk_constants.dart @@ -8,17 +8,17 @@ class BytedeskConstants { // // TODO: 增加自定义服务器地址接口 // 公司debug - // static const bool isDebug = true; - // static const bool isSecure = false; - // static const bool isWebSocketWss = false; - // static const String webSocketWssUrl = 'wss://www.bytedesk.com/websocket'; - // static const String httpBaseUrl = 'http://' + mqttHost + ':8000'; - // static const String httpBaseUrlAndroid = 'http://' + mqttHost + ':8000'; - // static const String httpBaseUrliOS = 'http://' + mqttHost + ':8000'; - // static const String httpUploadUrl = 'http://' + mqttHost + ':8000'; - // static const String host = mqttHost + ':8000'; - // static const int mqttPort = 3883; // not secure - // static const String mqttHost = '172.16.0.65'; + static const bool isDebug = true; + static const bool isSecure = false; + static const bool isWebSocketWss = false; + static const String webSocketWssUrl = 'wss://www.bytedesk.com/websocket'; + static const String httpBaseUrl = 'http://' + mqttHost + ':8000'; + static const String httpBaseUrlAndroid = 'http://' + mqttHost + ':8000'; + static const String httpBaseUrliOS = 'http://' + mqttHost + ':8000'; + static const String httpUploadUrl = 'http://' + mqttHost + ':8000'; + static const String host = mqttHost + ':8000'; + static const int mqttPort = 3883; // not secure + static const String mqttHost = '172.16.0.78'; // 本机测试 // static const bool isDebug = true; @@ -48,19 +48,19 @@ class BytedeskConstants { // static const String mqttHost = '192.168.0.102'; // 线上 - static const bool isDebug = false; // false; - static const bool isSecure = true; // secure - static const bool isWebSocketWss = true; - static const String webSocketWssUrl = 'wss://flutter.bytedesk.com/websocket'; - static const int mqttPort = 13883; // secure - static const String httpBaseUrl = 'https://' + mqttHost; - static const String httpBaseUrlAndroid = 'https://' + mqttHost; - static const String httpBaseUrliOS = 'https://' + mqttHost; - static const String httpUploadUrl = 'https://upload.bytedesk.com'; - static const String host = mqttHost; - static const String mqttHost = 'flutter.bytedesk.com'; + // static const bool isDebug = false; // false; + // static const bool isSecure = true; // secure + // static const bool isWebSocketWss = true; + // static const String webSocketWssUrl = 'wss://flutter.bytedesk.com/websocket'; + // static const int mqttPort = 13883; // secure + // static const String httpBaseUrl = 'https://' + mqttHost; + // static const String httpBaseUrlAndroid = 'https://' + mqttHost; + // static const String httpBaseUrliOS = 'https://' + mqttHost; + // static const String httpUploadUrl = 'https://upload.bytedesk.com'; + // static const String host = mqttHost; + // static const String mqttHost = 'flutter.bytedesk.com'; - // + // static const String WORKGROUP_WID_LIANGSHIBAO = '201808101819291'; static const String CHAT_TYPE_WORKGROUP = 'workGroup'; static const String CHAT_TYPE_APPOINTED = 'appointed'; @@ -81,6 +81,7 @@ class BytedeskConstants { static const String user = 'bytedesk_user'; static const String uid = 'bytedesk_uid'; static const String username = 'bytedesk_username'; + static const String password = 'bytedesk_password'; static const String nickname = 'bytedesk_nickname'; static const String avatar = 'bytedesk_avatar'; static const String description = 'bytedesk_description'; @@ -278,6 +279,9 @@ class BytedeskConstants { 'notification_kickoff'; // 发送表单请求 static const String MESSAGE_TYPE_NOTIFICATION_FORM = 'notification_form'; + // 表单内嵌类型 + static const String MESSAGE_TYPE_NOTIFICATION_FORM_REQUEST = "notification_form_request"; + static const String MESSAGE_TYPE_NOTIFICATION_FORM_RESULT = "notification_form_result"; // 通知初始化localStream // static const String MESSAGE_TYPE_NOTIFICATION_WEBRTC_INVITE = 'notification_webrtc_invite' static const String MESSAGE_TYPE_NOTIFICATION_WEBRTC_INVITE_VIDEO = diff --git a/bytedesk_kefu/lib/util/bytedesk_eventbus.dart b/bytedesk_kefu/lib/util/bytedesk_eventbus.dart new file mode 100644 index 0000000..d7757ca --- /dev/null +++ b/bytedesk_kefu/lib/util/bytedesk_eventbus.dart @@ -0,0 +1,47 @@ +//订阅者回调签名 +typedef void EventCallback(arg); + +class BytedeskEventBus { + //私有构造函数 + BytedeskEventBus._internal(); + + //保存单例 + static BytedeskEventBus _singleton = BytedeskEventBus._internal(); + + //工厂构造函数 + factory BytedeskEventBus() => _singleton; + + //保存事件订阅者队列,key:事件名(id),value: 对应事件的订阅者队列 + final _emap = Map?>(); + + //添加订阅者 + void on(eventName, EventCallback f) { + _emap[eventName] ??= []; + _emap[eventName]!.add(f); + } + + //移除订阅者 + void off(eventName, [EventCallback? f]) { + var list = _emap[eventName]; + if (eventName == null || list == null) return; + if (f == null) { + _emap[eventName] = null; + } else { + list.remove(f); + } + } + + //触发事件,事件触发后该事件所有订阅者会被调用 + void emit(eventName, [arg]) { + var list = _emap[eventName]; + if (list == null) return; + int len = list.length - 1; + //反向遍历,防止订阅者在回调中移除自身带来的下标错位 + for (var i = len; i > -1; --i) { + list[i](arg); + } + } +} + +//定义一个top-level(全局)变量,页面引入该文件后可以直接使用bus +var bus = BytedeskEventBus(); diff --git a/bytedesk_kefu/lib/util/bytedesk_utils.dart b/bytedesk_kefu/lib/util/bytedesk_utils.dart index d6b05b7..0d3e109 100755 --- a/bytedesk_kefu/lib/util/bytedesk_utils.dart +++ b/bytedesk_kefu/lib/util/bytedesk_utils.dart @@ -140,6 +140,10 @@ class BytedeskUtils { return new BytedeskMqtt().isConnected(); } + static void mqttDisconnect() { + new BytedeskMqtt().disconnect(); + } + static double? getLatitude() { if (isWeb) { return SpUtil.getDouble(BytedeskConstants.latitude); @@ -182,6 +186,11 @@ class BytedeskUtils { return format.format(new DateTime.now()); } + static String formatedTimestampNow() { + var format = new DateFormat('yyyyMMddHHmmss'); + return format.format(new DateTime.now()); + } + static Map url2query(String url) { var search = new RegExp('([^&=]+)=?([^&]*)'); var result = new Map(); diff --git a/bytedesk_kefu/lib/util/bytedesk_uuid.dart b/bytedesk_kefu/lib/util/bytedesk_uuid.dart index ffe4d07..117d373 100755 --- a/bytedesk_kefu/lib/util/bytedesk_uuid.dart +++ b/bytedesk_kefu/lib/util/bytedesk_uuid.dart @@ -4,6 +4,8 @@ import 'dart:math'; +import 'package:bytedesk_kefu/util/bytedesk_utils.dart'; + /// A UUID generator, useful for generating unique IDs for your Todos. /// Shamelessly extracted from the Flutter source code. /// @@ -15,12 +17,22 @@ import 'dart:math'; /// /// final String id = Uuid().generateV4(); class BytedeskUuid { + // + static String uuid() { + String timestamp = BytedeskUtils.formatedTimestampNow(); + final int special = 8 + Random().nextInt(4); + return timestamp + + '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}' + '${_bitsDigits(16, 4)}' + '4${_bitsDigits(12, 3)}' + '${_printDigits(special, 1)}${_bitsDigits(12, 3)}' + '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}'; + } /// Generate a version 4 (random) uuid. This is a uuid scheme that only uses /// random numbers as the source of the generated uuid. static String generateV4() { // Generate xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx / 8-4-4-4-12. final int special = 8 + Random().nextInt(4); - return '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}-' '${_bitsDigits(16, 4)}-' '4${_bitsDigits(12, 3)}-' diff --git a/bytedesk_kefu/pubspec.yaml b/bytedesk_kefu/pubspec.yaml index b22fe5c..31df6c1 100644 --- a/bytedesk_kefu/pubspec.yaml +++ b/bytedesk_kefu/pubspec.yaml @@ -1,6 +1,6 @@ name: bytedesk_kefu description: the best app chat sdk in china, you can chat with the agent freely at anytime. the agent can chat with the visitor by web/pc/mac/ios/android client. -version: 1.2.4 +version: 1.2.5 homepage: https://www.weikefu.net environment: @@ -18,8 +18,8 @@ dependencies: # https://pub.dev/packages/equatable equatable: ^2.0.3 # https://pub.dev/packages/flutter_bloc - bloc: ^7.2.1 - flutter_bloc: ^7.3.3 + bloc: ^8.0.3 + flutter_bloc: ^8.0.1 # https://pub.dev/packages/http http: ^0.13.4 http_parser: ^4.0.0 @@ -93,7 +93,7 @@ dependencies: # html: ^0.15.0 # mqtt_client依赖 typed_data: ^1.3.0 - crypto: ^3.0.1 + crypto: ^3.0.2 # Plugins for parsing css csslib: ^0.17.1 css_colors: ^1.1.1