diff --git a/CHANGELOG.md b/CHANGELOG.md index 88acaa9..a448945 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 15.1.0 + +Real-time chat + # 15.0.0 Shake 15 release diff --git a/README.md b/README.md index 18b11b3..28992f7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,24 @@ -# Shake for Flutter +# Shake Flutter SDK -Flutter plugin for [Shake](https://www.shakebugs.com). +[![pub package](https://img.shields.io/pub/v/shake_flutter)](https://pub.dev/packages/shake_flutter) + +Flutter plugin for [bug reporting](https://www.shakebugs.com). + +## Features + +| Feature | Available | +|:---------------:|:---------:| +| Bug reporting | ✅ | +| Crash reporting | ❌ | +| Users | ✅ | + +## Requirements + +| Platform | Version | +|:----------:|:---------:| +| Flutter | 1.12 | +| Android | 7.0 | +| iOS | 12.0 | ## How to use @@ -9,7 +27,7 @@ Flutter plugin for [Shake](https://www.shakebugs.com). Add Shake to your `pubspec.yaml` file. ```yaml dependencies: - shake_flutter: ^15.0.0 + shake_flutter: ^15.1.0 ``` Install package by running command in terminal. @@ -17,7 +35,7 @@ Install package by running command in terminal. flutter packages get ``` -## Start Shake +### Start Shake Add Shake import. ```dart @@ -41,6 +59,6 @@ void main() { Replace `client-id` and `client-secret` with the actual values you have in [your workspace settings](https://app.shakebugs.com/settings/workspace#general). -## Documentation +## Resources -Visit [documentation](https://www.shakebugs.com/docs) for more details. \ No newline at end of file +- [Official docs](https://www.shakebugs.com/docs/) \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index 61f287e..faea8ac 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -40,5 +40,5 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - api "$System.env.ANDROID_DEPENDENCY:15.0.+" + api "$System.env.ANDROID_DEPENDENCY:15.1.+" } diff --git a/android/src/main/kotlin/com/shakebugs/flutter/ShakePlugin.kt b/android/src/main/kotlin/com/shakebugs/flutter/ShakePlugin.kt index 90bd160..789b5dc 100644 --- a/android/src/main/kotlin/com/shakebugs/flutter/ShakePlugin.kt +++ b/android/src/main/kotlin/com/shakebugs/flutter/ShakePlugin.kt @@ -8,8 +8,9 @@ import com.shakebugs.flutter.utils.Constants import com.shakebugs.flutter.utils.Logger import com.shakebugs.shake.Shake import com.shakebugs.shake.ShakeInfo -import com.shakebugs.shake.internal.data.NetworkRequest -import com.shakebugs.shake.internal.data.NotificationEvent +import com.shakebugs.shake.ShakeScreen +import com.shakebugs.shake.internal.domain.models.NetworkRequest +import com.shakebugs.shake.internal.domain.models.NotificationEvent import com.shakebugs.shake.report.FeedbackType import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.activity.ActivityAware @@ -75,6 +76,8 @@ class ShakePlugin : FlutterPlugin, MethodCallHandler, ActivityAware { "getShakingThreshold" -> getShakingThreshold(result) "setInvokeShakeOnScreenshot" -> setInvokeShakeOnScreenshot(call) "isInvokeShakeOnScreenshot" -> isInvokeShakeOnScreenshot(result) + "getDefaultScreen" -> getDefaultScreen(result) + "setDefaultScreen" -> setDefaultScreen(call) "setScreenshotIncluded" -> setScreenshotIncluded(call) "isScreenshotIncluded" -> isScreenshotIncluded(result) "getEmailField" -> getEmailField(result) @@ -93,6 +96,7 @@ class ShakePlugin : FlutterPlugin, MethodCallHandler, ActivityAware { "setConsoleLogsEnabled" -> setConsoleLogsEnabled(call) "log" -> log(call) "setMetadata" -> setMetadata(call) + "clearMetadata" -> clearMetadata() "setShakeReportData" -> setShakeReportData(call) "silentReport" -> silentReport(call) "registerUser" -> registerUser(call) @@ -204,8 +208,22 @@ class ShakePlugin : FlutterPlugin, MethodCallHandler, ActivityAware { result.success(enabled) } - private fun getShakingThreshold(result: Result){ - val threshold: Int? = Shake.getReportConfiguration().getShakingThreshold() + private fun getDefaultScreen(result: Result) { + val defaultScreen: ShakeScreen = Shake.getReportConfiguration().defaultScreen + val defaultScreenStr: String = mapper?.shakeScreenToString(defaultScreen) ?: "newTicket" + result.success(defaultScreenStr) + } + + private fun setDefaultScreen(call: MethodCall) { + val defaultScreenStr: String? = call.argument("shakeScreen") + val defaultScreen: ShakeScreen? = mapper?.mapToShakeScreen(defaultScreenStr) + defaultScreen?.let { + Shake.getReportConfiguration().defaultScreen = defaultScreen + } + } + + private fun getShakingThreshold(result: Result) { + val threshold: Int = Shake.getReportConfiguration().shakingThreshold result.success(threshold) } @@ -228,12 +246,12 @@ class ShakePlugin : FlutterPlugin, MethodCallHandler, ActivityAware { result.success(enabled) } - private fun isScreenshotIncluded(result: Result){ + private fun isScreenshotIncluded(result: Result) { val enabled: Boolean = Shake.getReportConfiguration().isScreenshotIncluded result.success(enabled) } - private fun setScreenshotIncluded(call: MethodCall){ + private fun setScreenshotIncluded(call: MethodCall) { val enabled: Boolean? = call.argument("enabled") enabled?.let { Shake.getReportConfiguration().isScreenshotIncluded = it @@ -287,6 +305,10 @@ class ShakePlugin : FlutterPlugin, MethodCallHandler, ActivityAware { Shake.setMetadata(key, value) } + private fun clearMetadata() { + Shake.clearMetadata() + } + private fun log(call: MethodCall) { val logLevelStr: String? = call.argument("level") val message: String? = call.argument("message") diff --git a/android/src/main/kotlin/com/shakebugs/flutter/ShakeReflection.kt b/android/src/main/kotlin/com/shakebugs/flutter/ShakeReflection.kt index 40037f4..8065f99 100644 --- a/android/src/main/kotlin/com/shakebugs/flutter/ShakeReflection.kt +++ b/android/src/main/kotlin/com/shakebugs/flutter/ShakeReflection.kt @@ -4,16 +4,22 @@ import android.app.Activity import com.shakebugs.flutter.utils.Logger import com.shakebugs.flutter.utils.Reflection import com.shakebugs.shake.ShakeInfo -import com.shakebugs.shake.internal.data.NetworkRequest -import com.shakebugs.shake.internal.data.NotificationEvent +import com.shakebugs.shake.internal.domain.models.NetworkRequest +import com.shakebugs.shake.internal.domain.models.NotificationEvent import java.lang.reflect.Method object ShakeReflection { private const val CLASS_NAME = "com.shakebugs.shake.Shake" - + fun start(activity: Activity?, clientId: String?, clientSecret: String?) { try { - val method: Method? = Reflection.getMethod(Class.forName(CLASS_NAME), "startFromWrapper", Activity::class.java, String::class.java, String::class.java) + val method: Method? = Reflection.getMethod( + Class.forName(CLASS_NAME), + "startFromWrapper", + Activity::class.java, + String::class.java, + String::class.java + ) method?.invoke(null, activity, clientId, clientSecret) } catch (e: Exception) { Logger.e("Failed to start Shake", e) @@ -22,7 +28,11 @@ object ShakeReflection { fun setShakeInfo(shakeInfo: ShakeInfo?) { try { - val method: Method? = Reflection.getMethod(Class.forName(CLASS_NAME), "setShakeInfo", ShakeInfo::class.java) + val method: Method? = Reflection.getMethod( + Class.forName(CLASS_NAME), + "setShakeInfo", + ShakeInfo::class.java + ) method?.invoke(null, shakeInfo) } catch (e: Exception) { Logger.e("Failed to set shake info", e) @@ -31,7 +41,11 @@ object ShakeReflection { fun insertNetworkRequest(networkRequest: NetworkRequest?) { try { - val method: Method? = Reflection.getMethod(Class.forName(CLASS_NAME), "insertNetworkRequest", NetworkRequest::class.java) + val method: Method? = Reflection.getMethod( + Class.forName(CLASS_NAME), + "insertNetworkRequest", + NetworkRequest::class.java + ) method?.invoke(null, networkRequest) } catch (e: Exception) { Logger.e("Failed to insert network request", e) @@ -40,7 +54,11 @@ object ShakeReflection { fun insertNotificationEvent(notificationEvent: NotificationEvent?) { try { - val method: Method? = Reflection.getMethod(Class.forName(CLASS_NAME), "insertNotificationEvent", NotificationEvent::class.java) + val method: Method? = Reflection.getMethod( + Class.forName(CLASS_NAME), + "insertNotificationEvent", + NotificationEvent::class.java + ) method?.invoke(null, notificationEvent) } catch (e: Exception) { Logger.e("Failed to insert notification event", e) diff --git a/android/src/main/kotlin/com/shakebugs/flutter/helpers/Mapper.kt b/android/src/main/kotlin/com/shakebugs/flutter/helpers/Mapper.kt index 5d09694..646a194 100644 --- a/android/src/main/kotlin/com/shakebugs/flutter/helpers/Mapper.kt +++ b/android/src/main/kotlin/com/shakebugs/flutter/helpers/Mapper.kt @@ -7,12 +7,11 @@ import com.shakebugs.flutter.utils.Resources import com.shakebugs.shake.LogLevel import com.shakebugs.shake.ShakeReportConfiguration import com.shakebugs.shake.ShakeScreen -import com.shakebugs.shake.internal.data.NetworkRequest -import com.shakebugs.shake.internal.data.NotificationEvent +import com.shakebugs.shake.internal.domain.models.NetworkRequest +import com.shakebugs.shake.internal.domain.models.NotificationEvent import com.shakebugs.shake.report.FeedbackType import com.shakebugs.shake.report.ShakeFile - class Mapper(private val context: Context) { fun mapToShakeScreen(shakeScreenStr: String?): ShakeScreen { return when (shakeScreenStr) { @@ -22,6 +21,14 @@ class Mapper(private val context: Context) { } } + fun shakeScreenToString(shakeScreen: ShakeScreen): String? { + return when (shakeScreen) { + ShakeScreen.HOME -> "home" + ShakeScreen.NEW -> "newTicket" + else -> null + } + } + fun mapToShakeFiles(data: List>?): List? { return data?.map { val path: String = it["path"] as String @@ -65,6 +72,7 @@ class Mapper(private val context: Context) { config.activityHistoryData = data["activityHistoryData"] as Boolean config.blackBoxData = data["blackBoxData"] as Boolean config.screenshot = data["screenshot"] as Boolean + config.video = data["video"] as Boolean config.showReportSentMessage = data["showReportSentMessage"] as Boolean } return config diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index f2c0e5a..b18c2b0 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -7,7 +7,7 @@ FlutterApplication and put your custom class here. --> 15.0.0-rc) + - Shake-Staging (~> 15.1.0-rc.1447) - Toast (4.0.0) - url_launcher (0.0.1): - Flutter @@ -54,11 +54,11 @@ SPEC CHECKSUMS: fluttertoast: 6122fa75143e992b1d3470f61000f591a798cc58 package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 path_provider: d1e9807085df1f9cc9318206cd649dc0b76be3de - Shake-Staging: d7d5af5607f7b377723fd88915c7e2e410b349b8 - shake_flutter: ca19f9aa0119392650d6d6764245d653a6e38def + Shake-Staging: 1e48bab5826b8192d7c0a3917f3e1e7d44d6b02e + shake_flutter: f21bd5c31b35e9b3963146422751633b596672bb Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 url_launcher: b6e016d912f04be9f5bf6e8e82dc599b7ba59649 -PODFILE CHECKSUM: 350b23a1ddb073e6f234cd77e085ec2d3d146984 +PODFILE CHECKSUM: 18de14b99602a19f41203ed1bd1f3eb50097dbcf COCOAPODS: 1.11.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index cd9ac44..d1b4d59 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -51,7 +51,7 @@ 86325AE41E60DF0F6ED63D7D /* Pods-Runner.profile-production.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile-production.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile-production.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Shake.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Shake.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146EE1CF9000F007C117D /* ShakeExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShakeExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 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 = ""; }; @@ -140,7 +140,7 @@ 97C146EF1CF9000F007C117D /* Products */ = { isa = PBXGroup; children = ( - 97C146EE1CF9000F007C117D /* Shake.app */, + 97C146EE1CF9000F007C117D /* ShakeExample.app */, ); name = Products; sourceTree = ""; @@ -182,7 +182,7 @@ ); name = Runner; productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Shake.app */; + productReference = 97C146EE1CF9000F007C117D /* ShakeExample.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -410,7 +410,7 @@ "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.shakebugs.flutter.example; - PRODUCT_NAME = Shake; + PRODUCT_NAME = ShakeExample; PROVISIONING_PROFILE_SPECIFIER = "Shake Flutter Example"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -552,7 +552,7 @@ "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.shakebugs.flutter.example; - PRODUCT_NAME = Shake; + PRODUCT_NAME = ShakeExample; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -588,7 +588,7 @@ "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.shakebugs.flutter.example; - PRODUCT_NAME = Shake; + PRODUCT_NAME = ShakeExample; PROVISIONING_PROFILE_SPECIFIER = "Shake Flutter Example"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -678,7 +678,7 @@ "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.shakebugs.flutter.example.rc; - PRODUCT_NAME = Shake; + PRODUCT_NAME = ShakeExample; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -766,7 +766,7 @@ "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.shakebugs.flutter.example.rc; - PRODUCT_NAME = Shake; + PRODUCT_NAME = ShakeExample; PROVISIONING_PROFILE_SPECIFIER = "Shake Flutter Example RC"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -851,7 +851,7 @@ "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.shakebugs.flutter.example.rc; - PRODUCT_NAME = Shake; + PRODUCT_NAME = ShakeExample; PROVISIONING_PROFILE_SPECIFIER = "Shake Flutter Example RC"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -941,7 +941,7 @@ "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.shakebugs.flutter.example.pr; - PRODUCT_NAME = Shake; + PRODUCT_NAME = ShakeExample; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -1029,7 +1029,7 @@ "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.shakebugs.flutter.example.pr; - PRODUCT_NAME = Shake; + PRODUCT_NAME = ShakeExample; PROVISIONING_PROFILE_SPECIFIER = "Shake Flutter Example PR"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -1114,7 +1114,7 @@ "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.shakebugs.flutter.example.pr; - PRODUCT_NAME = Shake; + PRODUCT_NAME = ShakeExample; PROVISIONING_PROFILE_SPECIFIER = "Shake Flutter Example PR"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 70693e4..38ea8dc 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -1,5 +1,6 @@ import UIKit import Flutter +import Shake @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { @@ -7,7 +8,36 @@ import Flutter _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { + let center = UNUserNotificationCenter.current() + center.delegate = self + + // Request notifications permission to enabled chat notifications + center.requestAuthorization(options: [.sound,.alert,.badge]) { (granted, error) in + if granted { + print("Notification Enable Successfully") + }else{ + print("Some Error Occure") + } + } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } + + override func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { + if response.notification.request.content.categoryIdentifier.contains(SHKNotificationCategoryIdentifierDomain) { + Shake.report(center, didReceive: response, withCompletionHandler: completionHandler) + return; + } + + completionHandler() + } + + override func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { + if notification.request.content.categoryIdentifier.contains(SHKNotificationCategoryIdentifierDomain) { + Shake.report(center, willPresent: notification, withCompletionHandler: completionHandler) + return; + } + + completionHandler([.badge, .sound, .alert]) + } } diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index 7a7c121..7d29fc8 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -11,7 +11,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - Shake + Shake Flutter CFBundlePackageType APPL CFBundleShortVersionString diff --git a/example/lib/ui/main/home.dart b/example/lib/ui/main/home.dart index 4d3195e..fb199f8 100644 --- a/example/lib/ui/main/home.dart +++ b/example/lib/ui/main/home.dart @@ -228,7 +228,8 @@ class _HomeState extends State { Toggle( 'Screenshot included', screenshotIncluded!, - _onScreenshotIncluded,) + _onScreenshotIncluded, + ) ], ), ), @@ -488,6 +489,7 @@ class _HomeState extends State { configuration.activityHistoryData = true; configuration.blackBoxData = true; configuration.screenshot = true; + configuration.video = true; configuration.showReportSentMessage = true; Shake.silentReport( @@ -502,6 +504,8 @@ class _HomeState extends State { } void _addMetadata() { + Shake.setMetadata("Shake", "Metadata to clear."); + Shake.clearMetadata(); Shake.setMetadata('Shake', 'This is a Shake metadata.'); } @@ -531,7 +535,7 @@ class _HomeState extends State { void _postNotificationEvent() async { FlutterLocalNotificationsPlugin notificationsPlugin = - FlutterLocalNotificationsPlugin(); + FlutterLocalNotificationsPlugin(); InitializationSettings initializationSettings = InitializationSettings( android: AndroidInitializationSettings('@drawable/ic_bug_report'), @@ -540,9 +544,9 @@ class _HomeState extends State { await notificationsPlugin.initialize(initializationSettings); const AndroidNotificationDetails androidDetails = - AndroidNotificationDetails('shake-flutter', 'Shake Flutter'); + AndroidNotificationDetails('shake-flutter', 'Shake Flutter'); const NotificationDetails platformChannelSpecifics = - NotificationDetails(android: androidDetails); + NotificationDetails(android: androidDetails); await notificationsPlugin.show( 0, 'This notification was generated by the app!', diff --git a/example/package-lock.json b/example/package-lock.json new file mode 100644 index 0000000..48e341a --- /dev/null +++ b/example/package-lock.json @@ -0,0 +1,3 @@ +{ + "lockfileVersion": 1 +} diff --git a/ios/Classes/ShakePlugin.m b/ios/Classes/ShakePlugin.m index 001ef22..852a121 100644 --- a/ios/Classes/ShakePlugin.m +++ b/ios/Classes/ShakePlugin.m @@ -60,6 +60,10 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [self setInvokeShakeOnScreenshot:call result:result]; } else if([@"isInvokeShakeOnScreenshot" isEqualToString:call.method]) { [self isInvokeShakeOnScreenshot:call result:result]; + } else if([@"getDefaultScreen" isEqualToString:call.method]) { + [self getDefaultScreen:call result:result]; + } else if([@"setDefaultScreen" isEqualToString:call.method]) { + [self setDefaultScreen:call result:result]; } else if([@"setScreenshotIncluded" isEqualToString:call.method]){ [self setScreenshotIncluded:call result:result]; } else if([@"isScreenshotIncluded" isEqualToString:call.method]){ @@ -74,6 +78,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [self insertNotificationEvent:call result:result]; } else if ([@"setMetadata" isEqualToString:call.method]) { [self setMetadata:call result:result]; + } else if([@"clearMetadata" isEqualToString:call.method]) { + [self clearMetadata:result]; } else if ([@"log" isEqualToString:call.method]) { [self log:call result:result]; } else if([@"setShowIntroMessage" isEqualToString:call.method]) { @@ -136,7 +142,7 @@ - (void)start:(FlutterMethodCall*) call result:(FlutterResult)result { } - (void)show:(FlutterMethodCall*) call result:(FlutterResult)result { - NSString *shakeScreenArg = call.arguments[@"shakeScreen"]; + NSString* shakeScreenArg = call.arguments[@"shakeScreen"]; SHKShowOption showOption = [self mapToShowOption:shakeScreenArg]; [SHKShake show:showOption]; @@ -249,6 +255,21 @@ - (void)isInvokeShakeOnScreenshot:(FlutterMethodCall*) call result:(FlutterResul result(isInvokeShakeOnScreenshotObj); } +- (void)getDefaultScreen:(FlutterMethodCall*) call result:(FlutterResult)result { + SHKShowOption showOption = SHKShake.configuration.defaultShowOption; + NSString* showOptionStr = [self showOptionToString:showOption]; + + result(showOptionStr); +} + +-(void)setDefaultScreen:(FlutterMethodCall*) call result:(FlutterResult) result { + NSString* showOptionsStr = call.arguments[@"shakeScreen"]; + SHKShowOption showOption = [self mapToShowOption:showOptionsStr]; + SHKShake.configuration.defaultShowOption = showOption; + + result(nil); +} + -(void)isScreenshotIncluded:(FlutterMethodCall*) call result:(FlutterResult) result { BOOL isScreenshotIncluded = SHKShake.configuration.isScreenshotIncluded; NSNumber *isScreenshotIncludedObj = [NSNumber numberWithBool:isScreenshotIncluded]; @@ -318,6 +339,12 @@ - (void)setMetadata:(FlutterMethodCall*) call result:(FlutterResult) result { result(nil); } +- (void)clearMetadata:(FlutterResult)result { + [SHKShake clearMetadata]; + + result(nil); +} + - (void)log:(FlutterMethodCall*) call result:(FlutterResult) result { NSString* logLevelStr = call.arguments[@"level"]; NSString* message = call.arguments[@"message"]; @@ -506,6 +533,16 @@ - (SHKShowOption)mapToShowOption:(NSString*)showOptionStr return showOption; } +- (NSString*)showOptionToString:(SHKShowOption)showOption +{ + if (showOption == SHKShowOptionHome) + return @"home"; + if (showOption == SHKShowOptionNew) + return @"newTicket"; + + return @"newTicket"; +} + - (NSMutableArray*)mapToShakeFiles:(nonnull NSArray*)files { NSMutableArray* shakeFiles = [NSMutableArray array]; for(int i = 0; i < [files count]; i++) { @@ -569,13 +606,15 @@ - (SHKShowOption)mapToShowOption:(NSString*)showOptionStr - (SHKShakeReportConfiguration*)mapToConfiguration:(nonnull NSDictionary*)configurationDic { BOOL includesBlackBoxData = [[configurationDic objectForKey:@"blackBoxData"] boolValue]; BOOL includesActivityHistoryData = [[configurationDic objectForKey:@"activityHistoryData"] boolValue]; - BOOL includesScreenshotImage = [[configurationDic objectForKey:@"screenshot"] boolValue]; + BOOL includesScreenshot = [[configurationDic objectForKey:@"screenshot"] boolValue]; + BOOL includesVideo = [[configurationDic objectForKey:@"video"] boolValue]; BOOL showsToastMessageOnSend = [[configurationDic objectForKey:@"showReportSentMessage"] boolValue]; SHKShakeReportConfiguration *reportConfiguration = [[SHKShakeReportConfiguration alloc] init]; reportConfiguration.includesBlackBoxData = includesBlackBoxData; reportConfiguration.includesActivityHistoryData = includesActivityHistoryData; - reportConfiguration.includesScreenshotImage = includesScreenshotImage; + reportConfiguration.includesScreenshotImage = includesScreenshot; + reportConfiguration.includesVideo = includesVideo; reportConfiguration.showsToastMessageOnSend = showsToastMessageOnSend; return reportConfiguration; diff --git a/ios/shake_flutter.podspec b/ios/shake_flutter.podspec index 5872650..47b63fd 100644 --- a/ios/shake_flutter.podspec +++ b/ios/shake_flutter.podspec @@ -19,9 +19,6 @@ Shake SDK wrapper # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } - s.preserve_paths = 'Shake.framework' - s.xcconfig = {'OTHER_LDFLAGS' => '-framework Shake'} - s.vendored_frameworks = 'Shake.framework' - s.dependency "#{ENV['IOS_DEPENDENCY']}", "~> 15.0.0-rc" s.swift_version = '5.0' + s.dependency "#{ENV['IOS_DEPENDENCY']}", "~> 15.1.0-rc" end diff --git a/lib/models/shake_report_configuration.dart b/lib/models/shake_report_configuration.dart index dc6bcb9..0de92ef 100644 --- a/lib/models/shake_report_configuration.dart +++ b/lib/models/shake_report_configuration.dart @@ -3,11 +3,13 @@ /// Set [blackBoxData] to include or exclude black-box from bug report. /// Set [activityHistoryData] to include or exclude activity from bug report. /// Set [screenshot] to include or exclude screenshot from bug report. +/// Set [video] to include or exclude screenshot from bug report. /// Use [showReportSentMessage] to display or hide bug reported message. class ShakeReportConfiguration { bool blackBoxData = true; bool activityHistoryData = true; bool screenshot = true; + bool video = true; bool showReportSentMessage = false; Map toMap() { @@ -15,6 +17,7 @@ class ShakeReportConfiguration { "blackBoxData": blackBoxData, "activityHistoryData": activityHistoryData, "screenshot": screenshot, + "video": video, "showReportSentMessage": showReportSentMessage, }; } diff --git a/lib/network/shake_http_client.dart b/lib/network/shake_http_client.dart index 4b4bad7..c420c73 100644 --- a/lib/network/shake_http_client.dart +++ b/lib/network/shake_http_client.dart @@ -62,7 +62,8 @@ class ShakeHttpClient implements HttpClient { @override set authenticateProxy( - Future Function(String host, int port, String scheme, String? realm)? + Future Function( + String host, int port, String scheme, String? realm)? f) { client.authenticateProxy = f; } diff --git a/lib/shake_flutter.dart b/lib/shake_flutter.dart index da23691..bef7b65 100644 --- a/lib/shake_flutter.dart +++ b/lib/shake_flutter.dart @@ -112,6 +112,23 @@ class Shake { return await _channel.invokeMethod('isInvokeShakeOnShakeDeviceEvent'); } + /// Get screen top open when Shake is manually invoked. + /// + /// Returns [ShakeScreen.home] or [ShakeScreen.newTicket]. + static Future getDefaultScreen() async { + var defaultScreenStr = await _channel.invokeMethod('getDefaultScreen'); + return _mapper.mapToShakeScreen(defaultScreenStr); + } + + /// Sets screen to open when Shake is manually invoked. + /// + /// [ShakeScreen.home] or [ShakeScreen.newTicket]. + static void setDefaultScreen(ShakeScreen shakeScreen) async { + await _channel.invokeMethod('setDefaultScreen', { + 'shakeScreen': describeEnum(shakeScreen), + }); + } + ///Checks what value shaking threshold is set on static Future getShakingThreshold() async { return await _channel.invokeMethod('getShakingThreshold'); @@ -182,6 +199,11 @@ class Shake { }); } + /// Clears existing metadata. + static void clearMetadata() async { + await _channel.invokeMethod('clearMetadata'); + } + /// Adds custom log into the activity history. static void log(LogLevel logLevel, String message) async { await _channel.invokeMethod('log', { diff --git a/lib/utils/mapper.dart b/lib/utils/mapper.dart index b8210ef..d91c594 100644 --- a/lib/utils/mapper.dart +++ b/lib/utils/mapper.dart @@ -1,3 +1,4 @@ +import 'package:shake_flutter/enums/shake_screen.dart'; import 'package:shake_flutter/models/feedback_type.dart'; import 'package:shake_flutter/models/shake_file.dart'; @@ -17,4 +18,12 @@ class Mapper { List> shakeFilesToMap(List shakeFiles) { return shakeFiles.map((shakeFile) => shakeFile.toMap()).toList(); } + + /// Converts string to [ShakeScreen]. + ShakeScreen mapToShakeScreen(String shakeScreenStr) { + if (shakeScreenStr == "newTicket") return ShakeScreen.newTicket; + if (shakeScreenStr == "home") return ShakeScreen.home; + + return ShakeScreen.newTicket; + } }