diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..385f27a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "interactive" +} diff --git a/android/build.gradle b/android/build.gradle index 102519a..50d581e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -48,5 +48,5 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'com.github.verloop:android-sdk:1.1.14' + implementation 'com.github.verloop:android-sdk:1.1.16-rc.3' } diff --git a/android/src/main/kotlin/io/verloop/verloop_flutter_sdk/VerloopFlutterSdkPlugin.kt b/android/src/main/kotlin/io/verloop/verloop_flutter_sdk/VerloopFlutterSdkPlugin.kt index b4ddd9b..252a520 100644 --- a/android/src/main/kotlin/io/verloop/verloop_flutter_sdk/VerloopFlutterSdkPlugin.kt +++ b/android/src/main/kotlin/io/verloop/verloop_flutter_sdk/VerloopFlutterSdkPlugin.kt @@ -1,8 +1,7 @@ package io.verloop.verloop_flutter_sdk import android.app.Activity -import android.util.Log -import android.view.inputmethod.InputBinding +import android.content.Intent import androidx.annotation.NonNull import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.activity.ActivityAware @@ -11,11 +10,12 @@ import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler -import io.flutter.plugin.common.MethodChannel.Result import io.verloop.sdk.LiveChatButtonClickListener import io.verloop.sdk.LiveChatUrlClickListener import io.verloop.sdk.Verloop import io.verloop.sdk.VerloopConfig +import io.verloop.sdk.ui.Constants + /** VerloopFlutterSdkPlugin */ class VerloopFlutterSdkPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { @@ -234,6 +234,28 @@ class VerloopFlutterSdkPlugin : FlutterPlugin, MethodCallHandler, ActivityAware result.success(1) return } + "showDownloadButton" -> { + val args = call.arguments as? Map + if (args != null) { + val isAllowFileDownload = args["isAllowFileDownload"] as? Boolean + if (isAllowFileDownload != null) { + if (configBuilder != null) { + configBuilder = + configBuilder!!.allowFileDownload(isAllowFileDownload) + } + } + } + result.success(1) + return + } + "openMenuWidget" -> { + if (configBuilder != null) { + configBuilder = + configBuilder!!.openMenuWidgetOnStart(true) + } + result.success(1) + return + } "buildVerloop" -> { if (configBuilder == null) { configBuilder = VerloopConfig.Builder() @@ -276,6 +298,13 @@ class VerloopFlutterSdkPlugin : FlutterPlugin, MethodCallHandler, ActivityAware return } verloop!!.showChat() + + result.success(1) + return + } + "dismissChat" -> { + val intent = Intent(Constants.ACTION_CLOSE_VERLOOP_WIDGET) + activity.sendBroadcast(intent) result.success(1) return } diff --git a/example/android/gradlew b/example/android/gradlew old mode 100644 new mode 100755 diff --git a/example/android/local.properties b/example/android/local.properties index 100b284..b37df45 100644 --- a/example/android/local.properties +++ b/example/android/local.properties @@ -1,3 +1,3 @@ -sdk.dir=C:/Users/ADYA H S/AppData/Local/Android/Sdk -flutter.sdk=C:\\flutter +sdk.dir=/Users/pankajpatel/Library/Android/sdk +flutter.sdk=/Users/pankajpatel/Development/flutter flutter.buildMode=debug \ No newline at end of file diff --git a/example/firebase.json b/example/firebase.json new file mode 100644 index 0000000..2eda079 --- /dev/null +++ b/example/firebase.json @@ -0,0 +1 @@ +{"flutter":{"platforms":{"android":{"default":{"projectId":"my-verloop-test","appId":"1:1049556476892:android:3ef483bef07eaa623fe519","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"my-verloop-test","appId":"1:1049556476892:ios:35c079ea09c2762c3fe519","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"my-verloop-test","configurations":{"android":"1:1049556476892:android:3ef483bef07eaa623fe519","ios":"1:1049556476892:ios:35c079ea09c2762c3fe519","web":"1:1049556476892:web:b256cbf7e31b45da3fe519"}}}}}} \ No newline at end of file diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 8d4492f..7c56964 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 12.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index 1e8c3c9..728c145 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '9.0' + platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index acefd34..7e63457 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,71 +1,74 @@ PODS: - - Firebase/CoreOnly (8.15.0): - - FirebaseCore (= 8.15.0) - - Firebase/Messaging (8.15.0): + - Firebase/CoreOnly (11.2.0): + - FirebaseCore (= 11.2.0) + - Firebase/Messaging (11.2.0): - Firebase/CoreOnly - - FirebaseMessaging (~> 8.15.0) - - firebase_core (1.18.0): - - Firebase/CoreOnly (= 8.15.0) + - FirebaseMessaging (~> 11.2.0) + - firebase_core (3.6.0): + - Firebase/CoreOnly (= 11.2.0) - Flutter - - firebase_messaging (11.4.2): - - Firebase/Messaging (= 8.15.0) + - firebase_messaging (15.1.3): + - Firebase/Messaging (= 11.2.0) - firebase_core - Flutter - - FirebaseCore (8.15.0): - - FirebaseCoreDiagnostics (~> 8.0) - - GoogleUtilities/Environment (~> 7.7) - - GoogleUtilities/Logger (~> 7.7) - - FirebaseCoreDiagnostics (8.15.0): - - GoogleDataTransport (~> 9.1) - - GoogleUtilities/Environment (~> 7.7) - - GoogleUtilities/Logger (~> 7.7) - - nanopb (~> 2.30908.0) - - FirebaseInstallations (8.15.0): - - FirebaseCore (~> 8.0) - - GoogleUtilities/Environment (~> 7.7) - - GoogleUtilities/UserDefaults (~> 7.7) - - PromisesObjC (< 3.0, >= 1.2) - - FirebaseMessaging (8.15.0): - - FirebaseCore (~> 8.0) - - FirebaseInstallations (~> 8.0) - - GoogleDataTransport (~> 9.1) - - GoogleUtilities/AppDelegateSwizzler (~> 7.7) - - GoogleUtilities/Environment (~> 7.7) - - GoogleUtilities/Reachability (~> 7.7) - - GoogleUtilities/UserDefaults (~> 7.7) - - nanopb (~> 2.30908.0) + - FirebaseCore (11.2.0): + - FirebaseCoreInternal (~> 11.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/Logger (~> 8.0) + - FirebaseCoreInternal (11.4.0): + - "GoogleUtilities/NSData+zlib (~> 8.0)" + - FirebaseInstallations (11.4.0): + - FirebaseCore (~> 11.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - PromisesObjC (~> 2.4) + - FirebaseMessaging (11.2.0): + - FirebaseCore (~> 11.0) + - FirebaseInstallations (~> 11.0) + - GoogleDataTransport (~> 10.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/Reachability (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - nanopb (~> 3.30910.0) - Flutter (1.0.0) - - GoogleDataTransport (9.2.0): - - GoogleUtilities/Environment (~> 7.7) - - nanopb (< 2.30910.0, >= 2.30908.0) - - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/AppDelegateSwizzler (7.7.0): + - GoogleDataTransport (10.1.0): + - nanopb (~> 3.30910.0) + - PromisesObjC (~> 2.4) + - GoogleUtilities/AppDelegateSwizzler (8.0.2): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - - GoogleUtilities/Environment (7.7.0): - - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/Logger (7.7.0): + - GoogleUtilities/Privacy + - GoogleUtilities/Environment (8.0.2): + - GoogleUtilities/Privacy + - GoogleUtilities/Logger (8.0.2): - GoogleUtilities/Environment - - GoogleUtilities/Network (7.7.0): + - GoogleUtilities/Privacy + - GoogleUtilities/Network (8.0.2): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Privacy - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (7.7.0)" - - GoogleUtilities/Reachability (7.7.0): + - "GoogleUtilities/NSData+zlib (8.0.2)": + - GoogleUtilities/Privacy + - GoogleUtilities/Privacy (8.0.2) + - GoogleUtilities/Reachability (8.0.2): - GoogleUtilities/Logger - - GoogleUtilities/UserDefaults (7.7.0): + - GoogleUtilities/Privacy + - GoogleUtilities/UserDefaults (8.0.2): - GoogleUtilities/Logger - - nanopb (2.30908.0): - - nanopb/decode (= 2.30908.0) - - nanopb/encode (= 2.30908.0) - - nanopb/decode (2.30908.0) - - nanopb/encode (2.30908.0) - - PromisesObjC (2.1.1) + - GoogleUtilities/Privacy + - nanopb (3.30910.0): + - nanopb/decode (= 3.30910.0) + - nanopb/encode (= 3.30910.0) + - nanopb/decode (3.30910.0) + - nanopb/encode (3.30910.0) + - PromisesObjC (2.4.0) - verloop_flutter_sdk (0.0.4): - Flutter - - VerloopSDKiOS (= 0.2.5) - - VerloopSDKiOS (0.2.5) + - VerloopSDKiOS (= 0.2.13) + - VerloopSDKiOS (0.2.13) DEPENDENCIES: - firebase_core (from `.symlinks/plugins/firebase_core/ios`) @@ -77,7 +80,7 @@ SPEC REPOS: trunk: - Firebase - FirebaseCore - - FirebaseCoreDiagnostics + - FirebaseCoreInternal - FirebaseInstallations - FirebaseMessaging - GoogleDataTransport @@ -97,21 +100,21 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/verloop_flutter_sdk/ios" SPEC CHECKSUMS: - Firebase: 5f8193dff4b5b7c5d5ef72ae54bb76c08e2b841d - firebase_core: b14c1cfa29b9eb316345f74d1489328283825d6d - firebase_messaging: 5374d57b2ca7a5efe1a150500b9a2451ca9ff5af - FirebaseCore: 5743c5785c074a794d35f2fff7ecc254a91e08b1 - FirebaseCoreDiagnostics: 92e07a649aeb66352b319d43bdd2ee3942af84cb - FirebaseInstallations: 40bd9054049b2eae9a2c38ef1c3dd213df3605cd - FirebaseMessaging: 5e5118a2383b3531e730d974680954c679ca0a13 - Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a - GoogleDataTransport: 1c8145da7117bd68bbbed00cf304edb6a24de00f - GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1 - nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96 - PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb - verloop_flutter_sdk: e0461f415b265e2481a8bd251c8210a0711840fe - VerloopSDKiOS: bfd1532603c6c0cfbb8ceb47b05d155139152ff1 + Firebase: 98e6bf5278170668a7983e12971a66b2cd57fc8c + firebase_core: 2bedc3136ec7c7b8561c6123ed0239387b53f2af + firebase_messaging: 15d114e1a41fc31e4fbabcd48d765a19eec94a38 + FirebaseCore: a282032ae9295c795714ded2ec9c522fc237f8da + FirebaseCoreInternal: 5c2b016f06a96fbf20d9b443459f80427a827d7b + FirebaseInstallations: 6ef4a1c7eb2a61ee1f74727d7f6ce2e72acf1414 + FirebaseMessaging: c9ec7b90c399c7a6100297e9d16f8a27fc7f7152 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 + GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d + nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 + PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 + verloop_flutter_sdk: ff3eb6eac5a66f821da75fe6151d25e0006d2f19 + VerloopSDKiOS: 264442f5a14053eb354335debd536278d27762ac -PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c +PODFILE CHECKSUM: 30517025a2fecca2d72dac25f08abb5b9a8f1a56 -COCOAPODS: 1.11.3 +COCOAPODS: 1.15.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index f367720..f872d17 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -14,6 +14,7 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + CFB86FA7F1E23C7400773CF2 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3C12750059E0DAF337671250 /* GoogleService-Info.plist */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -34,6 +35,7 @@ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 26E955E17FBB789930D87DCE /* 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 = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3C12750059E0DAF337671250 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; 5921071C758174D1AA451058 /* 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 = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -99,6 +101,7 @@ 97C146EF1CF9000F007C117D /* Products */, 01CB55533E4F801C6CE483D4 /* Pods */, 06A055ECF0156BD2FDCF837A /* Frameworks */, + 3C12750059E0DAF337671250 /* GoogleService-Info.plist */, ); sourceTree = ""; }; @@ -141,6 +144,7 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 9FCC63B39E4B04B6BD3E9AC5 /* [CP] Embed Pods Frameworks */, + 86DB66AE6B389BD5D0912729 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -157,7 +161,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -193,6 +197,7 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + CFB86FA7F1E23C7400773CF2 /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -223,10 +228,12 @@ }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -235,8 +242,26 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 86DB66AE6B389BD5D0912729 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -491,7 +516,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = 4; - DEVELOPMENT_TEAM = 5423774D8G; + DEVELOPMENT_TEAM = R5ANF7UMFA; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -516,8 +541,10 @@ ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 4; - DEVELOPMENT_TEAM = 5423774D8G; + DEVELOPMENT_TEAM = ""; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -527,6 +554,7 @@ MARKETING_VERSION = 1.0.3; PRODUCT_BUNDLE_IDENTIFIER = io.verloop.verloopFlutterSdkExample; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c87d15a..5e31d3d 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + + + + API_KEY + AIzaSyCV1IQbJP1K6VC2_w3NKNgB6FHGOo5sa28 + GCM_SENDER_ID + 1049556476892 + PLIST_VERSION + 1 + BUNDLE_ID + io.verloop.verloopFlutterSdkExample + PROJECT_ID + my-verloop-test + STORAGE_BUCKET + my-verloop-test.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:1049556476892:ios:35c079ea09c2762c3fe519 + + \ No newline at end of file diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index be9f83d..fff155d 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -45,5 +45,7 @@ UIViewControllerBasedStatusBarAppearance + UIApplicationSupportsIndirectInputEvents + diff --git a/example/lib/main.dart b/example/lib/main.dart index 715cf5c..35ed30c 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,224 +1,28 @@ -import 'dart:developer'; -import 'dart:ffi'; - import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; +//import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; -import 'package:verloop_flutter_sdk/verloop_flutter_sdk.dart'; +import 'package:verloop_flutter_sdk_example/screens/login-screen/login_screen.dart'; import 'firebase_options.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); + await Firebase.initializeApp( - options: DefaultFirebaseOptions.currentPlatform, + options: DefaultFirebaseOptions.currentPlatform, ); runApp(const MyApp()); } -class MyApp extends StatefulWidget { - const MyApp({Key? key}) : super(key: key); - - @override - State createState() => _MyAppState(); -} - -class _MyAppState extends State { - final Map roomMap = {"key1": "value1"}; - final Map userMap = {"key2": "value2"}; - String clientId = "hello"; - String? recipeId; - String? userId; - String? userName; - String? userEmail; - String? userPhone; - final clientIdController = TextEditingController(); - final recipeIdController = TextEditingController(); - final userIdController = TextEditingController(); - final userNameController = TextEditingController(); - final userEmailController = TextEditingController(); - final userPhoneController = TextEditingController(); - bool changed = true; +class MyApp extends StatelessWidget { + const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( - home: Scaffold( - appBar: AppBar( - backgroundColor: Colors.black, - title: const Text('Plugin example app'), - ), - body: SingleChildScrollView( - child: Stack( - children: [ - Flex( - direction: Axis.vertical, - children: [ - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 8, vertical: 8), - child: TextField( - controller: clientIdController, - onChanged: (String text) { - setState(() { - clientId = clientIdController.text; - changed = true; - }); - }, - decoration: const InputDecoration( - border: OutlineInputBorder(), - hintText: - 'Enter the client id eg: hello or hello.stage', - ), - ), - ), - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 8, vertical: 8), - child: TextField( - controller: recipeIdController, - onChanged: (String text) { - setState(() { - recipeId = recipeIdController.text; - changed = true; - }); - }, - decoration: const InputDecoration( - border: OutlineInputBorder(), - hintText: 'Enter the recipe ID', - ), - ), - ), - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 8, vertical: 8), - child: TextField( - controller: userIdController, - onChanged: (String text) { - setState(() { - userId = userIdController.text; - changed = true; - }); - }, - decoration: const InputDecoration( - border: OutlineInputBorder(), - hintText: 'Enter the user Id', - ), - ), - ), - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 8, vertical: 8), - child: TextField( - controller: userNameController, - onChanged: (String text) { - setState(() { - userName = userNameController.text; - changed = true; - }); - }, - decoration: const InputDecoration( - border: OutlineInputBorder(), - hintText: 'Enter the user name', - ), - ), - ), - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 8, vertical: 8), - child: TextField( - controller: userPhoneController, - onChanged: (String text) { - setState(() { - userPhone = userPhoneController.text; - changed = true; - }); - }, - decoration: const InputDecoration( - border: OutlineInputBorder(), - hintText: 'Enter the user phone', - ), - ), - ), - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 8, vertical: 8), - child: TextField( - controller: userEmailController, - onChanged: (String text) { - setState(() { - userEmail = userEmailController.text; - changed = true; - }); - }, - decoration: const InputDecoration( - border: OutlineInputBorder(), - hintText: 'Enter the user email', - ), - ), - ), - Text('Running for client $clientId'), - changed == false - ? const SizedBox() - : TextButton( - onPressed: () { - setState(() { - changed = false; - }); - }, - child: const Text("Submit")), - ], - ), - ], - ), - ), - floatingActionButton: changed == true - ? const SizedBox() - : FutureBuilder( - // Initialize FlutterFire - future: FirebaseMessaging.instance.getToken(), - builder: (context, snapshot) { - // Check for errors - if (snapshot.hasError) { - return const Text("Something went wrong"); - } - if (snapshot.hasData && snapshot.data != "") { - String token = snapshot.data ?? ""; - - return VerloopWidget( - clientId: clientId, - fcmToken: token, - recipeId: recipeId, - roomVariables: roomMap, - userVariables: userMap, - userId: userId, - userName: userName, - userEmail: userEmail, - userPhone: userPhone, - onButtonClicked: - (String? title, String? payload, String? type) { - log("button click title $title $payload"); - }, - onUrlClicked: (String? url) { - log("url clicked $url"); - }, - overrideUrlOnClick: true, - child: const FloatingActionButton( - onPressed: null, - child: Icon(Icons.chat), - ), - ); - } - return const Text("Loading..."); - }, - ), - ), + theme: ThemeData(useMaterial3: true), + + debugShowCheckedModeBanner: true, + home: const LoginScreen(), ); } - - @override - void dispose() { - clientIdController.dispose(); - recipeIdController.dispose(); - super.dispose(); - } } diff --git a/example/lib/screens/home_screen.dart b/example/lib/screens/home_screen.dart new file mode 100644 index 0000000..bbd1eff --- /dev/null +++ b/example/lib/screens/home_screen.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; + +class HomeScreen extends StatefulWidget { + final String? title; + final String? payload; + final String? type; + + const HomeScreen({ + super.key, + this.title, + this.type, + this.payload, + }); + + @override + State createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State { + @override + Widget build(BuildContext context) { + final size = MediaQuery.sizeOf(context); + return Scaffold( + appBar: AppBar( + automaticallyImplyLeading: false, + title: const Text("Home-screen"), + ), + body: SizedBox( + width: size.width, + height: size.height, + child: Center( + child: Column( + children: [ + Text(widget.title ?? ""), + Text(widget.payload ?? ""), + Text(widget.type ?? ""), + ], + ), + ), + ), + ); + } +} diff --git a/example/lib/screens/login-screen/login_screen.dart b/example/lib/screens/login-screen/login_screen.dart new file mode 100644 index 0000000..d559349 --- /dev/null +++ b/example/lib/screens/login-screen/login_screen.dart @@ -0,0 +1,243 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:verloop_flutter_sdk/verloop_flutter_sdk.dart'; +import 'package:verloop_flutter_sdk_example/screens/home_screen.dart'; +// ignore: depend_on_referenced_packages + import 'package:firebase_messaging/firebase_messaging.dart'; + +class LoginScreen extends StatefulWidget { + const LoginScreen({super.key}); + + @override + State createState() => _LoginScreenState(); +} + +class _LoginScreenState extends State { + final Map roomMap = {"key1": "value1"}; + final Map userMap = {"key2": "value2"}; + String clientId = "hello"; + String? recipeId; + String? userId; + String? userName; + String? userEmail; + String? userPhone; + final clientIdController = TextEditingController(); + final recipeIdController = TextEditingController(); + final userIdController = TextEditingController(); + final userNameController = TextEditingController(); + final userEmailController = TextEditingController(); + final userPhoneController = TextEditingController(); + bool changed = true; + final VerloopSdk verloop = VerloopSdk(); + + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.black, + title: const Text('Plugin example app'), + ), + body: SingleChildScrollView( + child: Stack( + children: [ + Flex( + direction: Axis.vertical, + children: [ + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + child: TextField( + controller: clientIdController, + onChanged: (String text) { + setState(() { + clientId = clientIdController.text; + changed = true; + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: + 'Enter the client id eg: hello or hello.stage', + ), + ), + ), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + child: TextField( + controller: recipeIdController, + onChanged: (String text) { + setState(() { + recipeId = recipeIdController.text; + changed = true; + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: 'Enter the recipe ID', + ), + ), + ), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + child: TextField( + controller: userIdController, + onChanged: (String text) { + setState(() { + userId = userIdController.text; + changed = true; + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: 'Enter the user Id', + ), + ), + ), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + child: TextField( + controller: userNameController, + onChanged: (String text) { + setState(() { + userName = userNameController.text; + changed = true; + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: 'Enter the user name', + ), + ), + ), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + child: TextField( + controller: userPhoneController, + onChanged: (String text) { + setState(() { + userPhone = userPhoneController.text; + changed = true; + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: 'Enter the user phone', + ), + ), + ), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + child: TextField( + controller: userEmailController, + onChanged: (String text) { + setState(() { + userEmail = userEmailController.text; + changed = true; + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: 'Enter the user email', + ), + ), + ), + Text('Running for client $clientId'), + changed == false + ? const SizedBox() + : TextButton( + onPressed: () { + setState(() { + changed = false; + }); + }, + child: const Text("Submit")), + ], + ), + ], + ), + ), + floatingActionButton: changed == true + ? const SizedBox() + : FutureBuilder( + // Initialize FlutterFire + future: FirebaseMessaging.instance.getToken(), + builder: (context, snapshot) { + // Check for errors + if (snapshot.hasError) { + return const Text("Something went wrong"); + } + if (snapshot.hasData && snapshot.data != "") { + String token = snapshot.data ?? ""; + + return VerloopWidget( + clientId: clientId, + fcmToken: token, + recipeId: recipeId, + roomVariables: roomMap, + userVariables: userMap, + userId: userId, + userName: userName, + userEmail: userEmail, + userPhone: userPhone, + showDownloadButton: true, + openMenuWidget:true, + onButtonClicked:_handleButtonClick, + onUrlClicked: _handleUrlClick, + overrideUrlOnClick: true, + child: const FloatingActionButton( + onPressed: null, + child: Icon(Icons.chat), + ), + ); + } + return const Text("Loading..."); + }, + ), + ); + } + + void _handleButtonClick(String? title, String? payload, String? type) async { + log("button click title $title $payload"); + if (payload != null) { + verloop.dismissChat(); + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => HomeScreen( + title: title, + payload: payload, + type: type, + )), + ); + } + } + + void _handleUrlClick(String? url) { + log("url clicked $url"); + if (url != null) { + //verloop.dismissChat(); + // Pop Verloop and remove all routes until the initial route + Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute(builder: (context) => HomeScreen(title: url)), + (Route route) => route.isFirst); + } + } + + @override + void dispose() { + clientIdController.dispose(); + recipeIdController.dispose(); + super.dispose(); + } +} diff --git a/example/pubspec.lock b/example/pubspec.lock index fcb9523..5d2fbc3 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -1,104 +1,118 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "5534e701a2c505fed1f0799e652dd6ae23bd4d2c4cf797220e5ced5764a7c1c2" + url: "https://pub.dev" + source: hosted + version: "1.3.44" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.8.2" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" + version: "1.3.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.18.0" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.8" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.3.1" firebase_core: dependency: "direct main" description: name: firebase_core - url: "https://pub.dartlang.org" + sha256: "51dfe2fbf3a984787a2e7b8592f2f05c986bfedd6fdacea3f9e0a7beb334de96" + url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "3.6.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - url: "https://pub.dartlang.org" + sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 + url: "https://pub.dev" source: hosted - version: "4.4.1" + version: "5.3.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - url: "https://pub.dartlang.org" + sha256: f967a7138f5d2ffb1ce15950e2a382924239eaa521150a8f144af34e68b3b3e5 + url: "https://pub.dev" source: hosted - version: "1.6.5" + version: "2.18.1" firebase_messaging: dependency: "direct main" description: name: firebase_messaging - url: "https://pub.dartlang.org" + sha256: eb6e28a3a35deda61fe8634967c84215efc19133ba58d8e0fc6c9a2af2cba05e + url: "https://pub.dev" source: hosted - version: "11.4.2" + version: "15.1.3" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface - url: "https://pub.dartlang.org" + sha256: b316c4ee10d93d32c033644207afc282d9b2b4372f3cf9c6022f3558b3873d2d + url: "https://pub.dev" source: hosted - version: "3.5.2" + version: "4.5.46" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - url: "https://pub.dartlang.org" + sha256: d7f0147a1a9fe4313168e20154a01fd5cf332898de1527d3930ff77b8c7f5387 + url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "3.9.2" flutter: dependency: "direct main" description: flutter @@ -108,9 +122,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" + url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.2" flutter_test: dependency: "direct dev" description: flutter @@ -121,55 +136,78 @@ packages: description: flutter source: sdk version: "0.0.0" - js: + leak_tracker: dependency: transitive description: - name: js - url: "https://pub.dartlang.org" + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 + url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "3.0.0" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" source: hosted - version: "0.12.11" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" source: hosted - version: "0.1.4" + version: "0.11.1" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + url: "https://pub.dev" source: hosted - version: "1.7.0" + version: "1.15.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" source: hosted - version: "1.8.1" + version: "1.9.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.8" sky_engine: dependency: transitive description: flutter @@ -179,58 +217,81 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + url: "https://pub.dev" source: hosted - version: "0.4.9" + version: "0.7.2" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" verloop_flutter_sdk: dependency: "direct main" description: path: ".." relative: true source: path - version: "0.0.4" + version: "0.0.9" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + url: "https://pub.dev" + source: hosted + version: "14.2.5" + web: + dependency: transitive + description: + name: web + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + url: "https://pub.dev" + source: hosted + version: "1.1.0" sdks: - dart: ">=2.17.3 <3.0.0" - flutter: ">=2.5.0" + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.22.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index e02f05e..e67e1ca 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -29,8 +29,10 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 - firebase_messaging: ^14.8.0 - firebase_core: ^2.28.0 + firebase_core: ^3.6.0 + firebase_messaging: ^15.1.3 + #firebase_messaging: ^14.8.0 + #firebase_core: ^2.28.0 dev_dependencies: flutter_test: diff --git a/ios/Classes/SwiftVerloopFlutterSdkPlugin.swift b/ios/Classes/SwiftVerloopFlutterSdkPlugin.swift index 3ff1863..46b7572 100644 --- a/ios/Classes/SwiftVerloopFlutterSdkPlugin.swift +++ b/ios/Classes/SwiftVerloopFlutterSdkPlugin.swift @@ -5,6 +5,8 @@ import VerloopSDKiOS public class SwiftVerloopFlutterSdkPlugin: NSObject, FlutterPlugin, VLEventDelegate { private var previousWindow: UIWindow? = nil private var window = UIWindow() + + private var viewController: UIViewController? private static var methodChannel = "verloop.flutter.dev/method-call" private static var buttonClickChannel = "verloop.flutter.dev/events/button-click" @@ -26,6 +28,7 @@ public class SwiftVerloopFlutterSdkPlugin: NSObject, FlutterPlugin, VLEventDeleg let channel = FlutterMethodChannel(name: methodChannel, binaryMessenger: registrar.messenger()) let buttonChannel = FlutterEventChannel(name: buttonClickChannel, binaryMessenger: registrar.messenger()) let urlChannel = FlutterEventChannel(name: urlClickChannel, binaryMessenger: registrar.messenger()) + let instance = SwiftVerloopFlutterSdkPlugin() registrar.addMethodCallDelegate(instance, channel: channel) @@ -39,7 +42,7 @@ public class SwiftVerloopFlutterSdkPlugin: NSObject, FlutterPlugin, VLEventDeleg switch call.method { case "setConfig": if let args = call.arguments as? Dictionary { - var clientId = args["CLIENT_ID"] as? String + let clientId = args["CLIENT_ID"] as? String if clientId == nil || clientId == "" { result(FlutterError.init(code: SwiftVerloopFlutterSdkPlugin.ERROR_102, message: "CLIENT_ID missing", @@ -48,49 +51,49 @@ public class SwiftVerloopFlutterSdkPlugin: NSObject, FlutterPlugin, VLEventDeleg } config = VLConfig(clientId: clientId!) - var userId = args["USER_ID"] as? String + let userId = args["USER_ID"] as? String if userId != nil && userId != "" { config?.setUserId(userId: userId!) } - var fcmToken = args["FCM_TOKEN"] as? String + let fcmToken = args["FCM_TOKEN"] as? String if fcmToken != nil && fcmToken != "" { config?.setNotificationToken(notificationToken: fcmToken!) // If you wish to get notifications, else, skip this } - var recipeId = args["RECIPE_ID"] as? String + let recipeId = args["RECIPE_ID"] as? String if recipeId != nil && recipeId != "" { config?.setRecipeId(recipeId: recipeId!) // In case you want to use default recipe, skip this } - var userName = args["USER_NAME"] as? String + let userName = args["USER_NAME"] as? String if userName != nil && userName != "" { config?.setUserName(userName: userName!) // If guest name variable is a part of the recipe, or the value is not required, skip this } - var userEmail = args["USER_EMAIL"] as? String + let userEmail = args["USER_EMAIL"] as? String if userEmail != nil && userEmail != "" { config?.setUserEmail(userEmail: userEmail!) // If email variable is a part of the recipe, or the value is not required, skip this } - var userPhone = args["USER_PHONE"] as? String + let userPhone = args["USER_PHONE"] as? String if userPhone != nil && userPhone != "" { config?.setUserPhone(userPhone: userPhone!) // If phone variable is a part of the recipe, or the value is not required, skip this } - var isStaging = args["IS_STAGING"] as? Bool + let isStaging = args["IS_STAGING"] as? Bool if isStaging != nil { config?.setStaging(isStaging: isStaging!) // Keep this as true if you want to access .stage.verloop.io account. If the account doesn't exist, keep it as false or skip it } - var customFields = args["ROOM_CUSTOM_FIELDS"] as? Dictionary // These are predefined variables added on room level + let customFields = args["ROOM_CUSTOM_FIELDS"] as? Dictionary // These are predefined variables added on room level if customFields != nil { for (key, value) in customFields! { config?.putCustomField(key: key, value: value, scope: VLConfig.SCOPE.ROOM) } } - var userCustomFields = args["USER_CUSTOM_FIELDS"] as? Dictionary // These are predefined variables added on user level + let userCustomFields = args["USER_CUSTOM_FIELDS"] as? Dictionary // These are predefined variables added on user level if userCustomFields != nil { for (key, value) in userCustomFields! { config?.putCustomField(key: key, value: value, scope: VLConfig.SCOPE.USER) @@ -111,7 +114,7 @@ public class SwiftVerloopFlutterSdkPlugin: NSObject, FlutterPlugin, VLEventDeleg result(1) case "setUrlClickListener": if let args = call.arguments as? Dictionary { - var overrideUrl = args["OVERRIDE_URL"] as? Bool + let overrideUrl = args["OVERRIDE_URL"] as? Bool if overrideUrl != nil { config?.setUrlRedirectionFlag(canRedirect: !overrideUrl!) // if you wish to open the url in a browser, then keep it as false } @@ -121,6 +124,17 @@ public class SwiftVerloopFlutterSdkPlugin: NSObject, FlutterPlugin, VLEventDeleg return; }) result(1) + case "showDownloadButton": + if let args = call.arguments as? Dictionary { + let isAllowFileDownload = args["isAllowFileDownload"] as? Bool + if isAllowFileDownload != nil { + config?.showDownloadButton(isAllowFileDownload ?? false) + } + } + result(1) + case "openMenuWidget": + config?.openMenuWidget() + result(1) case "buildVerloop": if config == nil { result(FlutterError.init(code: SwiftVerloopFlutterSdkPlugin.ERROR_101, @@ -137,14 +151,16 @@ public class SwiftVerloopFlutterSdkPlugin: NSObject, FlutterPlugin, VLEventDeleg details: "call buildVerloop before calling showChat")) return } - previousWindow = UIApplication.shared.keyWindow - window.isOpaque = true -// window.backgroundColor = UIColor.white -// window.frame = UIScreen.main.bounds - - window.windowLevel = UIWindow.Level.normal + 1 - window.rootViewController = verloop!.getNavController() - window.makeKeyAndVisible() +// previousWindow = UIApplication.shared.keyWindow +// window.isOpaque = true +// window.windowLevel = UIWindow.Level.normal + 1 + //window.rootViewController = verloop!.getNavController() + //window.makeKeyAndVisible() + viewController = verloop!.getNavController() + if let rootVC = UIApplication.shared.delegate?.window??.rootViewController { + rootVC.present(viewController!, animated: true, completion: nil) + } + result(1) case "dispose": verloop = nil clientId = nil @@ -152,6 +168,12 @@ public class SwiftVerloopFlutterSdkPlugin: NSObject, FlutterPlugin, VLEventDeleg config?.setButtonOnClickListener(onButtonClicked: nil) config = nil return + + case "dismissChat": + self.viewController?.dismiss(animated: true, completion: { + self.viewController = nil // Clear the reference after dismissing + }) + result(1) default: result(FlutterMethodNotImplemented) } diff --git a/ios/verloop_flutter_sdk.podspec b/ios/verloop_flutter_sdk.podspec index 492be0d..1fef8e7 100644 --- a/ios/verloop_flutter_sdk.podspec +++ b/ios/verloop_flutter_sdk.podspec @@ -15,8 +15,8 @@ This is a wrapper over native SDK for flutter app s.source = { :path => '.' } s.source_files = 'Classes/**/*' s.dependency 'Flutter' - s.dependency "VerloopSDKiOS", "0.2.7" - s.platform = :ios, '11.0' + s.dependency "VerloopSDKiOS", "0.2.13" + s.platform = :ios, '12.0' # Flutter.framework does not contain a i386 slice. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } diff --git a/lib/verloop_flutter_sdk.dart b/lib/verloop_flutter_sdk.dart index 3d5d0bc..5489de8 100644 --- a/lib/verloop_flutter_sdk.dart +++ b/lib/verloop_flutter_sdk.dart @@ -16,6 +16,7 @@ class VerloopWidget extends StatefulWidget { final String? userEmail; final String? userPhone; final bool overrideUrlOnClick; + final bool showDownloadButton; final Widget? child; final Function(String? title, String? payload, String? type)? onButtonClicked; @@ -23,6 +24,7 @@ class VerloopWidget extends StatefulWidget { final Map? userVariables; final Map? roomVariables; + final bool? openMenuWidget; const VerloopWidget( {Key? key, @@ -38,6 +40,8 @@ class VerloopWidget extends StatefulWidget { this.roomVariables, this.onButtonClicked, this.onUrlClicked, + this.openMenuWidget, + this.showDownloadButton = false, this.overrideUrlOnClick = false}) : super(key: key); @@ -79,6 +83,7 @@ class _VerloopWidgetState extends State { ); sdk?.setButtonClickListener(); sdk?.setUrlClickListener(overrideUrlOnClick: widget.overrideUrlOnClick); + sdk?.showDownloadButton(isAllowFileDownload: widget.showDownloadButton); sdk?.buildVerloop(); sdk?.onButtonClicked.listen((event) { widget.onButtonClicked?.call(event.title, event.payload, event.type); @@ -86,6 +91,11 @@ class _VerloopWidgetState extends State { sdk?.onUrlClicked.listen((event) { widget.onUrlClicked?.call(event.url); }); + + if (widget.openMenuWidget == true) { + sdk?.openMenuWidget(); + } + setState(() { _ready = true; }); @@ -141,6 +151,15 @@ class VerloopSdk { return await VerloopFlutterSdkPlatform.instance.setButtonClickListener(); } + Future openMenuWidget() async { + return await VerloopFlutterSdkPlatform.instance.openMenuWidget(); + } + + Future showDownloadButton({bool isAllowFileDownload = false}) async { + return await VerloopFlutterSdkPlatform.instance + .showDownloadButton(isAllowFileDownload: isAllowFileDownload); + } + Future setUrlClickListener({bool overrideUrlOnClick = false}) async { return await VerloopFlutterSdkPlatform.instance .setUrlClickListener(overrideUrlOnClick: overrideUrlOnClick); @@ -165,4 +184,9 @@ class VerloopSdk { Future dispose() async { return await VerloopFlutterSdkPlatform.instance.dispose(); } + + Future dismissChat() async { + return await VerloopFlutterSdkPlatform.instance.dismissChat(); + } + } diff --git a/lib/verloop_flutter_sdk_method_channel.dart b/lib/verloop_flutter_sdk_method_channel.dart index 848128b..bd93a67 100644 --- a/lib/verloop_flutter_sdk_method_channel.dart +++ b/lib/verloop_flutter_sdk_method_channel.dart @@ -72,6 +72,26 @@ class MethodChannelVerloopFlutterSdk extends VerloopFlutterSdkPlatform { } } + @override + Future openMenuWidget() async { + try { + await verloopMethods.invokeMethod('openMenuWidget'); + } on PlatformException catch (e) { + log("Failed to load widget: '${e.message}'."); + } + } + + @override + Future showDownloadButton({bool isAllowFileDownload = false}) async { + try { + await verloopMethods.invokeMethod('showDownloadButton', { + 'isAllowFileDownload': isAllowFileDownload, + }); + } on PlatformException catch (e) { + log("Failed to set url click listener: '${e.message}'."); + } + } + @override Future buildVerloop() async { try { @@ -120,4 +140,13 @@ class MethodChannelVerloopFlutterSdk extends VerloopFlutterSdkPlatform { log("Failed to dispose widget: '${e.message}'."); } } + + @override + Future dismissChat() async { + try { + await verloopMethods.invokeMethod('dismissChat'); + } on PlatformException catch (e) { + log("Failed to load widget: '${e.message}'."); + } + } } diff --git a/lib/verloop_flutter_sdk_platform_interface.dart b/lib/verloop_flutter_sdk_platform_interface.dart index 5467044..d1da25f 100644 --- a/lib/verloop_flutter_sdk_platform_interface.dart +++ b/lib/verloop_flutter_sdk_platform_interface.dart @@ -45,8 +45,17 @@ abstract class VerloopFlutterSdkPlatform extends PlatformInterface { 'setButtonClickListener() has not been implemented.'); } + Future openMenuWidget() async { + throw UnimplementedError( + 'openMenuWidget() has not been implemented.'); + } + Future setUrlClickListener({bool overrideUrlOnClick = false}) async { throw UnimplementedError('setUrlClickListener() has not been implemented.'); + } + + Future showDownloadButton({bool isAllowFileDownload = false}) async { + throw UnimplementedError('showDownloadButton() has not been implemented.'); } Future buildVerloop() async { @@ -68,4 +77,9 @@ abstract class VerloopFlutterSdkPlatform extends PlatformInterface { Future dispose() async { throw UnimplementedError('dispose() has not been implemented.'); } + + Future dismissChat() async { + throw UnimplementedError('dismissChat() has not been implemented.'); + } + }