diff --git a/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java index cd1e018cb..b79d82dbb 100644 --- a/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java @@ -19,6 +19,7 @@ import com.instabug.flutter.modules.RepliesApi; import com.instabug.flutter.modules.SessionReplayApi; import com.instabug.flutter.modules.SurveysApi; +import com.instabug.library.internal.crossplatform.InternalCore; import java.util.concurrent.Callable; @@ -35,6 +36,7 @@ public class InstabugFlutterPlugin implements FlutterPlugin, ActivityAware { @SuppressLint("StaticFieldLeak") private static Activity activity; + /** * Embedding v1 */ diff --git a/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java index 74c4e4ba4..cd3a09b52 100644 --- a/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java @@ -6,13 +6,16 @@ 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; import com.instabug.flutter.util.ThreadManager; +import com.instabug.flutter.util.privateViews.ScreenshotCaptor; import com.instabug.library.Feature; import com.instabug.library.Instabug; import com.instabug.library.InstabugColorTheme; @@ -21,13 +24,17 @@ import com.instabug.library.Platform; import com.instabug.library.ReproConfigurations; import com.instabug.library.featuresflags.model.IBGFeatureFlag; +import com.instabug.library.internal.crossplatform.InternalCore; import com.instabug.library.internal.module.InstabugLocale; import com.instabug.library.invocation.InstabugInvocationEvent; import com.instabug.library.model.NetworkLog; +import com.instabug.library.screenshot.instacapture.ScreenshotRequest; 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; @@ -92,7 +99,9 @@ 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) { @@ -441,4 +450,24 @@ public void networkLog(@NonNull Map data) { public void willRedirectToStore() { Instabug.willRedirectToStore(); } + + public static void setScreenshotCaptor(ScreenshotCaptor screenshotCaptor,InternalCore internalCore) { + internalCore._setScreenshotCaptor(new com.instabug.library.screenshot.ScreenshotCaptor() { + @Override + public void capture(@NonNull ScreenshotRequest screenshotRequest) { + screenshotCaptor.capture(new ScreenshotCaptor.CapturingCallback() { + @Override + public void onCapturingFailure(Throwable throwable) { + screenshotRequest.getListener().onCapturingFailure(throwable); + } + + @Override + public void onCapturingSuccess(Bitmap bitmap) { + screenshotRequest.getListener().onCapturingSuccess(bitmap); + } + }); + } + }); + } + } diff --git a/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/util/privateViews/ScreenshotCaptor.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/util/privateViews/ScreenshotCaptor.java new file mode 100644 index 000000000..86eb40007 --- /dev/null +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/util/privateViews/ScreenshotCaptor.java @@ -0,0 +1,13 @@ +package com.instabug.flutter.util.privateViews; + +import android.graphics.Bitmap; + +public interface ScreenshotCaptor { + public void capture(CapturingCallback listener); + + public interface CapturingCallback { + public void onCapturingFailure(Throwable throwable); + + public void onCapturingSuccess(Bitmap bitmap); + } +} \ No newline at end of file diff --git a/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/InstabugApiTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/InstabugApiTest.java index 2abb8987e..1474071bf 100644 --- a/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/InstabugApiTest.java +++ b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/InstabugApiTest.java @@ -36,8 +36,10 @@ import com.instabug.library.ReproConfigurations; import com.instabug.library.ReproMode; import com.instabug.library.featuresflags.model.IBGFeatureFlag; +import com.instabug.library.internal.crossplatform.InternalCore; import com.instabug.library.invocation.InstabugInvocationEvent; import com.instabug.library.model.NetworkLog; +import com.instabug.library.screenshot.ScreenshotCaptor; import com.instabug.library.ui.onboarding.WelcomeMessage; import org.json.JSONObject; @@ -59,6 +61,7 @@ import java.util.concurrent.Callable; import io.flutter.plugin.common.BinaryMessenger; + import org.mockito.verification.VerificationMode; public class InstabugApiTest { @@ -349,11 +352,11 @@ public void testClearAllExperiments() { @Test public void testAddFeatureFlags() { - Map featureFlags = new HashMap<>(); - featureFlags.put("key1","variant1"); + Map featureFlags = new HashMap<>(); + featureFlags.put("key1", "variant1"); api.addFeatureFlags(featureFlags); - List flags=new ArrayList(); - flags.add(new IBGFeatureFlag("key1","variant1")); + List flags = new ArrayList(); + flags.add(new IBGFeatureFlag("key1", "variant1")); mInstabug.verify(() -> Instabug.addFeatureFlags(flags)); } @@ -598,4 +601,12 @@ public void testWillRedirectToStore() { api.willRedirectToStore(); mInstabug.verify(Instabug::willRedirectToStore); } + + @Test + public void testSetScreenshotCaptor() { + InternalCore internalCore = spy(InternalCore.INSTANCE); + + InstabugApi.setScreenshotCaptor(any(), internalCore); + verify(internalCore)._setScreenshotCaptor(any(ScreenshotCaptor.class)); + } } diff --git a/packages/instabug_flutter/example/ios/Podfile.lock b/packages/instabug_flutter/example/ios/Podfile.lock index b0ee46890..00c869075 100644 --- a/packages/instabug_flutter/example/ios/Podfile.lock +++ b/packages/instabug_flutter/example/ios/Podfile.lock @@ -8,26 +8,28 @@ PODS: DEPENDENCIES: - Flutter (from `Flutter`) + - Instabug (from `https://ios-releases.instabug.com/custom/feature-flutter-private-views-base/13.4.2/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/feature-flutter-private-views-base/13.4.2/Instabug.podspec instabug_flutter: :path: ".symlinks/plugins/instabug_flutter/ios" SPEC CHECKSUMS: Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - Instabug: 7a71890217b97b1e32dbca96661845396b66da2f + Instabug: 7aacd5099c11ce96bc49dda40eba0963c06acccc instabug_flutter: a2df87e3d4d9e410785e0b1ffef4bc64d1f4b787 OCMock: 5ea90566be239f179ba766fd9fbae5885040b992 -PODFILE CHECKSUM: 8f7552fd115ace1988c3db54a69e4a123c448f84 +PODFILE CHECKSUM: 02e3295e1482e04d2cbd38390c8ea91a5c0c2ff1 COCOAPODS: 1.14.3 diff --git a/packages/instabug_private_views/CHANGELOG.md b/packages/instabug_private_views/CHANGELOG.md index 41cc7d819..26deb9dda 100644 --- a/packages/instabug_private_views/CHANGELOG.md +++ b/packages/instabug_private_views/CHANGELOG.md @@ -1,3 +1,7 @@ -## 0.0.1 +# Changelog -* TODO: Describe initial release. +## [UnReleased](https://github.com/Instabug/) + +### Added + +- Add support for masking private views during screen capturing ([#527](https://github.com/Instabug/Instabug-Flutter/pull/527)). diff --git a/packages/instabug_private_views/README.md b/packages/instabug_private_views/README.md index 0fb279904..0c7f936a8 100644 --- a/packages/instabug_private_views/README.md +++ b/packages/instabug_private_views/README.md @@ -35,7 +35,7 @@ void main() { invocationEvents: [InvocationEvent.floatingButton], ); - ReproSteps.enablePrivateViews(); + ReproSteps.enableMaskingPrivateViews(); runApp(MyApp()); diff --git a/packages/instabug_private_views/android/src/main/java/com/instabug/instabug_private_views/InstabugPrivateViewsPlugin.java b/packages/instabug_private_views/android/src/main/java/com/instabug/instabug_private_views/InstabugPrivateViewsPlugin.java index 662328c5b..2065b60c1 100644 --- a/packages/instabug_private_views/android/src/main/java/com/instabug/instabug_private_views/InstabugPrivateViewsPlugin.java +++ b/packages/instabug_private_views/android/src/main/java/com/instabug/instabug_private_views/InstabugPrivateViewsPlugin.java @@ -82,7 +82,7 @@ public void onDetachedFromActivity() { private void register(BinaryMessenger messenger, FlutterRenderer renderer) { privateViewManager = new PrivateViewManager(new InstabugPrivateViewPigeon.InstabugPrivateViewFlutterApi(messenger), new PixelCopyCaptureManager(), new BoundryCaptureManager(renderer)); - InstabugPrivateView instabugPrivateView=new InstabugPrivateView(messenger,privateViewManager, InternalCore.INSTANCE); + InstabugPrivateView.init(messenger,privateViewManager); } } diff --git a/packages/instabug_private_views/android/src/main/java/com/instabug/instabug_private_views/modules/InstabugPrivateView.java b/packages/instabug_private_views/android/src/main/java/com/instabug/instabug_private_views/modules/InstabugPrivateView.java index 26c332b40..9213eadf3 100644 --- a/packages/instabug_private_views/android/src/main/java/com/instabug/instabug_private_views/modules/InstabugPrivateView.java +++ b/packages/instabug_private_views/android/src/main/java/com/instabug/instabug_private_views/modules/InstabugPrivateView.java @@ -2,31 +2,38 @@ import androidx.annotation.NonNull; +import com.instabug.flutter.generated.InstabugLogPigeon; +import com.instabug.flutter.modules.InstabugApi; +import com.instabug.flutter.modules.InstabugLogApi; +import com.instabug.flutter.util.privateViews.ScreenshotCaptor; import com.instabug.instabug_private_views.generated.InstabugPrivateViewPigeon; import com.instabug.library.internal.crossplatform.InternalCore; -import com.instabug.library.screenshot.ScreenshotCaptor; import com.instabug.library.screenshot.instacapture.ScreenshotRequest; import io.flutter.plugin.common.BinaryMessenger; public class InstabugPrivateView implements InstabugPrivateViewPigeon.InstabugPrivateViewHostApi { PrivateViewManager privateViewManager; - private final InternalCore internalCore; - public InstabugPrivateView(BinaryMessenger messenger, PrivateViewManager privateViewManager, InternalCore internalCore) { + public static void init(BinaryMessenger messenger, PrivateViewManager privateViewManager) { + final InstabugPrivateView api = new InstabugPrivateView(messenger,privateViewManager); + InstabugPrivateViewPigeon.InstabugPrivateViewHostApi.setup(messenger, api); + } + + public InstabugPrivateView(BinaryMessenger messenger, PrivateViewManager privateViewManager) { this.privateViewManager = privateViewManager; - this.internalCore = internalCore; InstabugPrivateViewPigeon.InstabugPrivateViewHostApi.setup(messenger, this); } @Override public void init() { - internalCore._setScreenshotCaptor(new ScreenshotCaptor() { + InstabugApi.setScreenshotCaptor(new ScreenshotCaptor() { @Override - public void capture(@NonNull ScreenshotRequest screenshotRequest) { - privateViewManager.mask(screenshotRequest.getListener()); + public void capture(CapturingCallback listener) { + privateViewManager.mask(listener); + } - }); + },InternalCore.INSTANCE); } } diff --git a/packages/instabug_private_views/android/src/main/java/com/instabug/instabug_private_views/modules/PrivateViewManager.java b/packages/instabug_private_views/android/src/main/java/com/instabug/instabug_private_views/modules/PrivateViewManager.java index 8a30a140e..6b8abb152 100644 --- a/packages/instabug_private_views/android/src/main/java/com/instabug/instabug_private_views/modules/PrivateViewManager.java +++ b/packages/instabug_private_views/android/src/main/java/com/instabug/instabug_private_views/modules/PrivateViewManager.java @@ -10,11 +10,11 @@ import androidx.annotation.VisibleForTesting; import com.instabug.flutter.util.ThreadManager; +import com.instabug.flutter.util.privateViews.ScreenshotCaptor; import com.instabug.instabug_private_views.generated.InstabugPrivateViewPigeon; import com.instabug.instabug_private_views.model.ScreenshotResult; import com.instabug.instabug_private_views.modules.capturing.CaptureManager; import com.instabug.instabug_private_views.modules.capturing.ScreenshotResultCallback; -import com.instabug.library.screenshot.ScreenshotCaptor; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -22,7 +22,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicReference; -public class PrivateViewManager { +public class PrivateViewManager { private static final String THREAD_NAME = "IBG-Flutter-Screenshot"; public static final String EXCEPTION_MESSAGE = "IBG-Flutter-Screenshot: error capturing screenshot"; diff --git a/packages/instabug_private_views/example/android/gradlew b/packages/instabug_private_views/example/android/gradlew old mode 100644 new mode 100755 diff --git a/packages/instabug_private_views/example/ios/Runner.xcodeproj/project.pbxproj b/packages/instabug_private_views/example/ios/Runner.xcodeproj/project.pbxproj index a7281449c..ef3f7beed 100644 --- a/packages/instabug_private_views/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/instabug_private_views/example/ios/Runner.xcodeproj/project.pbxproj @@ -15,6 +15,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 */; }; + BE133A632CD831A500FEADB5 /* PrivateViewHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BE133A622CD831A500FEADB5 /* PrivateViewHostApiTests.m */; }; BE9F8D392CD5C068003ADA97 /* PrivateViewApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BE9F8D382CD5C068003ADA97 /* PrivateViewApiTests.m */; }; /* End PBXBuildFile section */ @@ -64,6 +65,7 @@ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 99B4BB79D25D93036AAF6480 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; A1871ACDFF6D3EA7210660EF /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + BE133A622CD831A500FEADB5 /* PrivateViewHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrivateViewHostApiTests.m; sourceTree = ""; }; BE9F8D382CD5C068003ADA97 /* PrivateViewApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrivateViewApiTests.m; sourceTree = ""; }; BE9F8D3A2CD5C06A003ADA97 /* RunnerTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RunnerTests-Bridging-Header.h"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -93,6 +95,7 @@ children = ( BE9F8D382CD5C068003ADA97 /* PrivateViewApiTests.m */, BE9F8D3A2CD5C06A003ADA97 /* RunnerTests-Bridging-Header.h */, + BE133A622CD831A500FEADB5 /* PrivateViewHostApiTests.m */, ); path = RunnerTests; sourceTree = ""; @@ -390,6 +393,7 @@ buildActionMask = 2147483647; files = ( BE9F8D392CD5C068003ADA97 /* PrivateViewApiTests.m in Sources */, + BE133A632CD831A500FEADB5 /* PrivateViewHostApiTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/instabug_private_views/example/ios/RunnerTests/PrivateViewHostApiTests.m b/packages/instabug_private_views/example/ios/RunnerTests/PrivateViewHostApiTests.m new file mode 100644 index 000000000..8cbe328ea --- /dev/null +++ b/packages/instabug_private_views/example/ios/RunnerTests/PrivateViewHostApiTests.m @@ -0,0 +1,57 @@ +#import +#import +#import +#import "PrivateViewApi.h" +#import "instabug_flutter/InstabugApi.h" +#import "PrivateViewHostApi.h" + +@interface PrivateViewHostApiTests : XCTestCase + +@property (nonatomic, strong) PrivateViewHostApi *api; +@property (nonatomic, strong) id privateViewApiMock; + +@end + +@implementation PrivateViewHostApiTests + +- (void)setUp { + [super setUp]; + + // Set up a mock for PrivateViewApi + self.privateViewApiMock = OCMClassMock([PrivateViewApi class]); + + // Initialize the PrivateViewHostApi instance + self.api = [[PrivateViewHostApi alloc] init]; + self.api.privateViewApi = self.privateViewApiMock; +} + +- (void)tearDown { + self.api = nil; + self.privateViewApiMock = nil; + [super tearDown]; +} + +- (void)testInitWithError_setsScreenshotMaskingHandler { + // Define an expectation for the screenshot masking handler + UIImage *mockScreenshot = [[UIImage alloc] init]; + UIImage *mockMaskedImage = [[UIImage alloc] init]; + FlutterError *error = nil; + + + + OCMStub([self.privateViewApiMock mask:mockScreenshot completion:([OCMArg invokeBlockWithArgs:mockMaskedImage, nil])]); + + + // Call initWithError and set up the screenshot masking handler + [self.api initWithError:&error]; + + // Invoke the screenshot masking handler + void (^completionHandler)(UIImage * _Nullable) = ^(UIImage * _Nullable maskedImage) { + XCTAssertEqual(maskedImage, mockMaskedImage, @"The masked image should be returned by the completion handler."); + }; + [InstabugApi setScreenshotMaskingHandler:^(UIImage * _Nonnull screenshot, void (^ _Nonnull completion)(UIImage * _Nullable)) { + completionHandler(screenshot); + }]; +} + +@end diff --git a/packages/instabug_private_views/example/pubspec.lock b/packages/instabug_private_views/example/pubspec.lock deleted file mode 100644 index 7f9a6825f..000000000 --- a/packages/instabug_private_views/example/pubspec.lock +++ /dev/null @@ -1,304 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - async: - dependency: transitive - description: - name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.dev" - source: hosted - version: "2.11.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - characters: - dependency: transitive - description: - name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - clock: - dependency: transitive - description: - name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.dev" - source: hosted - version: "1.1.1" - collection: - dependency: transitive - description: - name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a - url: "https://pub.dev" - source: hosted - version: "1.18.0" - csslib: - dependency: transitive - description: - name: csslib - sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" - url: "https://pub.dev" - source: hosted - version: "1.0.2" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" - source: hosted - version: "1.0.8" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.dev" - source: hosted - version: "1.3.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" - url: "https://pub.dev" - source: hosted - version: "4.0.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - html: - dependency: transitive - description: - name: html - sha256: "1fc58edeaec4307368c60d59b7e15b9d658b57d7f3125098b6294153c75337ec" - url: "https://pub.dev" - source: hosted - version: "0.15.5" - instabug_flutter: - dependency: "direct main" - description: - path: "../../instabug_flutter" - relative: true - source: path - version: "13.4.0" - instabug_private_views: - dependency: "direct main" - description: - path: ".." - relative: true - source: path - version: "1.0.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" - url: "https://pub.dev" - source: hosted - 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 - sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" - url: "https://pub.dev" - source: hosted - version: "4.0.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb - url: "https://pub.dev" - source: hosted - version: "0.12.16+1" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" - source: hosted - version: "0.11.1" - meta: - dependency: transitive - description: - name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 - url: "https://pub.dev" - source: hosted - version: "1.15.0" - path: - dependency: transitive - description: - name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" - url: "https://pub.dev" - source: hosted - version: "1.9.0" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" - url: "https://pub.dev" - source: hosted - version: "1.10.0" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" - url: "https://pub.dev" - source: hosted - version: "1.11.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 - url: "https://pub.dev" - source: hosted - version: "2.1.2" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.dev" - source: hosted - version: "1.2.1" - test_api: - dependency: transitive - description: - name: test_api - sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" - url: "https://pub.dev" - source: hosted - version: "0.7.2" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - video_player: - dependency: "direct main" - description: - name: video_player - sha256: "4a8c3492d734f7c39c2588a3206707a05ee80cef52e8c7f3b2078d430c84bc17" - url: "https://pub.dev" - source: hosted - version: "2.9.2" - video_player_android: - dependency: transitive - description: - name: video_player_android - sha256: "391e092ba4abe2f93b3e625bd6b6a6ec7d7414279462c1c0ee42b5ab8d0a0898" - url: "https://pub.dev" - source: hosted - version: "2.7.16" - video_player_avfoundation: - dependency: transitive - description: - name: video_player_avfoundation - sha256: cd5ab8a8bc0eab65ab0cea40304097edc46da574c8c1ecdee96f28cd8ef3792f - url: "https://pub.dev" - source: hosted - version: "2.6.2" - video_player_platform_interface: - dependency: transitive - description: - name: video_player_platform_interface - sha256: "229d7642ccd9f3dc4aba169609dd6b5f3f443bb4cc15b82f7785fcada5af9bbb" - url: "https://pub.dev" - source: hosted - version: "6.2.3" - video_player_web: - dependency: transitive - description: - name: video_player_web - sha256: "881b375a934d8ebf868c7fb1423b2bfaa393a0a265fa3f733079a86536064a10" - url: "https://pub.dev" - source: hosted - version: "2.3.3" - 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: ">=3.5.0 <4.0.0" - flutter: ">=3.24.0" diff --git a/packages/instabug_private_views/example/pubspec.yaml b/packages/instabug_private_views/example/pubspec.yaml index 6b7e0bea9..8e9d153ee 100644 --- a/packages/instabug_private_views/example/pubspec.yaml +++ b/packages/instabug_private_views/example/pubspec.yaml @@ -1,29 +1,17 @@ name: instabug_private_views_example description: "Demonstrates how to use the instabug_private_views plugin." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev environment: - sdk: ">=2.14.0 <4.0.0" + sdk: ">=2.12.0 <4.0.0" -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. dependencies: flutter: sdk: flutter instabug_private_views: - path: ../ - instabug_flutter: - path: '../../instabug_flutter' + path: '../' - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 video_player: diff --git a/packages/instabug_private_views/example/pubspec_overrides.yaml b/packages/instabug_private_views/example/pubspec_overrides.yaml deleted file mode 100644 index 709235b01..000000000 --- a/packages/instabug_private_views/example/pubspec_overrides.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# melos_managed_dependency_overrides: instabug_private_views,instabug_flutter -dependency_overrides: - instabug_flutter: - path: ../../instabug_flutter - instabug_private_views: - path: .. diff --git a/packages/instabug_private_views/ios/Classes/PrivateViewApi.h b/packages/instabug_private_views/ios/Classes/PrivateViewApi.h deleted file mode 100644 index 80aa0bd36..000000000 --- a/packages/instabug_private_views/ios/Classes/PrivateViewApi.h +++ /dev/null @@ -1,34 +0,0 @@ -#import -#import "InstabugPrivateViewPigeon.h" -#import - - -@interface PrivateViewApi : NSObject - -@property (nonatomic, strong) InstabugPrivateViewFlutterApi *flutterApi; -@property (nonatomic, strong) NSObject * flutterEngineRegistrar; - -- (instancetype)initWithFlutterApi:(InstabugPrivateViewFlutterApi *)api - registrar:(NSObject *)registrar; - -- (void)mask:(UIImage *)screenshot - completion:(void (^)(UIImage *maskedImage))completion; -- (void)handlePrivateViewsResult:(NSArray *)rectangles - error:(FlutterError *)error - screenshot:(UIImage *)screenshot - completion:(void (^)(UIImage *))completion; -- (NSArray *)convertToRectangles:(NSArray *)rectangles; - -- (UIImage *)drawMaskedImage:(UIImage *)screenshot withPrivateViews:(NSArray *)privateViews; -- (CGPoint)getFlutterViewOrigin; - -- (void)logError:(FlutterError *)error; - -@end - -// Extern function to initialize PrivateViewApi -extern PrivateViewApi* InitPrivateViewApi( - id messenger, - NSObject *flutterEngineRegistrar -); - diff --git a/packages/instabug_private_views/ios/Classes/PrivateViewApi.m b/packages/instabug_private_views/ios/Classes/PrivateViewApi.m deleted file mode 100644 index 4ff3d173d..000000000 --- a/packages/instabug_private_views/ios/Classes/PrivateViewApi.m +++ /dev/null @@ -1,116 +0,0 @@ -#import "PrivateViewApi.h" -#import "Util/FlutterPluginRegistrar+FlutterEngine.h" - -extern PrivateViewApi* InitPrivateViewApi( - id messenger, - NSObject *flutterEngineRegistrar -) { - InstabugPrivateViewFlutterApi *flutterApi = [[InstabugPrivateViewFlutterApi alloc] initWithBinaryMessenger:messenger]; - return [[PrivateViewApi alloc] initWithFlutterApi:flutterApi registrar:flutterEngineRegistrar]; -} - -@implementation PrivateViewApi - -// Initializer with proper memory management -- (instancetype)initWithFlutterApi:(InstabugPrivateViewFlutterApi *)api - registrar:( NSObject *) registrar { - if ((self = [super init])) { - _flutterApi = api; - _flutterEngineRegistrar = registrar; - } - return self; -} - -- (void)mask:(UIImage *)screenshot - completion:(void (^)(UIImage *))completion { - - __weak typeof(self) weakSelf = self; - - [self.flutterApi getPrivateViewsWithCompletion:^(NSArray *rectangles, FlutterError *error) { - [weakSelf handlePrivateViewsResult:rectangles - error:error - screenshot:screenshot - completion:completion]; - }]; -} - -#pragma mark - Private Methods - -// Handle the result of fetching private views -- (void)handlePrivateViewsResult:(NSArray *)rectangles - error:(FlutterError *)error - screenshot:(UIImage *)screenshot - completion:(void (^)(UIImage *))completion { - if (error) { - [self logError:error]; - completion(screenshot); - return; - } - - NSArray *privateViews = [self convertToRectangles:rectangles]; - UIImage *maskedScreenshot = [self drawMaskedImage:screenshot withPrivateViews:privateViews]; - completion(maskedScreenshot); - -} - -// Convert the raw rectangles array into CGRect values -- (NSArray *)convertToRectangles:(NSArray *)rectangles { - - NSMutableArray *privateViews = [NSMutableArray arrayWithCapacity:rectangles.count / 4]; - CGPoint flutterOrigin = [self getFlutterViewOrigin]; - - for (NSUInteger i = 0; i < rectangles.count; i += 4) { - CGFloat left = rectangles[i].doubleValue; - CGFloat top = rectangles[i + 1].doubleValue; - CGFloat right = rectangles[i + 2].doubleValue; - CGFloat bottom = rectangles[i + 3].doubleValue; - - CGRect rect = CGRectMake(flutterOrigin.x + left, - flutterOrigin.y + top, - right - left + 1, - bottom - top + 1); - [privateViews addObject:[NSValue valueWithCGRect:rect]]; - } - return privateViews; -} - -// Draw the masked image by filling private views with black rectangles -- (UIImage *)drawMaskedImage:(UIImage *)screenshot withPrivateViews:(NSArray *)privateViews { - UIGraphicsBeginImageContextWithOptions(screenshot.size, NO, 0); - CGContextRef context = UIGraphicsGetCurrentContext(); - - @try { - [screenshot drawAtPoint:CGPointZero]; - CGContextSetFillColorWithColor(context, UIColor.blackColor.CGColor); - - for (NSValue *value in privateViews) { - CGContextFillRect(context, value.CGRectValue); - } - - return UIGraphicsGetImageFromCurrentImageContext(); - } @finally { - UIGraphicsEndImageContext(); - } -} - -// Retrieve the origin point of the Flutter view -- (CGPoint)getFlutterViewOrigin { - FlutterViewController *flutterVC = (FlutterViewController *)self.flutterEngineRegistrar.flutterEngine.viewController; - - UIView *flutterView = flutterVC.view; - if(!flutterView) - return CGPointZero; - UIWindow *window = flutterView.window; - CGRect globalFrame = [flutterView convertRect:flutterView.bounds toView:window]; - - return globalFrame.origin ; -} - - -// Log error details -- (void)logError:(FlutterError *)error { - NSLog(@"IBG-Flutter: Error getting private views: %@", error.message); -} - - -@end diff --git a/packages/instabug_private_views/ios/Classes/PrivateViewHostApi.h b/packages/instabug_private_views/ios/Classes/PrivateViewHostApi.h deleted file mode 100644 index 54ced156c..000000000 --- a/packages/instabug_private_views/ios/Classes/PrivateViewHostApi.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "PrivateViewApi.h" -#import "InstabugPrivateViewPigeon.h" -extern void InitPrivateViewHostApi(id _Nonnull messenger, PrivateViewApi * _Nonnull api); - -@interface PrivateViewHostApi : NSObject -@property (nonatomic, strong) PrivateViewApi* _Nonnull privateViewApi; -@end diff --git a/packages/instabug_private_views/ios/Classes/PrivateViewHostApi.m b/packages/instabug_private_views/ios/Classes/PrivateViewHostApi.m deleted file mode 100644 index 6b1c26c4d..000000000 --- a/packages/instabug_private_views/ios/Classes/PrivateViewHostApi.m +++ /dev/null @@ -1,29 +0,0 @@ -// -// PrivateViewHostApi.m -// instabug_flutter -// -// Created by Ahmed alaa on 02/11/2024. -// - -#import "PrivateViewHostApi.h" -#import "instabug_flutter/InstabugApi.h" - -extern void InitPrivateViewHostApi(id _Nonnull messenger, PrivateViewApi * _Nonnull privateViewApi) { - PrivateViewHostApi *api = [[PrivateViewHostApi alloc] init]; - api.privateViewApi = privateViewApi; - InstabugPrivateViewHostApiSetup(messenger, api); -} - -@implementation PrivateViewHostApi - -- (void)initWithError:(FlutterError * _Nullable __autoreleasing * _Nonnull)error { - [InstabugApi setScreenshotMaskingHandler:^(UIImage * _Nonnull screenshot, void (^ _Nonnull completion)(UIImage * _Nullable)) { - [self.privateViewApi mask:screenshot completion:^(UIImage * _Nonnull maskedImage) { - if (maskedImage != nil) { - completion(maskedImage); - } - }]; - }]; -} - -@end diff --git a/packages/instabug_private_views/lib/src/repro_steps.dart b/packages/instabug_private_views/lib/src/repro_steps.dart index 285dcc71a..a17600d01 100644 --- a/packages/instabug_private_views/lib/src/repro_steps.dart +++ b/packages/instabug_private_views/lib/src/repro_steps.dart @@ -3,7 +3,7 @@ import 'package:instabug_private_views/src/private_views_manager.dart'; // ignore: avoid_classes_with_only_static_members class ReproSteps { - static void enablePrivateViews() { + static void enableMaskingPrivateViews() { final api = InstabugPrivateViewHostApi(); api.init(); InstabugPrivateViewFlutterApi.setup(PrivateViewsManager.I); diff --git a/packages/instabug_private_views/pubspec.lock b/packages/instabug_private_views/pubspec.lock index 5b677cdc6..d32834150 100644 --- a/packages/instabug_private_views/pubspec.lock +++ b/packages/instabug_private_views/pubspec.lock @@ -450,14 +450,6 @@ packages: url: "https://pub.dev" source: hosted version: "10.1.5" - plugin_platform_interface: - dependency: "direct main" - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" pool: dependency: transitive description: diff --git a/packages/instabug_private_views/pubspec.yaml b/packages/instabug_private_views/pubspec.yaml index 7c8ac4a01..60288d069 100644 --- a/packages/instabug_private_views/pubspec.yaml +++ b/packages/instabug_private_views/pubspec.yaml @@ -1,7 +1,9 @@ name: instabug_private_views -description: "An add-on for the Instabug Flutter SDK that provides private views support in screen capturing." -version: 1.0.0 +description: "An extension for the Instabug Flutter SDK that enables support for masking private views during screen capturing." +version: 1.0.1 homepage: https://www.instabug.com +repository: https://github.com/Instabug/Instabug-Flutter +documentation: https://docs.instabug.com/docs/flutter-overview environment: sdk: ">=2.14.0 <4.0.0" @@ -11,7 +13,6 @@ dependencies: flutter: sdk: flutter instabug_flutter: - plugin_platform_interface: ^2.0.2 dev_dependencies: build_runner: ^2.0.3 @@ -24,3 +25,12 @@ dev_dependencies: pana: ^0.21.0 # pigeon v3.0.0 is needed for running Flutter 2 tests on CI pigeon: '>=3.0.0 <=10.1.5' + +flutter: + plugin: + platforms: + android: + package: com.instabug.instabug_private_views + pluginClass: InstabugPrivateViewsPlugin + ios: + pluginClass: InstabugPrivateViewsPlugin \ No newline at end of file