diff --git a/CHANGELOG.md b/CHANGELOG.md index bfc3356e1..066781091 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Added +- Add support for App variant. ([#585](https://github.com/Instabug/Instabug-Flutter/pull/585)) + - Add support for xCode 16. ([#574](https://github.com/Instabug/Instabug-Flutter/pull/574)) - Add support for BugReporting user consents. ([#573](https://github.com/Instabug/Instabug-Flutter/pull/573)) diff --git a/android/build.gradle b/android/build.gradle index a6c41ffd0..e630d92bc 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -44,7 +44,7 @@ android { } dependencies { - api 'com.instabug.library:instabug:14.3.0' + api 'com.instabug.library:instabug:15.0.1' testImplementation 'junit:junit:4.13.2' testImplementation "org.mockito:mockito-inline:3.12.1" testImplementation "io.mockk:mockk:1.13.13" diff --git a/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java b/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java index edfde055a..35455237d 100644 --- a/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java +++ b/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java @@ -6,9 +6,11 @@ import android.graphics.BitmapFactory; import android.net.Uri; import android.util.Log; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; + import com.instabug.flutter.generated.InstabugPigeon; import com.instabug.flutter.util.ArgsRegistry; import com.instabug.flutter.util.Reflection; @@ -30,9 +32,11 @@ import com.instabug.library.invocation.InstabugInvocationEvent; import com.instabug.library.model.NetworkLog; import com.instabug.library.ui.onboarding.WelcomeMessage; + import io.flutter.FlutterInjector; import io.flutter.embedding.engine.loader.FlutterLoader; import io.flutter.plugin.common.BinaryMessenger; + import org.jetbrains.annotations.NotNull; import org.json.JSONObject; @@ -102,10 +106,12 @@ public Boolean isEnabled() { @NotNull @Override - public Boolean isBuilt() { return Instabug.isBuilt(); } + public Boolean isBuilt() { + return Instabug.isBuilt(); + } @Override - public void init(@NonNull String token, @NonNull List invocationEvents, @NonNull String debugLogsLevel) { + public void init(@NonNull String token, @NonNull List invocationEvents, @NonNull String debugLogsLevel, @Nullable String appVariant) { setCurrentPlatform(); InstabugInvocationEvent[] invocationEventsArray = new InstabugInvocationEvent[invocationEvents.size()]; @@ -116,11 +122,14 @@ public void init(@NonNull String token, @NonNull List invocationEvents, final Application application = (Application) context; final int parsedLogLevel = ArgsRegistry.sdkLogLevels.get(debugLogsLevel); - - new Instabug.Builder(application, token) + Instabug.Builder builder = new Instabug.Builder(application, token) .setInvocationEvents(invocationEventsArray) - .setSdkDebugLogsLevel(parsedLogLevel) - .build(); + .setSdkDebugLogsLevel(parsedLogLevel); + if (appVariant != null) { + builder.setAppVariant(appVariant); + } + + builder.build(); Instabug.setScreenshotProvider(screenshotProvider); } @@ -146,6 +155,17 @@ public void setUserData(@NonNull String data) { Instabug.setUserData(data); } + @Override + public void setAppVariant(@NonNull String appVariant) { + try { + Instabug.setAppVariant(appVariant); + + } catch (Exception e) { + e.printStackTrace(); + } + + } + @Override public void logUserEvent(@NonNull String name) { Instabug.logUserEvent(name); @@ -500,13 +520,13 @@ public void willRedirectToStore() { Instabug.willRedirectToStore(); } - + @Override public void setNetworkLogBodyEnabled(@NonNull Boolean isEnabled) { - try { - Instabug.setNetworkLogBodyEnabled(isEnabled); - } catch (Exception e) { - e.printStackTrace(); - } + try { + Instabug.setNetworkLogBodyEnabled(isEnabled); + } catch (Exception e) { + e.printStackTrace(); + } } } diff --git a/android/src/test/java/com/instabug/flutter/InstabugApiTest.java b/android/src/test/java/com/instabug/flutter/InstabugApiTest.java index 97b9cdf7b..7efb8e425 100644 --- a/android/src/test/java/com/instabug/flutter/InstabugApiTest.java +++ b/android/src/test/java/com/instabug/flutter/InstabugApiTest.java @@ -132,6 +132,8 @@ public void testSetCurrentPlatform() { @Test public void testSdkInit() { String token = "app-token"; + String appVariant = "app-variant"; + List invocationEvents = Collections.singletonList("InvocationEvent.floatingButton"); String logLevel = "LogLevel.error"; @@ -143,7 +145,7 @@ public void testSdkInit() { when(mock.setSdkDebugLogsLevel(anyInt())).thenReturn(mock); }); - api.init(token, invocationEvents, logLevel); + api.init(token, invocationEvents, logLevel,appVariant); Instabug.Builder builder = mInstabugBuilder.constructed().get(0); @@ -155,6 +157,8 @@ public void testSdkInit() { ); verify(builder).setInvocationEvents(InstabugInvocationEvent.FLOATING_BUTTON); verify(builder).setSdkDebugLogsLevel(LogLevel.ERROR); + verify(builder).setAppVariant(appVariant); + verify(builder).build(); // Sets screenshot provider @@ -652,6 +656,14 @@ public void testSetNetworkLogBodyEnabled() { mInstabug.verify(() -> Instabug.setNetworkLogBodyEnabled(true)); } + @Test + public void testSetAppVariant() { + String appVariant = "app-variant"; + api.setAppVariant(appVariant); + + mInstabug.verify(() -> Instabug.setAppVariant(appVariant)); + } + @Test public void testSetNetworkLogBodyDisabled() { api.setNetworkLogBodyEnabled(false); diff --git a/example/ios/InstabugTests/InstabugApiTests.m b/example/ios/InstabugTests/InstabugApiTests.m index 9f2c04373..3cbcc13f0 100644 --- a/example/ios/InstabugTests/InstabugApiTests.m +++ b/example/ios/InstabugTests/InstabugApiTests.m @@ -38,15 +38,22 @@ - (void)testSetEnabled { - (void)testInit { NSString *token = @"app-token"; + NSString *appVariant = @"app-variant"; + NSArray *invocationEvents = @[@"InvocationEvent.floatingButton", @"InvocationEvent.screenshot"]; NSString *logLevel = @"LogLevel.error"; FlutterError *error; - [self.api initToken:token invocationEvents:invocationEvents debugLogsLevel:logLevel error:&error]; + [self.api initToken:token invocationEvents:invocationEvents debugLogsLevel:logLevel appVariant:appVariant error:&error]; OCMVerify([self.mInstabug setCurrentPlatform:IBGPlatformFlutter]); + OCMVerify([self.mInstabug setSdkDebugLogsLevel:IBGSDKDebugLogsLevelError]); + OCMVerify([self.mInstabug startWithToken:token invocationEvents:(IBGInvocationEventFloatingButton | IBGInvocationEventScreenshot)]); + + XCTAssertEqual(Instabug.appVariant, appVariant); + } - (void)testShow { diff --git a/example/ios/Podfile b/example/ios/Podfile index 6020d7a4b..8c33e3737 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -30,7 +30,7 @@ target 'Runner' do use_frameworks! use_modular_headers! - pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/fix-main-thread-warning/15.0.0/Instabug.podspec' +# pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/fix-main-thread-warning/15.0.0/Instabug.podspec' flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 38bbc9c4e..7fc4f1185 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,35 +1,33 @@ PODS: - Flutter (1.0.0) - - Instabug (15.0.0) + - Instabug (15.1.1) - instabug_flutter (14.3.0): - Flutter - - Instabug (= 15.0.0) + - Instabug (= 15.1.1) - OCMock (3.6) DEPENDENCIES: - Flutter (from `Flutter`) - - Instabug (from `https://ios-releases.instabug.com/custom/fix-main-thread-warning/15.0.0/Instabug.podspec`) - instabug_flutter (from `.symlinks/plugins/instabug_flutter/ios`) - OCMock (= 3.6) SPEC REPOS: trunk: + - Instabug - OCMock EXTERNAL SOURCES: Flutter: :path: Flutter - Instabug: - :podspec: https://ios-releases.instabug.com/custom/fix-main-thread-warning/15.0.0/Instabug.podspec instabug_flutter: :path: ".symlinks/plugins/instabug_flutter/ios" SPEC CHECKSUMS: Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - Instabug: 3b1db5a683e85ec5a02946aa2b3314036f9022be - instabug_flutter: e59da7a0cae82ce00b2773625ee544c275442000 + Instabug: 3e7af445c14d7823fcdecba223f09b5f7c0c6ce1 + instabug_flutter: 9985587d7f2ea3c71c989e97a8693bb3e278da8d OCMock: 5ea90566be239f179ba766fd9fbae5885040b992 -PODFILE CHECKSUM: c16418947581b888c337ed7ff120a59b4b5f3f3f +PODFILE CHECKSUM: ce81c2e411a4f13d81e98c82acb1a197da154fb3 COCOAPODS: 1.16.2 diff --git a/example/lib/main.dart b/example/lib/main.dart index 91b0a67e7..1052d42c8 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -48,10 +48,10 @@ void main() { WidgetsFlutterBinding.ensureInitialized(); Instabug.init( - token: 'ed6f659591566da19b67857e1b9d40ab', - invocationEvents: [InvocationEvent.floatingButton], - debugLogsLevel: LogLevel.verbose, - ); + token: 'ed6f659591566da19b67857e1b9d40ab', + invocationEvents: [InvocationEvent.floatingButton], + debugLogsLevel: LogLevel.verbose, + appVariant: 'variant 1'); FlutterError.onError = (FlutterErrorDetails details) { Zone.current.handleUncaughtError(details.exception, details.stack!); diff --git a/example/pubspec.lock b/example/pubspec.lock index 93971dc8b..423416d07 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -37,10 +37,26 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" + dio: + dependency: "direct main" + description: + name: dio + sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9" + url: "https://pub.dev" + source: hosted + version: "5.8.0+1" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78" + url: "https://pub.dev" + source: hosted + version: "2.1.1" fake_async: dependency: transitive description: @@ -120,18 +136,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" url: "https://pub.dev" source: hosted - version: "10.0.5" + version: "10.0.7" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.8" leak_tracker_testing: dependency: transitive description: @@ -200,7 +216,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: @@ -213,10 +229,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.0" stream_channel: dependency: transitive description: @@ -229,10 +245,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" sync_http: dependency: transitive description: @@ -253,10 +269,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.3" typed_data: dependency: transitive description: @@ -277,18 +293,26 @@ packages: dependency: transitive description: name: vm_service - sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + url: "https://pub.dev" + source: hosted + version: "14.3.0" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" url: "https://pub.dev" source: hosted - version: "14.2.5" + version: "1.1.1" webdriver: dependency: transitive description: name: webdriver - sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e" + sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.4" sdks: dart: ">=3.5.0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/ios/Classes/Modules/InstabugApi.m b/ios/Classes/Modules/InstabugApi.m index 3bdc465f0..edced7a05 100644 --- a/ios/Classes/Modules/InstabugApi.m +++ b/ios/Classes/Modules/InstabugApi.m @@ -29,7 +29,13 @@ - (nullable NSNumber *)isEnabledWithError:(FlutterError * _Nullable __autoreleas return @(Instabug.enabled); } -- (void)initToken:(NSString *)token invocationEvents:(NSArray *)invocationEvents debugLogsLevel:(NSString *)debugLogsLevel error:(FlutterError *_Nullable *_Nonnull)error { +- (void)initToken:(nonnull NSString *)token invocationEvents:(nonnull NSArray *)invocationEvents debugLogsLevel:(nonnull NSString *)debugLogsLevel appVariant:(nullable NSString *)appVariant error:(FlutterError * _Nullable __autoreleasing * _Nonnull)error { + + if(appVariant != nil){ + Instabug.appVariant = appVariant; + } + + SEL setPrivateApiSEL = NSSelectorFromString(@"setCurrentPlatform:"); if ([[Instabug class] respondsToSelector:setPrivateApiSEL]) { NSInteger *platformID = IBGPlatformFlutter; @@ -45,7 +51,8 @@ - (void)initToken:(NSString *)token invocationEvents:(NSArray *)invo [IBGNetworkLogger disableAutomaticCapturingOfNetworkLogs]; IBGInvocationEvent resolvedEvents = 0; - + + for (NSString *event in invocationEvents) { resolvedEvents |= (ArgsRegistry.invocationEvents[event]).integerValue; } @@ -396,4 +403,12 @@ - (void)setNetworkLogBodyEnabledIsEnabled:(NSNumber *)isEnabled IBGNetworkLogger.logBodyEnabled = [isEnabled boolValue]; } + +- (void)setAppVariantAppVariant:(nonnull NSString *)appVariant error:(FlutterError * _Nullable __autoreleasing * _Nonnull)error { + + Instabug.appVariant = appVariant; + +} + + @end diff --git a/ios/instabug_flutter.podspec b/ios/instabug_flutter.podspec index 22c684ec7..ffb6ca962 100644 --- a/ios/instabug_flutter.podspec +++ b/ios/instabug_flutter.podspec @@ -17,6 +17,6 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-framework "Flutter" -framework "InstabugSDK"'} s.dependency 'Flutter' - s.dependency 'Instabug', '15.0.0' + s.dependency 'Instabug', '15.1.1' end diff --git a/lib/src/modules/instabug.dart b/lib/src/modules/instabug.dart index 6bba8ed1f..80726fd7e 100644 --- a/lib/src/modules/instabug.dart +++ b/lib/src/modules/instabug.dart @@ -11,6 +11,7 @@ import 'dart:typed_data'; import 'dart:ui'; import 'package:flutter/material.dart'; + // to maintain supported versions prior to Flutter 3.3 // ignore: unused_import import 'package:flutter/services.dart'; @@ -179,10 +180,12 @@ class Instabug { /// The [token] that identifies the app, you can find it on your dashboard. /// The [invocationEvents] are the events that invoke the SDK's UI. /// The [debugLogsLevel] used to debug Instabug's SDK. + /// The [appVariant] used to set current App variant name. static Future init({ required String token, required List invocationEvents, LogLevel debugLogsLevel = LogLevel.error, + String? appVariant, }) async { $setup(); InstabugLogger.I.logLevel = debugLogsLevel; @@ -190,6 +193,7 @@ class Instabug { token, invocationEvents.mapToString(), debugLogsLevel.toString(), + appVariant, ); return FeatureFlagsManager().registerW3CFlagsListener(); } @@ -482,4 +486,11 @@ class Instabug { static Future willRedirectToStore() async { return _host.willRedirectToStore(); } + + /// This property sets the `appVariant` string to be included in all network requests. + /// It should be set before calling [init] method. + /// [appVariant] used to set current App variant name + static Future setAppVariant(String appVariant) async { + return _host.setAppVariant(appVariant); + } } diff --git a/pigeons/instabug.api.dart b/pigeons/instabug.api.dart index 275306987..6502409cc 100644 --- a/pigeons/instabug.api.dart +++ b/pigeons/instabug.api.dart @@ -12,39 +12,65 @@ abstract class FeatureFlagsFlutterApi { @HostApi() abstract class InstabugHostApi { void setEnabled(bool isEnabled); + bool isEnabled(); + bool isBuilt(); - void init(String token, List invocationEvents, String debugLogsLevel); + + void init( + String token, + List invocationEvents, + String debugLogsLevel, + String? appVariant, + ); void show(); + void showWelcomeMessageWithMode(String mode); void identifyUser(String email, String? name, String? userId); + void setUserData(String data); + + void setAppVariant(String appVariant); + void logUserEvent(String name); + void logOut(); void setLocale(String locale); + void setColorTheme(String theme); + void setWelcomeMessageMode(String mode); + void setPrimaryColor(int color); + void setSessionProfilerEnabled(bool enabled); + void setValueForStringWithKey(String value, String key); void appendTags(List tags); + void resetTags(); @async List? getTags(); void addExperiments(List experiments); + void removeExperiments(List experiments); + void clearAllExperiments(); + void addFeatureFlags(Map featureFlagsMap); + void removeFeatureFlags(List featureFlags); + void removeAllFeatureFlags(); void setUserAttribute(String value, String key); + void removeUserAttribute(String key); @async @@ -58,13 +84,17 @@ abstract class InstabugHostApi { String? crashMode, String? sessionReplayMode, ); + void reportScreenChange(String screenName); void setCustomBrandingImage(String light, String dark); + void setFont(String font); void addFileAttachmentWithURL(String filePath, String fileName); + void addFileAttachmentWithData(Uint8List data, String fileName); + void clearFileAttachments(); void networkLog(Map data); diff --git a/test/instabug_test.dart b/test/instabug_test.dart index e2fd7d298..b6f891221 100644 --- a/test/instabug_test.dart +++ b/test/instabug_test.dart @@ -84,7 +84,7 @@ void main() { ); verify( - mHost.init(token, events.mapToString(), LogLevel.error.toString()), + mHost.init(token, events.mapToString(), LogLevel.error.toString(), null), ).called(1); });