From 7e41f2c6e4728810f548eeb0f8bd077b48253fe4 Mon Sep 17 00:00:00 2001 From: ahmed alaa <154802748+ahmedAlaaInstabug@users.noreply.github.com> Date: Thu, 14 Aug 2025 19:38:27 +0300 Subject: [PATCH 1/2] Refactor/monorepo2 (#623) * feat: add private view * feat: add private view * feat: add private view * feat: add private view * feat: add private view * feat: add private view * feat: add private view * feat: add private view android integration * feat: add private view android integration * feat: add private view android integration * refactor: make mono-repo * refactor: make mono-repo * refactor: make mono-repo * refactor: make mono-repo * refactor: make mono-repo * refactor: make mono-repo * refactor: make mono-repo * refactor: make mono-repo * refactor: make mono-repo * refactor: make mono-repo * refactor: make mono-repo * refactor: make mono-repo * refactor: make mono-repo * refactor: add http-package to mono-repo * refactor: add http-package to mono-repo * refactor: add http-package to mono-repo * refactor: add http-package to mono-repo * refactor: add http-package to mono-repo * refactor: add http-package to mono-repo * refactor: add dio interceptor to mono-repo * refactor: add dio interceptor to mono-repo * refactor: add modular plugin to mono-repo * refactor: add modular plugin to mono-repo * refactor: add modular plugin to mono-repo * refactor: add modular plugin to mono-repo * fix PR comments * fix: android test cases * fix: android test cases * fix PR comments * fix git ignore * rename: instabug_flutter * rename: instabug_flutter * doc:comment why not use const constructor * fix * feat(ios): handle private views (#524) * refactor: rename http client package * refactor: rename dio interceptor package * feat: add private view example page (#525) * feat: add private view page * fix private view screen * init * init * init * init * init * init * fix PR comment * fix PR comment * fix PR comment * add hybrid app * add hybrid app * add hybrid app * add more example in private view oage * add more example in private view oage * add more example in private view oage * chore: add build files * chore: add animation * fix: private view time * fix: private view time * feat: add w3c header * Refactor: monorepo v14.0.0 changes (#537) * refactor: monoRepo dev changes * refactor: monoRepo dev changes * feat : add w3c feature * feat : add w3c feature * chore: update to latest version * chore: update to latest version * chore: update to latest version * chore: update to latest version * chore: update to latest version * chore: update to latest version * chore: update to latest version * chore: update to latest version * fix same example name * monorepo * monorepo * monorepo * monorepo * monorepo * fix: android canvas crash * chore: rename enable private views * feat: user steps (#540) * feat: gestures & UI elements detection * testing * testing * testing * chore: update ios snapshot * format * format * format * chore(android): integrate with android snapshot * chore(ios): integrate with ios custom build * fix(android): passed required params to log user steps * fix(ios): add double tap event * feat(ios): add native user steps switch * fix(ios): pass flutter view name * feat(example): add private view test * fix: user steps parameters * chore(android): integrate private views snapshot * chore: cleanup unused params * fix(example): clean up imports * fix: update test cases * chore: update deps * fix(ios): update log user steps test case * fix: linters issues * fix(android): update test case * chore(android): activate commented code * chore(android): activate android test case * fix(ios): add double tap to test case * chore(ios): restore cocoapods version * chore(example): revert old app token * test * test * test * test * test * test * chore(android): add descriptive comment * chore(android): update snapshot * fix: PR comments * fix: PR comments * fix: ios CI * fix: ios CI * fix: ios CI * fix: ios CI * fix: ios CI * fix: android CI * fix: android CI * Update config.yml * fix: android CI * fix: android CI * fix: fix private view app * fix: extra space in message * chore(android): upgrade to latest snapshot * fix: trim message * feat: auto mask in Flutter (#555) * feat: enhance private view mechanism * fix: e2e test * fix test 2.10.0 * fix test 2.10.0 * fix test 2.10.0 * fix test 2.10.0 * fix test 2.10.0 * fix test 2.10.0 * fix test 2.10.0 * feat: enhance private view * fix test * fix test * fix test * fix test * fix test * fix: PR comments * chore: update example app * fix: masking sliver view * fix: masking sliver view * fix: masking sliver view * fix: masking sliver view * fix: flutter format * fix: format --------- Co-authored-by: kholood * fix: format * fix: format * fix: format * fix: format * Sanity/v16.0.0 (#621) * fix: add support for newer gradle versions (#512) * feat: attach w3c header (#481) * feat: add android feature flag * fix: test cases * fix: test cases * fix: test cases * fix: test cases * fix: add more test cases * fix: add more test cases * fix: add more test cases * fix: add more test cases * Release: v14.0.0 (#532) * chore(android): bump sdk to v14.0.0 * chore(ios): bump sdk to v14.0.0 * Release: v14.0.0 * Release: v14.0.0 * Release: v14.0.0 * chore: change release date (#535) * Release: v14.0.0 (#533) * fix: add support for newer gradle versions (#512) * feat: attach w3c header (#481) * feat: add android feature flag * fix: test cases * fix: test cases * fix: test cases * fix: test cases * fix: add more test cases * fix: add more test cases * fix: add more test cases * fix: add more test cases * Release: v14.0.0 (#532) * chore(android): bump sdk to v14.0.0 * chore(ios): bump sdk to v14.0.0 * Release: v14.0.0 * Release: v14.0.0 * Release: v14.0.0 * chore: change release date (#535) --------- Co-authored-by: kholood * Release: 14.1.0 (#539) * release: 14.1.0 * release: 14.1.0 * release: v14.1.0 * release: v14.1.0 * Release: v14.1.0 (#542) * fix: add support for newer gradle versions (#512) * feat: attach w3c header (#481) * feat: add android feature flag * fix: test cases * fix: test cases * fix: test cases * fix: test cases * fix: add more test cases * fix: add more test cases * fix: add more test cases * fix: add more test cases * Release: v14.0.0 (#532) * chore(android): bump sdk to v14.0.0 * chore(ios): bump sdk to v14.0.0 * Release: v14.0.0 * Release: v14.0.0 * Release: v14.0.0 * chore: change release date (#535) * Release: 14.1.0 (#539) * release: 14.1.0 * release: 14.1.0 * release: v14.1.0 * release: v14.1.0 --------- Co-authored-by: kholood * fix: set ReproStepsConfig on android * release: v14.1.0 * fix: set ReproStepsConfig * fix(android): report current view change * chore(android): update report current view test * chore(android): add report current view to mocked class * chore: Enhance inline code documentation * fix(android): fix test case * chore: Enhance inline code documentation * chore: increase the test coverage of APM related classes. * chore: apply dart format * chore: apply lint comments * chore: Integrate the absent APM APIs into the APM screen of the sample application. * chore: apply dart format * fix: e2e test * feat: support 3.29 * feat: enable/disable stop capturing network body * fix: add change log * Update CHANGELOG.md * feat: support 3.29 * feat: support 3.29 * feat: support 3.29 * feat: support 3.29 * ci: fix ci issue * chore: flutter sanity branch * fix: revert pod version * fix: use released versions * fix: changelog * fix: change log formate * fix: native fatal crash * chore: bump android version to 14.3.0 * Update CHANGELOG.md * Rlease: 14.3.0 * refactor: Replace APM API that uses reflection by a package private API * fix: network log unit test * feat: support BR adding user consents (#573) * feat: support BR adding user consents * feat: add change log * fix: android test * fix: use named parameters * fix: ios tests * Release: v14.3.1 (#577) * release: v14.3.1 * feat: support xcode 16 (#574) * feat: xcode 16 support * feat: xcode 16 support * feat: xcode 16 support * feat: xcode 16 support * feat: xcode 16 support * chore: update changelog --------- Co-authored-by: kholood * Revert "refactor: Replace APM API that uses reflection by a package private API" (#580) * Release/v15.0.1 (#581) * Revert "refactor: Replace APM API that uses reflection by a package private API" This reverts commit 55fba6dbf9fc0d9cf9a152d113ac2c485093ad83. * chore(ios): bump sdk to v.15.1.1 * chore(android): bump SDK to v15.0.1 * chore: bump sdk to v15.0.1 * chore:add change log item * Release: v14.3.1 (#577) (#588) * release: v14.3.1 Co-authored-by: Mohamed Zakaria El-Zoghbi <5540492+mzelzoghbi@users.noreply.github.com> Co-authored-by: ahmed alaa <154802748+ahmedAlaaInstabug@users.noreply.github.com> * Release: v14.3.1 (#577) (#589) * release: v14.3.1 Co-authored-by: Mohamed Zakaria El-Zoghbi <5540492+mzelzoghbi@users.noreply.github.com> Co-authored-by: ahmed alaa <154802748+ahmedAlaaInstabug@users.noreply.github.com> Co-authored-by: Ahmed alaa * Release: v14.3.1 (#577) (#591) * release: v14.3.1 Co-authored-by: Mohamed Zakaria El-Zoghbi <5540492+mzelzoghbi@users.noreply.github.com> * bump: android SDK to 15.0.2 (#594) * bump: android SDK to 15.0.2 * bump: android SDK to 15.0.2 * Merge pull request #597 from Instabug/release/androidv15.0.2 Release: v15.0.2 * feat: support app variant (#585) * feat: app variant * feat: app variant * feat: app variant * feat: app variant * feat: support advanced UI customization (#599) * feat: support advanced UI customization * chore: add change log * fix: delete setFullScreen * fix: linting * fix: unit test * fix: linting * fix: resolve comments * fix: add full screen function * fix: ios tests * fix: ios tests * chore: remove deprecated apis (#614) * feat: support advanced UI customization * chore: add change log * fix: delete setFullScreen * fix: linting * fix: unit test * fix: linting * fix: resolve comments * chore: remove deprecated apis * chore: add changelog * fix: setTheme calling * fix: formatte * fix: formate * fix: formatting * fix: ios tests * fix: ios tests * fix: e2e tests * fix: formate analyze * fix: e2e ios testing * fix: format --------- Co-authored-by: ahmed alaa <154802748+ahmedAlaaInstabug@users.noreply.github.com> --------- Co-authored-by: ahmed alaa <154802748+ahmedAlaaInstabug@users.noreply.github.com> * bump native SDKs to 16.0.0 * bump native SDKs to 16.0.0 * fix: merge issues * fix: merge issues * fix: analyze * fix: analyze * fix: analyze --------- Co-authored-by: Mohamed Zakaria El-Zoghbi <5540492+mzelzoghbi@users.noreply.github.com> Co-authored-by: kholood Co-authored-by: Andrew Amin Co-authored-by: Andrew Amin <160974398+AndrewAminInstabug@users.noreply.github.com> Co-authored-by: AyaMahmoud148 * fix: analyze * fix: analyze --------- Co-authored-by: kholood Co-authored-by: Mohamed Zakaria El-Zoghbi <5540492+mzelzoghbi@users.noreply.github.com> Co-authored-by: Andrew Amin Co-authored-by: Andrew Amin <160974398+AndrewAminInstabug@users.noreply.github.com> Co-authored-by: AyaMahmoud148 --- .circleci/config.yml | 262 +++-- .gitignore | 7 +- README.md | 127 +-- analysis_options.yaml | 5 +- dangerfile.ts | 30 +- e2e/.gitignore | 908 ++++++++--------- e2e/Utils/CaptainTest.cs | 30 +- melos.yaml | 82 ++ .../instabug_dio_interceptor/CHANGELOG.md | 55 + packages/instabug_dio_interceptor/LICENSE | 21 + packages/instabug_dio_interceptor/README.md | 17 + .../example/.metadata | 10 + .../example/README.md | 16 + .../example/android/.gitignore | 13 + .../example/android/app/build.gradle | 56 + .../android/app/src/debug/AndroidManifest.xml | 0 .../android/app/src/main/AndroidManifest.xml | 36 + .../app/FlutterMultiDexApplication.java | 25 + .../com/example/example/MainActivity.kt | 6 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin .../app/src/main/res/values-night/styles.xml | 18 + .../app/src/main/res/values/styles.xml | 18 + .../main/res/xml/network_security_config.xml | 13 + .../app/src/profile/AndroidManifest.xml | 0 .../example}/android/build.gradle | 0 .../example}/android/gradle.properties | 0 .../gradle/wrapper/gradle-wrapper.properties | 0 .../example}/android/settings.gradle | 0 .../example/ios/.gitignore | 34 + .../ios/Flutter/AppFrameworkInfo.plist | 26 + .../example/ios/Flutter/Debug.xcconfig | 2 + .../example/ios/Flutter/Release.xcconfig | 2 + .../example/ios/Podfile | 41 + .../ios/Runner.xcodeproj/project.pbxproj | 555 ++++++++++ .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/WorkspaceSettings.xcsettings | 0 .../xcshareddata/xcschemes/Runner.xcscheme | 87 ++ .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/WorkspaceSettings.xcsettings | 0 .../example/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 0 .../Icon-App-1024x1024@1x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin .../Icon-App-83.5x83.5@2x.png | Bin .../LaunchImage.imageset/Contents.json | 0 .../LaunchImage.imageset/LaunchImage.png | Bin .../LaunchImage.imageset/LaunchImage@2x.png | Bin .../LaunchImage.imageset/LaunchImage@3x.png | Bin .../LaunchImage.imageset/README.md | 0 .../Runner/Base.lproj/LaunchScreen.storyboard | 0 .../ios/Runner/Base.lproj/Main.storyboard | 0 .../example/ios/Runner/Info.plist | 51 + .../ios/Runner/Runner-Bridging-Header.h | 1 + .../example/lib/main.dart | 78 ++ .../example}/pubspec.lock | 107 +- .../example/pubspec.yaml | 25 + .../example/pubspec_overrides.yaml | 6 + .../lib/instabug_dio_interceptor.dart | 108 ++ .../instabug_dio_interceptor/pubspec.lock | 737 ++++++++++++++ .../instabug_dio_interceptor/pubspec.yaml | 60 ++ .../pubspec_overrides.yaml | 4 + packages/instabug_dio_interceptor/release.sh | 13 + .../test/instabug_dio_interceptor_test.dart | 116 +++ .../test/mock_adapter.dart | 43 + .../instabug_flutter/.metadata | 0 .../instabug_flutter/.pubignore | 0 .../instabug_flutter/CHANGELOG.md | 10 +- packages/instabug_flutter/Gemfile | 1 + packages/instabug_flutter/Gemfile.lock | 11 + LICENSE => packages/instabug_flutter/LICENSE | 0 packages/instabug_flutter/README.md | 116 +++ .../instabug_flutter/android}/.gitignore | 0 .../instabug_flutter/android}/build.gradle | 6 +- .../android}/gradle.properties | 0 .../gradle/wrapper/gradle-wrapper.properties | 0 .../android}/proguard-rules.txt | 0 .../instabug_flutter/android}/settings.gradle | 0 .../android}/src/main/AndroidManifest.xml | 0 .../flutter/InstabugFlutterPlugin.java | 23 + .../flutter/model/ScreenshotResult.java | 21 + .../com/instabug/flutter/modules/ApmApi.java | 0 .../flutter/modules/BugReportingApi.java | 0 .../flutter/modules/CrashReportingApi.java | 0 .../flutter/modules/FeatureRequestsApi.java | 0 .../instabug/flutter/modules/InstabugApi.java | 73 +- .../flutter/modules/InstabugLogApi.java | 0 .../flutter/modules/InstabugPrivateView.java | 47 + .../flutter/modules/PrivateViewManager.java | 147 +++ .../instabug/flutter/modules/RepliesApi.java | 0 .../flutter/modules/SessionReplayApi.java | 0 .../instabug/flutter/modules/SurveysApi.java | 0 .../capturing/BoundryCaptureManager.java | 43 + .../modules/capturing/CaptureManager.java | 7 + .../capturing/PixelCopyCaptureManager.java | 86 ++ .../capturing/ScreenshotResultCallback.java | 9 + .../instabug/flutter/util/ArgsRegistry.java | 19 + .../com/instabug/flutter/util/Reflection.java | 0 .../instabug/flutter/util/ThreadManager.java | 0 .../util/privateViews/ScreenshotCaptor.java | 13 + .../java/com/instabug/flutter/ApmApiTest.java | 0 .../instabug/flutter/ArgsRegistryTest.java | 0 .../instabug/flutter/BugReportingApiTest.java | 0 .../flutter/CrashReportingApiTest.java | 0 .../flutter/FeatureRequestsApiTest.java | 0 .../com/instabug/flutter/InstabugApiTest.java | 69 ++ .../instabug/flutter/InstabugLogApiTest.java | 0 .../com/instabug/flutter/RepliesApiTest.java | 0 .../flutter/SessionReplayApiTest.java | 0 .../com/instabug/flutter/SurveysApiTest.java | 0 .../com/instabug/flutter/util/Callback.java | 0 .../instabug/flutter/util/GlobalMocks.java | 8 + .../instabug/flutter/util/MockReflected.java | 3 + .../com/instabug/flutter/util/MockResult.java | 0 .../BoundryScreenshotCaptorTest.java | 77 ++ .../PixelCopyScreenshotCaptorTest.java | 91 ++ .../private_views/PrivateViewManagerTest.java | 146 +++ .../android}/upload_symbols.gradle | 0 packages/instabug_flutter/dangerfile.ts | 37 + .../instabug_flutter/example}/.gitignore | 0 .../instabug_flutter/example}/.metadata | 0 .../instabug_flutter/example}/README.md | 0 .../example}/android/.gitignore | 0 .../example}/android/app/build.gradle | 1 + .../android/app/src/debug/AndroidManifest.xml | 6 + .../android/app/src/main/AndroidManifest.xml | 0 .../InstabugExampleMethodCallHandler.kt | 0 .../example/InstabugSample/MainActivity.kt | 0 .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values/styles.xml | 0 .../main/res/xml/network_security_config.xml | 0 .../app/src/profile/AndroidManifest.xml | 6 + .../example/android/build.gradle | 21 + .../example/android/gradle.properties | 6 + .../android/gradle/wrapper/gradle-wrapper.jar | Bin .../gradle/wrapper/gradle-wrapper.properties | 6 + .../instabug_flutter/example}/android/gradlew | 0 .../example}/android/gradlew.bat | 180 ++-- .../example/android/settings.gradle | 27 + .../example}/android/settings_aar.gradle | 0 .../instabug_flutter/example/assets/img.png | Bin 0 -> 181305 bytes .../instabug_flutter/example}/ios/.gitignore | 0 .../ios/Flutter/AppFrameworkInfo.plist | 0 .../example}/ios/Flutter/Debug.xcconfig | 0 .../example}/ios/Flutter/Release.xcconfig | 0 .../example}/ios/InstabugTests/ApmApiTests.m | 0 .../ios/InstabugTests/ArgsRegistryTests.m | 0 .../ios/InstabugTests/BugReportingApiTests.m | 0 .../InstabugTests/CrashReportingApiTests.m | 0 .../InstabugTests/FeatureRequestsApiTests.m | 0 .../example}/ios/InstabugTests/Info.plist | 0 .../ios/InstabugTests/InstabugApiTests.m | 35 +- .../ios/InstabugTests/InstabugLogApiTests.m | 0 .../ios/InstabugTests/PrivateViewApiTests.m | 191 ++++ .../InstabugTests/PrivateViewHostApiTests.m | 57 ++ .../ios/InstabugTests/RepliesApiTests.m | 0 .../ios/InstabugTests/SessionReplayApiTests.m | 0 .../ios/InstabugTests/SurveysApiTests.m | 0 .../ios/InstabugTests/Util/Apm+Test.h | 0 .../InstabugTests/Util/IBGCrashReporting+CP.h | 0 .../Util/IBGNetworkLogger+Test.h | 0 .../ios/InstabugTests/Util/IBGSurvey+Test.h | 0 .../ios/InstabugTests/Util/Instabug+Test.h | 0 .../instabug_flutter/example}/ios/Podfile | 0 .../instabug_flutter/example/ios/Podfile.lock | 40 + .../ios/Runner.xcodeproj/project.pbxproj | 0 .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 0 .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../example}/ios/Runner/AppDelegate.swift | 0 .../AppIcon.appiconset/Contents.json | 122 +++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + .../example}/ios/Runner/Info.plist | 0 .../Runner/InstabugExampleMethodCallHandler.h | 0 .../Runner/InstabugExampleMethodCallHandler.m | 0 .../ios/Runner/Runner-Bridging-Header.h | 0 .../instabug_flutter/example}/lib/main.dart | 11 +- .../example}/lib/src/app_routes.dart | 0 .../lib/src/components/apm_switch.dart | 0 .../src/components/fatal_crashes_content.dart | 0 .../lib/src/components/flows_content.dart | 0 .../lib/src/components/network_content.dart | 10 +- .../components/non_fatal_crashes_content.dart | 0 .../example}/lib/src/components/page.dart | 0 ...stabug_flutter_example_method_channel.dart | 0 .../example}/lib/src/screens/apm_page.dart | 0 .../lib/src/screens/complex_page.dart | 0 .../lib/src/screens/crashes_page.dart | 0 .../lib/src/screens/my_home_page.dart | 44 +- .../lib/src/screens/private_view_page.dart | 258 +++++ ...reen_capture_premature_extension_page.dart | 0 .../lib/src/screens/screen_loading_page.dart | 0 .../lib/src/screens/user_steps_page.dart | 262 +++++ .../example}/lib/src/utils/show_messages.dart | 0 .../lib/src/widget/instabug_button.dart | 0 .../instabug_clipboard_icon_button.dart | 0 .../src/widget/instabug_clipboard_input.dart | 0 .../lib/src/widget/instabug_text_field.dart | 0 .../example}/lib/src/widget/nested_view.dart | 11 +- .../lib/src/widget/section_title.dart | 0 .../instabug_flutter/example/pubspec.lock | 370 +++++++ .../instabug_flutter/example}/pubspec.yaml | 2 +- .../example/pubspec_overrides.yaml | 6 + .../example}/test_driver/example.dart | 0 .../instabug_flutter/ios}/.gitignore | 0 .../instabug_flutter/ios}/Assets/.gitkeep | 0 .../ios}/Classes/InstabugFlutterPlugin.h | 0 .../ios}/Classes/InstabugFlutterPlugin.m | 5 + .../ios}/Classes/Modules/ApmApi.h | 0 .../ios}/Classes/Modules/ApmApi.m | 0 .../ios}/Classes/Modules/BugReportingApi.h | 0 .../ios}/Classes/Modules/BugReportingApi.m | 0 .../ios}/Classes/Modules/CrashReportingApi.h | 0 .../ios}/Classes/Modules/CrashReportingApi.m | 0 .../ios}/Classes/Modules/FeatureRequestsApi.h | 0 .../ios}/Classes/Modules/FeatureRequestsApi.m | 0 .../ios}/Classes/Modules/InstabugApi.h | 1 + .../ios}/Classes/Modules/InstabugApi.m | 44 +- .../ios}/Classes/Modules/InstabugLogApi.h | 0 .../ios}/Classes/Modules/InstabugLogApi.m | 0 .../ios/Classes/Modules/PrivateViewApi.h | 34 + .../ios/Classes/Modules/PrivateViewApi.m | 144 +++ .../ios/Classes/Modules/PrivateViewHostApi.h | 7 + .../ios/Classes/Modules/PrivateViewHostApi.m | 33 + .../ios}/Classes/Modules/RepliesApi.h | 0 .../ios}/Classes/Modules/RepliesApi.m | 0 .../ios}/Classes/Modules/SessionReplayApi.h | 0 .../ios}/Classes/Modules/SessionReplayApi.m | 0 .../ios}/Classes/Modules/SurveysApi.h | 0 .../ios}/Classes/Modules/SurveysApi.m | 0 .../ios}/Classes/Util/ArgsRegistry.h | 3 + .../ios}/Classes/Util/ArgsRegistry.m | 23 + .../FlutterPluginRegistrar+FlutterEngine.h | 8 + .../FlutterPluginRegistrar+FlutterEngine.m | 13 + .../ios}/Classes/Util/IBGAPM+PrivateAPIs.h | 0 .../ios}/Classes/Util/IBGCrashReporting+CP.h | 0 .../ios}/Classes/Util/IBGNetworkLogger+CP.h | 0 .../ios/Classes/Util/Instabug+CP.h | 9 + .../Util/NativeUtils/IBGTimeIntervalUnits.h | 0 .../ios}/instabug_flutter.podspec | 4 +- .../lib}/instabug_flutter.dart | 5 + .../lib}/src/models/crash_data.dart | 0 .../lib}/src/models/exception_data.dart | 0 .../lib}/src/models/feature_flag.dart | 0 .../lib}/src/models/generated_w3c_header.dart | 0 .../lib}/src/models/instabug_route.dart | 0 .../lib}/src/models/network_data.dart | 0 .../lib}/src/models/theme_config.dart | 0 .../lib}/src/models/trace_partial_id.dart | 0 .../lib}/src/models/w3c_feature_flags.dart | 0 .../lib}/src/models/w3c_header.dart | 0 .../lib}/src/modules/apm.dart | 0 .../lib}/src/modules/bug_reporting.dart | 2 +- .../lib}/src/modules/crash_reporting.dart | 0 .../lib}/src/modules/feature_requests.dart | 0 .../lib}/src/modules/instabug.dart | 37 +- .../lib}/src/modules/instabug_log.dart | 0 .../lib}/src/modules/network_logger.dart | 0 .../lib}/src/modules/replies.dart | 0 .../lib}/src/modules/session_replay.dart | 0 .../lib}/src/modules/surveys.dart | 0 .../lib}/src/utils/enum_converter.dart | 0 .../lib}/src/utils/feature_flags_manager.dart | 0 .../lib}/src/utils/ibg_build_info.dart | 0 .../lib}/src/utils/ibg_date_time.dart | 0 .../lib}/src/utils/instabug_logger.dart | 0 .../src/utils/instabug_montonic_clock.dart | 0 .../utils/instabug_navigator_observer.dart | 34 +- .../lib/src/utils/instabug_widget.dart | 60 ++ .../lib}/src/utils/iterable_ext.dart | 0 .../lib}/src/utils/network_manager.dart | 0 .../private_views/instabug_private_view.dart | 12 + .../instabug_sliver_private_view.dart | 14 + .../private_views/private_views_manager.dart | 180 ++++ .../lib}/src/utils/repro_steps_constants.dart | 0 .../utils/screen_loading/flags_config.dart | 0 .../instabug_capture_screen_loading.dart | 0 .../utils/screen_loading/route_matcher.dart | 0 .../screen_loading_manager.dart | 0 .../screen_loading/screen_loading_trace.dart | 0 .../src/utils/screen_loading/ui_trace.dart | 0 .../lib}/src/utils/screen_name_masker.dart | 0 .../utils/user_steps/instabug_user_steps.dart | 261 +++++ .../utils/user_steps/user_step_details.dart | 122 +++ .../src/utils/user_steps/widget_utils.dart | 223 ++++ .../lib}/src/utils/w3c_header_utils.dart | 0 packages/instabug_flutter/package.json | 9 + .../instabug_flutter/pigeons}/apm.api.dart | 0 .../pigeons}/bug_reporting.api.dart | 0 .../pigeons}/crash_reporting.api.dart | 0 .../pigeons}/feature_requests.api.dart | 0 .../pigeons}/instabug.api.dart | 12 +- .../pigeons}/instabug_log.api.dart | 0 .../pigeons/instabug_private_view.api.dart | 11 + .../pigeons}/replies.api.dart | 0 .../pigeons}/session_replay.api.dart | 0 .../pigeons}/surveys.api.dart | 0 packages/instabug_flutter/pubspec.lock | 717 +++++++++++++ packages/instabug_flutter/pubspec.yaml | 39 + .../instabug_flutter/scripts}/pigeon.sh | 0 .../instabug_flutter/test}/apm_test.dart | 0 .../test}/bug_reporting_test.dart | 0 .../test}/crash_reporting_test.dart | 0 .../test}/feature_flags_manager_test.dart | 0 .../test}/feature_requests_test.dart | 0 .../test}/instabug_log_test.dart | 0 .../instabug_flutter/test}/instabug_test.dart | 0 .../test}/network_data_test.dart | 0 .../test}/network_logger_test.dart | 0 .../test}/network_manager_test.dart | 0 .../instabug_flutter/test}/replies_test.dart | 0 .../test}/route_matcher_test.dart | 0 .../test}/session_replay_test.dart | 0 .../instabug_flutter/test}/surveys_test.dart | 0 .../instabug_navigator_observer_test.dart | 21 +- .../private_views_manager_test.dart | 161 +++ .../instabug_capture_screen_loading_test.dart | 0 .../screen_loading_manager_test.dart | 0 .../screen_loading_trace_test.dart | 0 .../utils/screen_loading/ui_trace_test.dart | 0 .../test}/utils/screen_name_masker_test.dart | 0 .../user_steps/instabug_user_steps_test.dart | 298 ++++++ .../user_steps/user_step_details_test.dart | 130 +++ .../utils/user_steps/widget_utils_test.dart | 111 ++ .../test}/w3_header_utils_test.dart | 0 packages/instabug_flutter/yarn.lock | 960 ++++++++++++++++++ packages/instabug_flutter_modular/.metadata | 10 + .../instabug_flutter_modular/CHANGELOG.md | 7 + packages/instabug_flutter_modular/LICENSE | 21 + packages/instabug_flutter_modular/README.md | 55 + .../example/.gitignore | 44 + .../example/android/.gitignore | 13 + .../example/android/app/build.gradle | 67 ++ .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 46 + .../app/FlutterMultiDexApplication.java | 25 + .../flutter_modular_demo_app/MainActivity.kt | 5 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 + .../app/src/main/res/values/styles.xml | 18 + .../main/res/xml/network_security_config.xml | 12 + .../app/src/profile/AndroidManifest.xml | 7 + .../example/android/build.gradle | 18 + .../example/android/gradle.properties | 6 + .../gradle/wrapper/gradle-wrapper.properties | 5 + .../example/android/settings.gradle | 26 + .../example/ios/.gitignore | 34 + .../ios/Flutter/AppFrameworkInfo.plist | 26 + .../example/ios/Flutter/Debug.xcconfig | 2 + .../example/ios/Flutter/Release.xcconfig | 2 + .../example/ios/Podfile | 44 + .../example}/ios/Podfile.lock | 0 .../ios/Runner.xcodeproj/project.pbxproj | 728 +++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 98 ++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../example/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 +++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 295 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 450 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 282 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 462 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 704 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 586 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 1674 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 762 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 1226 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 1418 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + .../example/ios/Runner/Info.plist | 49 + .../ios/Runner/Runner-Bridging-Header.h | 1 + .../example/ios/RunnerTests/RunnerTests.swift | 12 + .../example/lib/main.dart | 54 + .../example/lib/modules.dart | 9 + .../example/lib/modules/app_module.dart | 20 + .../example/lib/modules/second_module.dart | 31 + .../example/lib/modules/third_module.dart | 21 + .../example/lib/screens.dart | 17 + .../example/lib/screens/complex_page.dart | 95 ++ .../example/lib/screens/home_page.dart | 109 ++ .../example/lib/screens/not_found_page.dart | 18 + .../lib/screens/second_module_home_page.dart | 66 ++ .../example/lib/screens/simple_page.dart | 58 ++ .../lib/screens/third_module_home_page.dart | 50 + .../example/lib/widgets.dart | 38 + .../example/pubspec.lock | 259 +++++ .../example/pubspec.yaml | 93 ++ .../example/pubspec_overrides.yaml | 6 + .../lib/instabug_flutter_modular.dart | 1 + .../lib/src/instabug_modular_manager.dart | 76 ++ .../lib/src/instabug_module.dart | 28 + .../instabug_flutter_modular/pubspec.lock | 753 ++++++++++++++ .../instabug_flutter_modular/pubspec.yaml | 27 + .../pubspec_overrides.yaml | 4 + packages/instabug_flutter_modular/release.sh | 13 + .../src/instabug_modular_manager_test.dart | 201 ++++ packages/instabug_http_client/CHANGELOG.md | 49 + packages/instabug_http_client/LICENSE | 21 + packages/instabug_http_client/README.md | 36 + .../instabug_http_client/example/.metadata | 10 + .../instabug_http_client/example/README.md | 16 + .../example}/analysis_options.yaml | 3 +- .../example/android/.gitignore | 13 + .../example/android/app/build.gradle | 56 + .../android/app/src/debug/AndroidManifest.xml | 6 + .../android/app/src/main/AndroidManifest.xml | 36 + .../app/FlutterMultiDexApplication.java | 20 + .../com/example/example/MainActivity.kt | 6 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 + .../app/src/main/res/values/styles.xml | 18 + .../main/res/xml/network_security_config.xml | 13 + .../app/src/profile/AndroidManifest.xml | 6 + .../example/android/build.gradle | 15 + .../example/android/gradle.properties | 6 + .../gradle/wrapper/gradle-wrapper.properties | 6 + .../example/android/settings.gradle | 27 + .../example/ios/.gitignore | 34 + .../ios/Flutter/AppFrameworkInfo.plist | 26 + .../example/ios/Flutter/Debug.xcconfig | 2 + .../example/ios/Flutter/Release.xcconfig | 2 + .../instabug_http_client/example/ios/Podfile | 41 + .../ios/Runner.xcodeproj/project.pbxproj | 555 ++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 87 ++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../example/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 +++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + .../example/ios/Runner/Info.plist | 51 + .../ios/Runner/Runner-Bridging-Header.h | 1 + .../example/lib/main.dart | 73 ++ .../instabug_http_client/example/pubspec.lock | 251 +++++ .../instabug_http_client/example/pubspec.yaml | 24 + .../example/pubspec_overrides.yaml | 6 + .../lib/instabug_http_client.dart | 177 ++++ .../lib/instabug_http_logger.dart | 76 ++ packages/instabug_http_client/pubspec.lock | 620 +++++++++++ packages/instabug_http_client/pubspec.yaml | 29 + .../pubspec_overrides.yaml | 4 + packages/instabug_http_client/release.sh | 13 + .../test/instabug_http_client_test.dart | 207 ++++ pubspec.yaml | 42 +- scripts/init.sh | 47 + scripts/move_coverage_files.sh | 13 + 546 files changed, 16411 insertions(+), 912 deletions(-) create mode 100644 melos.yaml create mode 100644 packages/instabug_dio_interceptor/CHANGELOG.md create mode 100644 packages/instabug_dio_interceptor/LICENSE create mode 100644 packages/instabug_dio_interceptor/README.md create mode 100644 packages/instabug_dio_interceptor/example/.metadata create mode 100644 packages/instabug_dio_interceptor/example/README.md create mode 100644 packages/instabug_dio_interceptor/example/android/.gitignore create mode 100644 packages/instabug_dio_interceptor/example/android/app/build.gradle rename {example => packages/instabug_dio_interceptor/example}/android/app/src/debug/AndroidManifest.xml (100%) create mode 100644 packages/instabug_dio_interceptor/example/android/app/src/main/AndroidManifest.xml create mode 100644 packages/instabug_dio_interceptor/example/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java create mode 100644 packages/instabug_dio_interceptor/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt create mode 100644 packages/instabug_dio_interceptor/example/android/app/src/main/res/drawable-v21/launch_background.xml rename {example => packages/instabug_dio_interceptor/example}/android/app/src/main/res/drawable/launch_background.xml (100%) rename {example => packages/instabug_dio_interceptor/example}/android/app/src/main/res/mipmap-hdpi/ic_launcher.png (100%) rename {example => packages/instabug_dio_interceptor/example}/android/app/src/main/res/mipmap-mdpi/ic_launcher.png (100%) rename {example => packages/instabug_dio_interceptor/example}/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png (100%) rename {example => packages/instabug_dio_interceptor/example}/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png (100%) rename {example => packages/instabug_dio_interceptor/example}/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png (100%) create mode 100644 packages/instabug_dio_interceptor/example/android/app/src/main/res/values-night/styles.xml create mode 100644 packages/instabug_dio_interceptor/example/android/app/src/main/res/values/styles.xml create mode 100644 packages/instabug_dio_interceptor/example/android/app/src/main/res/xml/network_security_config.xml rename {example => packages/instabug_dio_interceptor/example}/android/app/src/profile/AndroidManifest.xml (100%) rename {example => packages/instabug_dio_interceptor/example}/android/build.gradle (100%) rename {example => packages/instabug_dio_interceptor/example}/android/gradle.properties (100%) rename {example => packages/instabug_dio_interceptor/example}/android/gradle/wrapper/gradle-wrapper.properties (100%) rename {example => packages/instabug_dio_interceptor/example}/android/settings.gradle (100%) create mode 100644 packages/instabug_dio_interceptor/example/ios/.gitignore create mode 100644 packages/instabug_dio_interceptor/example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 packages/instabug_dio_interceptor/example/ios/Flutter/Debug.xcconfig create mode 100644 packages/instabug_dio_interceptor/example/ios/Flutter/Release.xcconfig create mode 100644 packages/instabug_dio_interceptor/example/ios/Podfile create mode 100644 packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/project.pbxproj rename {example => packages/instabug_dio_interceptor/example}/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (100%) create mode 100644 packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme rename {example => packages/instabug_dio_interceptor/example}/ios/Runner.xcworkspace/contents.xcworkspacedata (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (100%) create mode 100644 packages/instabug_dio_interceptor/example/ios/Runner/AppDelegate.swift rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Base.lproj/LaunchScreen.storyboard (100%) rename {example => packages/instabug_dio_interceptor/example}/ios/Runner/Base.lproj/Main.storyboard (100%) create mode 100644 packages/instabug_dio_interceptor/example/ios/Runner/Info.plist create mode 100644 packages/instabug_dio_interceptor/example/ios/Runner/Runner-Bridging-Header.h create mode 100644 packages/instabug_dio_interceptor/example/lib/main.dart rename {example => packages/instabug_dio_interceptor/example}/pubspec.lock (83%) create mode 100644 packages/instabug_dio_interceptor/example/pubspec.yaml create mode 100644 packages/instabug_dio_interceptor/example/pubspec_overrides.yaml create mode 100644 packages/instabug_dio_interceptor/lib/instabug_dio_interceptor.dart create mode 100644 packages/instabug_dio_interceptor/pubspec.lock create mode 100644 packages/instabug_dio_interceptor/pubspec.yaml create mode 100644 packages/instabug_dio_interceptor/pubspec_overrides.yaml create mode 100755 packages/instabug_dio_interceptor/release.sh create mode 100644 packages/instabug_dio_interceptor/test/instabug_dio_interceptor_test.dart create mode 100644 packages/instabug_dio_interceptor/test/mock_adapter.dart rename .metadata => packages/instabug_flutter/.metadata (100%) rename .pubignore => packages/instabug_flutter/.pubignore (100%) rename CHANGELOG.md => packages/instabug_flutter/CHANGELOG.md (97%) create mode 100644 packages/instabug_flutter/Gemfile create mode 100644 packages/instabug_flutter/Gemfile.lock rename LICENSE => packages/instabug_flutter/LICENSE (100%) create mode 100644 packages/instabug_flutter/README.md rename {android => packages/instabug_flutter/android}/.gitignore (100%) rename {android => packages/instabug_flutter/android}/build.gradle (91%) rename {android => packages/instabug_flutter/android}/gradle.properties (100%) rename {android => packages/instabug_flutter/android}/gradle/wrapper/gradle-wrapper.properties (100%) rename {android => packages/instabug_flutter/android}/proguard-rules.txt (100%) rename {android => packages/instabug_flutter/android}/settings.gradle (100%) rename {android => packages/instabug_flutter/android}/src/main/AndroidManifest.xml (100%) rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java (78%) create mode 100644 packages/instabug_flutter/android/src/main/java/com/instabug/flutter/model/ScreenshotResult.java rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/modules/ApmApi.java (100%) rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/modules/BugReportingApi.java (100%) rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/modules/CrashReportingApi.java (100%) rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/modules/FeatureRequestsApi.java (100%) rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/modules/InstabugApi.java (89%) rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/modules/InstabugLogApi.java (100%) create mode 100644 packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugPrivateView.java create mode 100644 packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/PrivateViewManager.java rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/modules/RepliesApi.java (100%) rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/modules/SessionReplayApi.java (100%) rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/modules/SurveysApi.java (100%) create mode 100644 packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/BoundryCaptureManager.java create mode 100644 packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/CaptureManager.java create mode 100644 packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/PixelCopyCaptureManager.java create mode 100644 packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/ScreenshotResultCallback.java rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/util/ArgsRegistry.java (94%) rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/util/Reflection.java (100%) rename {android => packages/instabug_flutter/android}/src/main/java/com/instabug/flutter/util/ThreadManager.java (100%) create mode 100644 packages/instabug_flutter/android/src/main/java/com/instabug/flutter/util/privateViews/ScreenshotCaptor.java rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/ApmApiTest.java (100%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/ArgsRegistryTest.java (100%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/BugReportingApiTest.java (100%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/CrashReportingApiTest.java (100%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/FeatureRequestsApiTest.java (100%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/InstabugApiTest.java (90%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/InstabugLogApiTest.java (100%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/RepliesApiTest.java (100%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/SessionReplayApiTest.java (100%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/SurveysApiTest.java (100%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/util/Callback.java (100%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/util/GlobalMocks.java (93%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/util/MockReflected.java (92%) rename {android => packages/instabug_flutter/android}/src/test/java/com/instabug/flutter/util/MockResult.java (100%) create mode 100644 packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/private_views/BoundryScreenshotCaptorTest.java create mode 100644 packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/private_views/PixelCopyScreenshotCaptorTest.java create mode 100644 packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/private_views/PrivateViewManagerTest.java rename {android => packages/instabug_flutter/android}/upload_symbols.gradle (100%) create mode 100644 packages/instabug_flutter/dangerfile.ts rename {example => packages/instabug_flutter/example}/.gitignore (100%) rename {example => packages/instabug_flutter/example}/.metadata (100%) rename {example => packages/instabug_flutter/example}/README.md (100%) rename {example => packages/instabug_flutter/example}/android/.gitignore (100%) rename {example => packages/instabug_flutter/example}/android/app/build.gradle (99%) create mode 100644 packages/instabug_flutter/example/android/app/src/debug/AndroidManifest.xml rename {example => packages/instabug_flutter/example}/android/app/src/main/AndroidManifest.xml (100%) rename {example => packages/instabug_flutter/example}/android/app/src/main/kotlin/com/example/InstabugSample/InstabugExampleMethodCallHandler.kt (100%) rename {example => packages/instabug_flutter/example}/android/app/src/main/kotlin/com/example/InstabugSample/MainActivity.kt (100%) create mode 100644 packages/instabug_flutter/example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 packages/instabug_flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 packages/instabug_flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 packages/instabug_flutter/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 packages/instabug_flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 packages/instabug_flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename {example => packages/instabug_flutter/example}/android/app/src/main/res/values/styles.xml (100%) rename {example => packages/instabug_flutter/example}/android/app/src/main/res/xml/network_security_config.xml (100%) create mode 100644 packages/instabug_flutter/example/android/app/src/profile/AndroidManifest.xml create mode 100644 packages/instabug_flutter/example/android/build.gradle create mode 100644 packages/instabug_flutter/example/android/gradle.properties rename {example => packages/instabug_flutter/example}/android/gradle/wrapper/gradle-wrapper.jar (100%) create mode 100644 packages/instabug_flutter/example/android/gradle/wrapper/gradle-wrapper.properties rename {example => packages/instabug_flutter/example}/android/gradlew (100%) rename {example => packages/instabug_flutter/example}/android/gradlew.bat (96%) create mode 100644 packages/instabug_flutter/example/android/settings.gradle rename {example => packages/instabug_flutter/example}/android/settings_aar.gradle (100%) create mode 100644 packages/instabug_flutter/example/assets/img.png rename {example => packages/instabug_flutter/example}/ios/.gitignore (100%) rename {example => packages/instabug_flutter/example}/ios/Flutter/AppFrameworkInfo.plist (100%) rename {example => packages/instabug_flutter/example}/ios/Flutter/Debug.xcconfig (100%) rename {example => packages/instabug_flutter/example}/ios/Flutter/Release.xcconfig (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/ApmApiTests.m (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/ArgsRegistryTests.m (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/BugReportingApiTests.m (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/CrashReportingApiTests.m (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/FeatureRequestsApiTests.m (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/Info.plist (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/InstabugApiTests.m (95%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/InstabugLogApiTests.m (100%) create mode 100644 packages/instabug_flutter/example/ios/InstabugTests/PrivateViewApiTests.m create mode 100644 packages/instabug_flutter/example/ios/InstabugTests/PrivateViewHostApiTests.m rename {example => packages/instabug_flutter/example}/ios/InstabugTests/RepliesApiTests.m (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/SessionReplayApiTests.m (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/SurveysApiTests.m (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/Util/Apm+Test.h (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/Util/IBGCrashReporting+CP.h (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/Util/IBGNetworkLogger+Test.h (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/Util/IBGSurvey+Test.h (100%) rename {example => packages/instabug_flutter/example}/ios/InstabugTests/Util/Instabug+Test.h (100%) rename {example => packages/instabug_flutter/example}/ios/Podfile (100%) create mode 100644 packages/instabug_flutter/example/ios/Podfile.lock rename {example => packages/instabug_flutter/example}/ios/Runner.xcodeproj/project.pbxproj (100%) create mode 100644 packages/instabug_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/instabug_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/instabug_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename {example => packages/instabug_flutter/example}/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (100%) create mode 100644 packages/instabug_flutter/example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/instabug_flutter/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/instabug_flutter/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename {example => packages/instabug_flutter/example}/ios/Runner/AppDelegate.swift (100%) create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 packages/instabug_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 packages/instabug_flutter/example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 packages/instabug_flutter/example/ios/Runner/Base.lproj/Main.storyboard rename {example => packages/instabug_flutter/example}/ios/Runner/Info.plist (100%) rename {example => packages/instabug_flutter/example}/ios/Runner/InstabugExampleMethodCallHandler.h (100%) rename {example => packages/instabug_flutter/example}/ios/Runner/InstabugExampleMethodCallHandler.m (100%) rename {example => packages/instabug_flutter/example}/ios/Runner/Runner-Bridging-Header.h (100%) rename {example => packages/instabug_flutter/example}/lib/main.dart (85%) rename {example => packages/instabug_flutter/example}/lib/src/app_routes.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/components/apm_switch.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/components/fatal_crashes_content.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/components/flows_content.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/components/network_content.dart (89%) rename {example => packages/instabug_flutter/example}/lib/src/components/non_fatal_crashes_content.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/components/page.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/native/instabug_flutter_example_method_channel.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/screens/apm_page.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/screens/complex_page.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/screens/crashes_page.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/screens/my_home_page.dart (91%) create mode 100644 packages/instabug_flutter/example/lib/src/screens/private_view_page.dart rename {example => packages/instabug_flutter/example}/lib/src/screens/screen_capture_premature_extension_page.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/screens/screen_loading_page.dart (100%) create mode 100644 packages/instabug_flutter/example/lib/src/screens/user_steps_page.dart rename {example => packages/instabug_flutter/example}/lib/src/utils/show_messages.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/widget/instabug_button.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/widget/instabug_clipboard_icon_button.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/widget/instabug_clipboard_input.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/widget/instabug_text_field.dart (100%) rename {example => packages/instabug_flutter/example}/lib/src/widget/nested_view.dart (77%) rename {example => packages/instabug_flutter/example}/lib/src/widget/section_title.dart (100%) create mode 100644 packages/instabug_flutter/example/pubspec.lock rename {example => packages/instabug_flutter/example}/pubspec.yaml (99%) create mode 100644 packages/instabug_flutter/example/pubspec_overrides.yaml rename {example => packages/instabug_flutter/example}/test_driver/example.dart (100%) rename {ios => packages/instabug_flutter/ios}/.gitignore (100%) rename {ios => packages/instabug_flutter/ios}/Assets/.gitkeep (100%) rename {ios => packages/instabug_flutter/ios}/Classes/InstabugFlutterPlugin.h (100%) rename {ios => packages/instabug_flutter/ios}/Classes/InstabugFlutterPlugin.m (74%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/ApmApi.h (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/ApmApi.m (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/BugReportingApi.h (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/BugReportingApi.m (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/CrashReportingApi.h (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/CrashReportingApi.m (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/FeatureRequestsApi.h (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/FeatureRequestsApi.m (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/InstabugApi.h (70%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/InstabugApi.m (93%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/InstabugLogApi.h (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/InstabugLogApi.m (100%) create mode 100644 packages/instabug_flutter/ios/Classes/Modules/PrivateViewApi.h create mode 100644 packages/instabug_flutter/ios/Classes/Modules/PrivateViewApi.m create mode 100644 packages/instabug_flutter/ios/Classes/Modules/PrivateViewHostApi.h create mode 100644 packages/instabug_flutter/ios/Classes/Modules/PrivateViewHostApi.m rename {ios => packages/instabug_flutter/ios}/Classes/Modules/RepliesApi.h (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/RepliesApi.m (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/SessionReplayApi.h (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/SessionReplayApi.m (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/SurveysApi.h (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Modules/SurveysApi.m (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Util/ArgsRegistry.h (91%) rename {ios => packages/instabug_flutter/ios}/Classes/Util/ArgsRegistry.m (93%) create mode 100644 packages/instabug_flutter/ios/Classes/Util/FlutterPluginRegistrar+FlutterEngine.h create mode 100644 packages/instabug_flutter/ios/Classes/Util/FlutterPluginRegistrar+FlutterEngine.m rename {ios => packages/instabug_flutter/ios}/Classes/Util/IBGAPM+PrivateAPIs.h (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Util/IBGCrashReporting+CP.h (100%) rename {ios => packages/instabug_flutter/ios}/Classes/Util/IBGNetworkLogger+CP.h (100%) create mode 100644 packages/instabug_flutter/ios/Classes/Util/Instabug+CP.h rename {ios => packages/instabug_flutter/ios}/Classes/Util/NativeUtils/IBGTimeIntervalUnits.h (100%) rename {ios => packages/instabug_flutter/ios}/instabug_flutter.podspec (92%) rename {lib => packages/instabug_flutter/lib}/instabug_flutter.dart (74%) rename {lib => packages/instabug_flutter/lib}/src/models/crash_data.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/models/exception_data.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/models/feature_flag.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/models/generated_w3c_header.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/models/instabug_route.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/models/network_data.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/models/theme_config.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/models/trace_partial_id.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/models/w3c_feature_flags.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/models/w3c_header.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/modules/apm.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/modules/bug_reporting.dart (99%) rename {lib => packages/instabug_flutter/lib}/src/modules/crash_reporting.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/modules/feature_requests.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/modules/instabug.dart (96%) rename {lib => packages/instabug_flutter/lib}/src/modules/instabug_log.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/modules/network_logger.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/modules/replies.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/modules/session_replay.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/modules/surveys.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/enum_converter.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/feature_flags_manager.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/ibg_build_info.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/ibg_date_time.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/instabug_logger.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/instabug_montonic_clock.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/instabug_navigator_observer.dart (66%) create mode 100644 packages/instabug_flutter/lib/src/utils/instabug_widget.dart rename {lib => packages/instabug_flutter/lib}/src/utils/iterable_ext.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/network_manager.dart (100%) create mode 100644 packages/instabug_flutter/lib/src/utils/private_views/instabug_private_view.dart create mode 100644 packages/instabug_flutter/lib/src/utils/private_views/instabug_sliver_private_view.dart create mode 100644 packages/instabug_flutter/lib/src/utils/private_views/private_views_manager.dart rename {lib => packages/instabug_flutter/lib}/src/utils/repro_steps_constants.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/screen_loading/flags_config.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/screen_loading/instabug_capture_screen_loading.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/screen_loading/route_matcher.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/screen_loading/screen_loading_manager.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/screen_loading/screen_loading_trace.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/screen_loading/ui_trace.dart (100%) rename {lib => packages/instabug_flutter/lib}/src/utils/screen_name_masker.dart (100%) create mode 100644 packages/instabug_flutter/lib/src/utils/user_steps/instabug_user_steps.dart create mode 100644 packages/instabug_flutter/lib/src/utils/user_steps/user_step_details.dart create mode 100644 packages/instabug_flutter/lib/src/utils/user_steps/widget_utils.dart rename {lib => packages/instabug_flutter/lib}/src/utils/w3c_header_utils.dart (100%) create mode 100644 packages/instabug_flutter/package.json rename {pigeons => packages/instabug_flutter/pigeons}/apm.api.dart (100%) rename {pigeons => packages/instabug_flutter/pigeons}/bug_reporting.api.dart (100%) rename {pigeons => packages/instabug_flutter/pigeons}/crash_reporting.api.dart (100%) rename {pigeons => packages/instabug_flutter/pigeons}/feature_requests.api.dart (100%) rename {pigeons => packages/instabug_flutter/pigeons}/instabug.api.dart (91%) rename {pigeons => packages/instabug_flutter/pigeons}/instabug_log.api.dart (100%) create mode 100644 packages/instabug_flutter/pigeons/instabug_private_view.api.dart rename {pigeons => packages/instabug_flutter/pigeons}/replies.api.dart (100%) rename {pigeons => packages/instabug_flutter/pigeons}/session_replay.api.dart (100%) rename {pigeons => packages/instabug_flutter/pigeons}/surveys.api.dart (100%) create mode 100644 packages/instabug_flutter/pubspec.lock create mode 100644 packages/instabug_flutter/pubspec.yaml rename {scripts => packages/instabug_flutter/scripts}/pigeon.sh (100%) rename {test => packages/instabug_flutter/test}/apm_test.dart (100%) rename {test => packages/instabug_flutter/test}/bug_reporting_test.dart (100%) rename {test => packages/instabug_flutter/test}/crash_reporting_test.dart (100%) rename {test => packages/instabug_flutter/test}/feature_flags_manager_test.dart (100%) rename {test => packages/instabug_flutter/test}/feature_requests_test.dart (100%) rename {test => packages/instabug_flutter/test}/instabug_log_test.dart (100%) rename {test => packages/instabug_flutter/test}/instabug_test.dart (100%) rename {test => packages/instabug_flutter/test}/network_data_test.dart (100%) rename {test => packages/instabug_flutter/test}/network_logger_test.dart (100%) rename {test => packages/instabug_flutter/test}/network_manager_test.dart (100%) rename {test => packages/instabug_flutter/test}/replies_test.dart (100%) rename {test => packages/instabug_flutter/test}/route_matcher_test.dart (100%) rename {test => packages/instabug_flutter/test}/session_replay_test.dart (100%) rename {test => packages/instabug_flutter/test}/surveys_test.dart (100%) rename {test => packages/instabug_flutter/test}/utils/instabug_navigator_observer_test.dart (82%) create mode 100644 packages/instabug_flutter/test/utils/private_views/private_views_manager_test.dart rename {test => packages/instabug_flutter/test}/utils/screen_loading/instabug_capture_screen_loading_test.dart (100%) rename {test => packages/instabug_flutter/test}/utils/screen_loading/screen_loading_manager_test.dart (100%) rename {test => packages/instabug_flutter/test}/utils/screen_loading/screen_loading_trace_test.dart (100%) rename {test => packages/instabug_flutter/test}/utils/screen_loading/ui_trace_test.dart (100%) rename {test => packages/instabug_flutter/test}/utils/screen_name_masker_test.dart (100%) create mode 100644 packages/instabug_flutter/test/utils/user_steps/instabug_user_steps_test.dart create mode 100644 packages/instabug_flutter/test/utils/user_steps/user_step_details_test.dart create mode 100644 packages/instabug_flutter/test/utils/user_steps/widget_utils_test.dart rename {test => packages/instabug_flutter/test}/w3_header_utils_test.dart (100%) create mode 100644 packages/instabug_flutter/yarn.lock create mode 100644 packages/instabug_flutter_modular/.metadata create mode 100644 packages/instabug_flutter_modular/CHANGELOG.md create mode 100644 packages/instabug_flutter_modular/LICENSE create mode 100644 packages/instabug_flutter_modular/README.md create mode 100644 packages/instabug_flutter_modular/example/.gitignore create mode 100644 packages/instabug_flutter_modular/example/android/.gitignore create mode 100644 packages/instabug_flutter_modular/example/android/app/build.gradle create mode 100644 packages/instabug_flutter_modular/example/android/app/src/debug/AndroidManifest.xml create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/AndroidManifest.xml create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/kotlin/com/example/flutter_modular_demo_app/MainActivity.kt create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/res/values-night/styles.xml create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/res/values/styles.xml create mode 100644 packages/instabug_flutter_modular/example/android/app/src/main/res/xml/network_security_config.xml create mode 100644 packages/instabug_flutter_modular/example/android/app/src/profile/AndroidManifest.xml create mode 100644 packages/instabug_flutter_modular/example/android/build.gradle create mode 100644 packages/instabug_flutter_modular/example/android/gradle.properties create mode 100644 packages/instabug_flutter_modular/example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 packages/instabug_flutter_modular/example/android/settings.gradle create mode 100644 packages/instabug_flutter_modular/example/ios/.gitignore create mode 100644 packages/instabug_flutter_modular/example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 packages/instabug_flutter_modular/example/ios/Flutter/Debug.xcconfig create mode 100644 packages/instabug_flutter_modular/example/ios/Flutter/Release.xcconfig create mode 100644 packages/instabug_flutter_modular/example/ios/Podfile rename {example => packages/instabug_flutter_modular/example}/ios/Podfile.lock (100%) create mode 100644 packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/instabug_flutter_modular/example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/instabug_flutter_modular/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/instabug_flutter_modular/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/AppDelegate.swift create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Info.plist create mode 100644 packages/instabug_flutter_modular/example/ios/Runner/Runner-Bridging-Header.h create mode 100644 packages/instabug_flutter_modular/example/ios/RunnerTests/RunnerTests.swift create mode 100644 packages/instabug_flutter_modular/example/lib/main.dart create mode 100644 packages/instabug_flutter_modular/example/lib/modules.dart create mode 100644 packages/instabug_flutter_modular/example/lib/modules/app_module.dart create mode 100644 packages/instabug_flutter_modular/example/lib/modules/second_module.dart create mode 100644 packages/instabug_flutter_modular/example/lib/modules/third_module.dart create mode 100644 packages/instabug_flutter_modular/example/lib/screens.dart create mode 100644 packages/instabug_flutter_modular/example/lib/screens/complex_page.dart create mode 100644 packages/instabug_flutter_modular/example/lib/screens/home_page.dart create mode 100644 packages/instabug_flutter_modular/example/lib/screens/not_found_page.dart create mode 100644 packages/instabug_flutter_modular/example/lib/screens/second_module_home_page.dart create mode 100644 packages/instabug_flutter_modular/example/lib/screens/simple_page.dart create mode 100644 packages/instabug_flutter_modular/example/lib/screens/third_module_home_page.dart create mode 100644 packages/instabug_flutter_modular/example/lib/widgets.dart create mode 100644 packages/instabug_flutter_modular/example/pubspec.lock create mode 100644 packages/instabug_flutter_modular/example/pubspec.yaml create mode 100644 packages/instabug_flutter_modular/example/pubspec_overrides.yaml create mode 100644 packages/instabug_flutter_modular/lib/instabug_flutter_modular.dart create mode 100644 packages/instabug_flutter_modular/lib/src/instabug_modular_manager.dart create mode 100644 packages/instabug_flutter_modular/lib/src/instabug_module.dart create mode 100644 packages/instabug_flutter_modular/pubspec.lock create mode 100644 packages/instabug_flutter_modular/pubspec.yaml create mode 100644 packages/instabug_flutter_modular/pubspec_overrides.yaml create mode 100755 packages/instabug_flutter_modular/release.sh create mode 100644 packages/instabug_flutter_modular/test/src/instabug_modular_manager_test.dart create mode 100644 packages/instabug_http_client/CHANGELOG.md create mode 100644 packages/instabug_http_client/LICENSE create mode 100644 packages/instabug_http_client/README.md create mode 100644 packages/instabug_http_client/example/.metadata create mode 100644 packages/instabug_http_client/example/README.md rename {example => packages/instabug_http_client/example}/analysis_options.yaml (93%) create mode 100644 packages/instabug_http_client/example/android/.gitignore create mode 100644 packages/instabug_http_client/example/android/app/build.gradle create mode 100644 packages/instabug_http_client/example/android/app/src/debug/AndroidManifest.xml create mode 100644 packages/instabug_http_client/example/android/app/src/main/AndroidManifest.xml create mode 100644 packages/instabug_http_client/example/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java create mode 100644 packages/instabug_http_client/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt create mode 100644 packages/instabug_http_client/example/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 packages/instabug_http_client/example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 packages/instabug_http_client/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 packages/instabug_http_client/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 packages/instabug_http_client/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 packages/instabug_http_client/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 packages/instabug_http_client/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 packages/instabug_http_client/example/android/app/src/main/res/values-night/styles.xml create mode 100644 packages/instabug_http_client/example/android/app/src/main/res/values/styles.xml create mode 100644 packages/instabug_http_client/example/android/app/src/main/res/xml/network_security_config.xml create mode 100644 packages/instabug_http_client/example/android/app/src/profile/AndroidManifest.xml create mode 100644 packages/instabug_http_client/example/android/build.gradle create mode 100644 packages/instabug_http_client/example/android/gradle.properties create mode 100644 packages/instabug_http_client/example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 packages/instabug_http_client/example/android/settings.gradle create mode 100644 packages/instabug_http_client/example/ios/.gitignore create mode 100644 packages/instabug_http_client/example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 packages/instabug_http_client/example/ios/Flutter/Debug.xcconfig create mode 100644 packages/instabug_http_client/example/ios/Flutter/Release.xcconfig create mode 100644 packages/instabug_http_client/example/ios/Podfile create mode 100644 packages/instabug_http_client/example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 packages/instabug_http_client/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/instabug_http_client/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/instabug_http_client/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/instabug_http_client/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/instabug_http_client/example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/instabug_http_client/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/instabug_http_client/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/instabug_http_client/example/ios/Runner/AppDelegate.swift create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 packages/instabug_http_client/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 packages/instabug_http_client/example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 packages/instabug_http_client/example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 packages/instabug_http_client/example/ios/Runner/Info.plist create mode 100644 packages/instabug_http_client/example/ios/Runner/Runner-Bridging-Header.h create mode 100644 packages/instabug_http_client/example/lib/main.dart create mode 100644 packages/instabug_http_client/example/pubspec.lock create mode 100644 packages/instabug_http_client/example/pubspec.yaml create mode 100644 packages/instabug_http_client/example/pubspec_overrides.yaml create mode 100644 packages/instabug_http_client/lib/instabug_http_client.dart create mode 100644 packages/instabug_http_client/lib/instabug_http_logger.dart create mode 100644 packages/instabug_http_client/pubspec.lock create mode 100644 packages/instabug_http_client/pubspec.yaml create mode 100644 packages/instabug_http_client/pubspec_overrides.yaml create mode 100644 packages/instabug_http_client/release.sh create mode 100644 packages/instabug_http_client/test/instabug_http_client_test.dart create mode 100644 scripts/init.sh create mode 100644 scripts/move_coverage_files.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index ffeab99da..3c4365122 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,18 +2,36 @@ version: 2.1 orbs: android: circleci/android@2.5.0 - flutter: circleci/flutter@2.0.2 + flutter: circleci/flutter@2.0.4 node: circleci/node@5.2.0 advanced-checkout: vsco/advanced-checkout@1.1.0 +executors: + flutter-executor: + docker: + - image: cimg/base:stable + + commands: setup_flutter: + parameters: + version: + type: string + default: 3.24.3 + use_melos: + type: boolean + default: true + working_dir: + type: string + default: "~/project" steps: - flutter/install_sdk_and_pub: - version: 3.24.0 - - run: - name: Generate Pigeons - command: sh ./scripts/pigeon.sh + version: <> + app-dir: <> + - install_flutter_and_dart_packages: + generate_pigeons: true + use_melos: <> + working_dir: <> setup_ios: steps: # Flutter doesn't support Apple Silicon yet, so we need to install Rosetta use Flutter on M1 machines. @@ -26,7 +44,7 @@ commands: command: sudo gem install cocoapods - run: name: Install Pods - working_directory: example/ios + working_directory: packages/instabug_flutter/example/ios command: pod install --repo-update setup_captain: parameters: @@ -77,32 +95,71 @@ commands: name: Configure Captain Platform command: echo 'export CAPTAIN_PLATFORM=<>' >> $BASH_ENV # This runs `flutter pub get` and `dart pub get` if we pass parameter `generate_pigeons` to the job it also runs the following: - # - `sh ./scripts/pigeon.sh` - # - `dart run build_runner build --delete-conflicting-outputs` + # - `melos pigeon` + # - `melos generate` install_flutter_and_dart_packages: parameters: generate_pigeons: type: boolean + use_melos: + type: boolean + default: true + working_dir: + type: string steps: - - run: - name: Install Flutter Packages - command: flutter pub get - - run: - name: Install Dart Packages - command: dart pub get - description: Install Dart Packages (for dart explicit packages) - when: condition: equal: - - <> + - <> - true steps: - run: - name: Generate Pigeons - command: sh ./scripts/pigeon.sh + name: Install melos + command: dart pub global activate melos && echo 'export PATH="$PATH:$HOME/.pub-cache/bin"' >> $BASH_ENV + - run: + name: Install Flutter Packages + command: melos bootstrap + - run: + name: Install Dart Packages + command: melos dart_bootstrap + description: Install Dart Packages (for dart explicit packages) + - when: + condition: + equal: + - <> + - true + steps: + - run: + name: Generate Pigeons + command: melos pigeon --no-select + - run: + name: Build Pigeons + command: melos generate --no-select + - when: + condition: + equal: + - <> + - false + steps: + - run: + name: Install Flutter Packages + command: flutter pub get - run: - name: Build Pigeons - command: dart run build_runner build --delete-conflicting-outputs + name: Install Dart Packages + command: dart pub get + description: Install Dart Packages (for dart explicit packages) + - when: + condition: + equal: + - <> + - true + steps: + - run: + name: Generate Pigeons + command: sh scripts/pigeon.sh + - run: + name: Build Pigeons + command: dart run build_runner build --delete-conflicting-outputs jobs: danger: @@ -114,7 +171,7 @@ jobs: pkg-manager: yarn override-ci-command: yarn install --frozen-lockfile --network-concurrency 1 - attach_workspace: - at: coverage + at: ~/project - run: name: Run Danger command: yarn danger ci @@ -123,20 +180,38 @@ jobs: parameters: version: type: string - docker: - - image: cirrusci/flutter:<> + default: "3.24.3" + executor: flutter-executor steps: - advanced-checkout/shallow-checkout - - install_flutter_and_dart_packages: - generate_pigeons: true - - run: flutter test --coverage - - run: - working_directory: coverage - command: lcov --remove lcov.info '*.g.dart' '*.mocks.dart' -o lcov.info + - run: sudo apt-get update&& sudo apt-get -y install lcov + - setup_flutter: + version: <> + use_melos: true + - run: melos test-coverage --no-select - persist_to_workspace: - root: coverage + root: ~/project paths: - - lcov.info + - coverage + + + test_flutter_without_melos: + parameters: + version: + type: string + default: "2.10.0" + app-dir: + type: string + executor: flutter-executor + working_directory: <> + steps: + - advanced-checkout/shallow-checkout: + path: ~/project + - setup_flutter: + version: <> + use_melos: false + working_dir: <> + - run: flutter test test_android: executor: @@ -147,7 +222,7 @@ jobs: - advanced-checkout/shallow-checkout - setup_flutter - android/run-tests: - working-directory: example/android + working-directory: packages/instabug_flutter/example/android test-command: ./gradlew test e2e_android_captain: @@ -162,9 +237,9 @@ jobs: - setup_flutter - android/start-emulator-and-run-tests: run-tests-working-directory: e2e - additional-avd-args: --device 3 + additional-avd-args: --device 25 system-image: system-images;android-33;default;x86_64 - post-emulator-launch-assemble-command: cd example && flutter build apk --debug + post-emulator-launch-assemble-command: cd packages/instabug_flutter/example && flutter build apk --debug test-command: dotnet test test_ios: @@ -178,7 +253,7 @@ jobs: - setup_ios - run: name: Build and run tests - working_directory: ~/project/example/ios + working_directory: ~/project/packages/instabug_flutter/example/ios command: | xcodebuild -allowProvisioningUpdates \ -workspace Runner.xcworkspace \ @@ -199,53 +274,72 @@ jobs: - setup_ios - run: name: Build Example App - working_directory: example + working_directory: packages/instabug_flutter/example command: flutter build ios --simulator - run: name: Run E2E Tests - no_output_timeout: 30m + no_output_timeout: 20m working_directory: e2e command: dotnet test format_flutter: - docker: - - image: cirrusci/flutter + executor: flutter-executor steps: - advanced-checkout/shallow-checkout - - install_flutter_and_dart_packages: - generate_pigeons: false + - setup_flutter - run: name: Check Format - command: dart format . --set-exit-if-changed + command: melos format lint_flutter: - docker: - - image: cirrusci/flutter + executor: flutter-executor steps: - advanced-checkout/shallow-checkout - - install_flutter_and_dart_packages: - generate_pigeons: true + - setup_flutter - run: name: Perform Static Analysis - command: flutter analyze + command: melos analyze verify_pub: - docker: - - image: cirrusci/flutter + executor: flutter-executor steps: - advanced-checkout/shallow-checkout - - install_flutter_and_dart_packages: - generate_pigeons: true + - setup_flutter - run: name: Check Package Score - command: dart run pana --no-warning --exit-code-threshold 0 - - run: flutter pub publish --dry-run + command: melos score --no-select + - run: melos dryPublish --no-select - release: + release_dio_plugin: + executor: flutter-executor + steps: + - advanced-checkout/shallow-checkout + - setup_flutter + - run: chmod +x packages/Instabug-Dio-Interceptor/release.sh + - run: ./packages/Instabug-Dio-Interceptor/release.sh + + release_http_adapter_plugin: + executor: flutter-executor + steps: + - advanced-checkout/shallow-checkout + - setup_flutter + - run: chmod +x packages/Instabug-Dart-http-Adapter/release.sh + - run: ./packages/Instabug-Dart-http-Adapter/release.sh + + release_modular_plugin: + executor: flutter-executor + steps: + - advanced-checkout/shallow-checkout + - setup_flutter + - run: chmod +x packages/instabug_flutter_modular/release.sh + - run: ./packages/instabug_flutter_modular/release.sh + + + release_instabug_flutter: macos: xcode: 15.2.0 resource_class: macos.m1.medium.gen1 - working_directory: "~" + working_directory: "~/project" steps: - advanced-checkout/shallow-checkout: path: ~/project @@ -254,7 +348,7 @@ jobs: name: Install Rosetta command: softwareupdate --install-rosetta --agree-to-license - flutter/install_sdk_and_pub: - version: 3.3.6 + version: 3.10.5 app-dir: project - run: name: Install pub packages @@ -263,7 +357,7 @@ jobs: - run: name: Generate Pigeons working_directory: project - command: sh ./scripts/pigeon.sh + command: melos pigeon --no-select - run: name: Clone Escape command: git clone git@github.com:Instabug/Escape.git @@ -288,10 +382,10 @@ workflows: - test_flutter-stable - test_flutter: name: test_flutter-stable - version: stable - - test_flutter: + - test_flutter_without_melos: name: test_flutter-2.10.5 version: 2.10.5 + app-dir: "~/project/packages/instabug_flutter/" - e2e_android_captain - test_ios - e2e_ios_captain @@ -302,7 +396,7 @@ workflows: - verify_pub: requires: - lint_flutter - - hold_release: + - hold_release_instabug_flutter: type: approval requires: - danger @@ -319,9 +413,51 @@ workflows: filters: branches: only: master - - release: + - hold_release_dio_plugin: + type: approval + requires: + - test_flutter-stable + filters: + branches: + only: master + - release_dio_plugin: + requires: + - hold_release_dio_plugin + - verify_pub + filters: + branches: + only: master + - hold_release_http_adapter_plugin: + type: approval + requires: + - test_flutter-stable + filters: + branches: + only: master + - release_http_adapter_plugin: + requires: + - hold_release_http_adapter_plugin + - verify_pub + filters: + branches: + only: master + - hold_release_modular_plugin: + type: approval + requires: + - test_flutter-stable + filters: + branches: + only: master + - release_modular_plugin: requires: - - hold_release + - hold_release_modular_plugin + - verify_pub + filters: + branches: + only: master + - release_instabug_flutter: + requires: + - hold_release_instabug_flutter filters: branches: - only: master \ No newline at end of file + only: master diff --git a/.gitignore b/.gitignore index 071964ca9..dfa529b28 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ # Generated files *.mocks.dart *.g.dart -android/**/generated/ -ios/**/Generated/ +packages/**/android/**/generated/ +packages/**/ios/**/Generated/ # Miscellaneous *.class @@ -63,6 +63,8 @@ android/gradlew.bat **/ios/**/DerivedData/ **/ios/**/Icon? **/ios/**/Pods/ +**/ios/**/Pods/ + **/ios/**/.symlinks/ **/ios/**/profile **/ios/**/xcuserdata @@ -84,3 +86,4 @@ android/gradlew.bat !**/ios/**/default.pbxuser !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +/packages/**/lib/src/generated/ diff --git a/README.md b/README.md index 88080febd..4a260d8d2 100644 --- a/README.md +++ b/README.md @@ -1,116 +1,39 @@ -# Instabug for Flutter + -## Available Features +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. -| Feature | Status | -|:---------------------------------------------------------:|:-------:| -| [Bug Reporting](https://docs.instabug.com/docs/flutter-bug-reporting) | ✅ | -| [Crash Reporting](https://docs.instabug.com/docs/flutter-crash-reporting) | ✅ | -| [App Performance Monitoring](https://docs.instabug.com/docs/flutter-apm) | ✅ | -| [In-App Replies](https://docs.instabug.com/docs/flutter-in-app-replies) | ✅ | -| [In-App Surveys](https://docs.instabug.com/docs/flutter-in-app-surveys) | ✅ | -| [Feature Requests](https://docs.instabug.com/docs/flutter-in-app-feature-requests) | ✅ | +## Features -* ✅ Stable -* ⚙️ Under active development +TODO: List what your package can do. Maybe include images, gifs, or videos. -## Integration +## Getting started -### Installation +TODO: List prerequisites and provide or point to information on how to +start using the package. -1. Add Instabug to your `pubspec.yaml` file. +## Usage -```yaml -dependencies: - instabug_flutter: -``` - -2. Install the package by running the following command. - -```bash -flutter packages get -``` - -### Initializing Instabug - -Initialize the SDK in your `main` function. This starts the SDK with the default behavior and sets it to be shown when the device is shaken. +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. ```dart -import 'package:instabug_flutter/instabug_flutter.dart'; - -void main() { - WidgetsFlutterBinding.ensureInitialized(); - - Instabug.init( - token: 'APP_TOKEN', - invocationEvents: [InvocationEvent.shake], - ); - - runApp(MyApp()); -} +const like = 'sample'; ``` -> :warning: If you're updating the SDK from versions prior to v11, please check our [migration guide](https://docs.instabug.com/docs/flutter-migration-guide). - -## Crash reporting - -Instabug automatically captures every crash of your app and sends relevant details to the crashes page of your dashboard. - -⚠️ **Crashes will only be reported in release mode and not in debug mode.** - -```dart -void main() { - runZonedGuarded( - () { - WidgetsFlutterBinding.ensureInitialized(); - - Instabug.init( - token: 'APP_TOKEN', - invocationEvents: [InvocationEvent.shake], - ); - - FlutterError.onError = (FlutterErrorDetails details) { - Zone.current.handleUncaughtError(details.exception, details.stack!); - }; - - runApp(MyApp()); - }, - CrashReporting.reportCrash, - ); -} -``` - -## Repro Steps -Repro Steps list all of the actions an app user took before reporting a bug or crash, grouped by the screens they visited in your app. - - To enable this feature, you need to add `InstabugNavigatorObserver` to the `navigatorObservers` : - ``` - runApp(MaterialApp( - navigatorObservers: [InstabugNavigatorObserver()], - )); - ``` - -## Network Logging -You can choose to attach all your network requests to the reports being sent to the dashboard. To enable the feature when using the `dart:io` package `HttpClient`, please refer to the [Instabug Dart IO Http Client](https://github.com/Instabug/instabug-dart-io-http-client) repository. - -We also support the packages `http` and `dio`. For details on how to enable network logging for these external packages, refer to the [Instabug Dart Http Adapter](https://github.com/Instabug/Instabug-Dart-http-Adapter) and the [Instabug Dio Interceptor](https://github.com/Instabug/Instabug-Dio-Interceptor) repositories. - -## Microphone and Photo Library Usage Description (iOS Only) - -Instabug needs access to the microphone and photo library to be able to let users add audio and video attachments. Starting from iOS 10, apps that don’t provide a usage description for those 2 permissions would be rejected when submitted to the App Store. - -For your app not to be rejected, you’ll need to add the following 2 keys to your app’s info.plist file with text explaining to the user why those permissions are needed: - -* `NSMicrophoneUsageDescription` -* `NSPhotoLibraryUsageDescription` - -If your app doesn’t already access the microphone or photo library, we recommend using a usage description like: - -* "`` needs access to the microphone to be able to attach voice notes." -* "`` needs access to your photo library for you to be able to attach images." +## Additional information -**The permission alert for accessing the microphone/photo library will NOT appear unless users attempt to attach a voice note/photo while using Instabug.** +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/analysis_options.yaml b/analysis_options.yaml index 9e956095e..4f1f095e4 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -2,8 +2,9 @@ include: package:lint/analysis_options_package.yaml analyzer: exclude: - - "example/**" - - "**/*.g.dart" + - "packages/**/*.g.dart" + - "packages/**/example/**" + linter: rules: diff --git a/dangerfile.ts b/dangerfile.ts index 670ae0b05..ee0fb4944 100644 --- a/dangerfile.ts +++ b/dangerfile.ts @@ -1,5 +1,6 @@ import { danger, fail, schedule, warn } from 'danger'; -import collectCoverage, { ReportType } from '@instabug/danger-plugin-coverage'; +import collectCoverage, {ReportOptions, ReportType} from '@instabug/danger-plugin-coverage'; +import * as fs from 'fs'; const hasSourceChanges = danger.git.modified_files.some((file) => file.startsWith('lib/') @@ -20,7 +21,7 @@ async function hasDescription() { ); } - if (!danger.git.modified_files.includes('CHANGELOG.md') && !declaredTrivial) { + if (!danger.git.modified_files.includes('packages/instabug-Flutter/CHANGELOG.md') && !declaredTrivial) { warn( 'You have not included a CHANGELOG entry! \nYou can find it at [CHANGELOG.md](https://github.com/Instabug/Instabug-Flutter/blob/master/CHANGELOG.md).' ); @@ -29,9 +30,22 @@ async function hasDescription() { schedule(hasDescription()); -collectCoverage({ - label: 'Dart', - type: ReportType.LCOV, - filePath: 'coverage/lcov.info', - threshold: 80, -}); +// Function to extract the second part of the filename using '-' as a separator +const getLabelFromFilename = (filename: string): string | null => { + const parts = filename.split('-'); + return parts[1] ? parts[1].replace(/\.[^/.]+$/, '') : null; // Removes extension +}; + +console.log(JSON.stringify(getLabelFromFilename)); +const files = fs.readdirSync('coverage'); +let reportOptions: ReportOptions[] = []; +for (let file of files) { + reportOptions.push({ + label: getLabelFromFilename(file), + type: ReportType.LCOV, + filePath: "coverage/"+file, + threshold: 80, + }); +} +collectCoverage(reportOptions); + diff --git a/e2e/.gitignore b/e2e/.gitignore index a72f3ddc5..2afa2e272 100644 --- a/e2e/.gitignore +++ b/e2e/.gitignore @@ -1,454 +1,454 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Ww][Ii][Nn]32/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET -project.lock.json -project.fragment.lock.json -artifacts/ - -# Tye -.tye/ - -# ASP.NET Scaffolding -ScaffoldingReadMe.txt - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*.json -coverage*.xml -coverage*.info - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ - -# Fody - auto-generated XML schema -FodyWeavers.xsd - -## -## Visual studio for Mac -## - - -# globs -Makefile.in -*.userprefs -*.usertasks -config.make -config.status -aclocal.m4 -install-sh -autom4te.cache/ -*.tar.gz -tarballs/ -test-results/ - -# Mac bundle stuff -*.dmg -*.app - -# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore -# Windows thumbnail cache files -Thumbs.db -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# JetBrains Rider -.idea/ -*.sln.iml - -## -## Visual Studio Code -## -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# JetBrains Rider +.idea/ +*.sln.iml + +## +## Visual Studio Code +## +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json diff --git a/e2e/Utils/CaptainTest.cs b/e2e/Utils/CaptainTest.cs index 35749d727..e32255d4b 100644 --- a/e2e/Utils/CaptainTest.cs +++ b/e2e/Utils/CaptainTest.cs @@ -1,5 +1,7 @@ using System.Drawing; using Instabug.Captain; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium.MultiTouch; namespace E2E.Utils; @@ -7,10 +9,11 @@ public class CaptainTest : IDisposable { private static readonly CaptainConfig _config = new() { - AndroidApp = Path.GetFullPath("../../../../example/build/app/outputs/flutter-apk/app-debug.apk"), + AndroidApp = Path.GetFullPath("../../../../packages/instabug_flutter/example/build/app/outputs/flutter-apk/app-debug.apk"), AndroidAppId = "com.instabug.flutter.example", AndroidVersion = "13", - IosApp = Path.GetFullPath("../../../../example/build/ios/iphonesimulator/Runner.app"), + + IosApp = Path.GetFullPath("../../../../packages/instabug_flutter/example/build/ios/iphonesimulator/Runner.app"), IosAppId = "com.instabug.InstabugSample", IosVersion = "17.2", IosDevice = "iPhone 15 Pro Max" @@ -28,28 +31,5 @@ public void Dispose() captain.RestartApp(); } - protected void ScrollDown() - { - captain.Swipe( - start: new Point(captain.Window.Size.Width / 2, captain.Window.Size.Height - 200), - end: new Point(captain.Window.Size.Width / 2, 250) - ); - } - - protected void ScrollDownLittle() - { - captain.Swipe( - start: new Point(captain.Window.Size.Width / 2, captain.Window.Size.Height - 200), - end: new Point(captain.Window.Size.Width / 2, captain.Window.Size.Height - 220) - ); - } - - protected void ScrollUp() - { - captain.Swipe( - start: new Point(captain.Window.Size.Width / 2, 250), - end: new Point(captain.Window.Size.Width / 2, captain.Window.Size.Height - 200) - ); - } } diff --git a/melos.yaml b/melos.yaml new file mode 100644 index 000000000..b96ab7100 --- /dev/null +++ b/melos.yaml @@ -0,0 +1,82 @@ +name: instabug_flutter_mono + +packages: + - packages/* + - packages/*/** +scripts: + dart_bootstrap: + run: dart pub get + analyze: + run: dart analyze . + format: + run: dart format . --set-exit-if-changed + exec: + concurrency: 1 + failFast: true + orderDependents: true + pigeon: + run: sh scripts/pigeon.sh + exec: + concurrency: 1 + failFast: true + orderDependents: true + packageFilters: + fileExists: 'scripts/pigeon.sh' + generate: + run: dart run build_runner build -d + description: Build all generated files for Dart & Flutter packages in this project.t + exec: + concurrency: 1 + failFast: true + orderDependents: true + packageFilters: + dependsOn: build_runner + test: + run: flutter test + description: Tests all packages. + exec: + concurrency: 1 + failFast: true + orderDependents: true + packageFilters: + dependsOn: flutter_test + test-coverage: + run: flutter test --coverage && cd coverage && lcov --ignore-errors unused --remove lcov.info '*.g.dart' '*.mocks.dart' -o lcov.info && sh ../../../scripts/move_coverage_files.sh + description: Tests all packages. + exec: + concurrency: 1 + failFast: true + orderDependents: true + select-package: + dir-exists: + - test + packageFilters: + dependsOn: flutter_test + dirExists: test + dryPublish: + run: flutter pub publish --dry-run + description: Tests publishing (dry run). + exec: + concurrency: 1 + orderDependents: true + packageFilters: + flutter: true + dependsOn: pana + private: false + pods: + run: cd ios && pod install --repo-update + description: running pod install + exec: + concurrency: 1 + orderDependents: true + packageFilters: + fileExists: 'ios/PodFile' + score: + run: dart run pana --no-warning --exit-code-threshold 0 + exec: + concurrency: 1 + orderDependents: true + packageFilters: + dependsOn: pana + private: false + diff --git a/packages/instabug_dio_interceptor/CHANGELOG.md b/packages/instabug_dio_interceptor/CHANGELOG.md new file mode 100644 index 000000000..4fd938e6f --- /dev/null +++ b/packages/instabug_dio_interceptor/CHANGELOG.md @@ -0,0 +1,55 @@ +# Changelog + +## [2.5.0] (2025-07-17) + +### Added +- supports Instabug SDK above 3.0.0 ([#33](https://github.com/Instabug/Instabug-Dio-Interceptor/pull/33)). + +## [2.4.1] (2025-04-21) + +### Added +- supports Dart versions above 3.0.0 ([#32](https://github.com/Instabug/Instabug-Dio-Interceptor/pull/32)). + +## [2.4.0] (2024-11-18) + +### Added + +- Add support for tracing network requests from Instabug to services like Datadog and New Relic ([#30](https://github.com/Instabug/Instabug-Dio-Interceptor/pull/30)). + +## [2.3.0] - (2024-05-07) + +### Added + +- Add support for Instabug Flutter SDK v13 ([#28](https://github.com/Instabug/Instabug-Dio-Interceptor/pull/28)). +- Add support for Instabug Flutter SDK v12 ([#26](https://github.com/Instabug/Instabug-Dio-Interceptor/pull/26)), closes [#25](https://github.com/Instabug/Instabug-Dio-Interceptor/issues/25). + +## v2.2.0 (2022-03-14) + +- Adds support for Dio v5 +- Relaxes dependencies version constraints + +## v2.1.1 (2022-08-01) + +- Bumps [instabug_flutter](https://pub.dev/packages/instabug_flutter) to v11 + +## v2.1.0 (2022-01-06) + +- Fixes network log compilation error. +- Adds payload size for network log. + +## v2.0.1 (2021-09-29) + +- Fixes an issue with APM network logger not reporting to the dashboard + +## v2.0.0 (2021-09-20) + +- Adds support for Dio v4.0 +- Upgrades to null safety + +## v1.0.0 (2019-07-29) + +- Updates instabug_flutter dependency name + +## v0.0.1 (2019-07-22) + +- Initial release diff --git a/packages/instabug_dio_interceptor/LICENSE b/packages/instabug_dio_interceptor/LICENSE new file mode 100644 index 000000000..e4ca5a0ed --- /dev/null +++ b/packages/instabug_dio_interceptor/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Instabug + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/instabug_dio_interceptor/README.md b/packages/instabug_dio_interceptor/README.md new file mode 100644 index 000000000..4fc3ec30d --- /dev/null +++ b/packages/instabug_dio_interceptor/README.md @@ -0,0 +1,17 @@ +# Instabug Dio Interceptor + +[![CircleCI](https://circleci.com/gh/Instabug/Instabug-Dio-Interceptor.svg?style=svg)](https://circleci.com/gh/Instabug/Instabug-Dio-Interceptor) +[![pub package](https://img.shields.io/pub/v/instabug_dio_interceptor.svg)](https://pub.dev/packages/instabug_dio_interceptor) + +This package is an add on to [Instabug-Flutter](https://github.com/Instabug/Instabug-Flutter). + +It intercepts any requests performed with `Dio` Package and sends them to the report that will be sent to the dashboard. + +## Integration + +To enable network logging, simply add the `InstabugDioInterceptor` to the dio object interceptors as follows: + +```dart +var dio = new Dio(); +dio.interceptors.add(InstabugDioInterceptor()); +``` diff --git a/packages/instabug_dio_interceptor/example/.metadata b/packages/instabug_dio_interceptor/example/.metadata new file mode 100644 index 000000000..5a023280a --- /dev/null +++ b/packages/instabug_dio_interceptor/example/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 7e9793dee1b85a243edd0e06cb1658e98b077561 + channel: stable + +project_type: app diff --git a/packages/instabug_dio_interceptor/example/README.md b/packages/instabug_dio_interceptor/example/README.md new file mode 100644 index 000000000..a13562602 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/README.md @@ -0,0 +1,16 @@ +# example + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/packages/instabug_dio_interceptor/example/android/.gitignore b/packages/instabug_dio_interceptor/example/android/.gitignore new file mode 100644 index 000000000..6f568019d --- /dev/null +++ b/packages/instabug_dio_interceptor/example/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/packages/instabug_dio_interceptor/example/android/app/build.gradle b/packages/instabug_dio_interceptor/example/android/app/build.gradle new file mode 100644 index 000000000..86b077f53 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/android/app/build.gradle @@ -0,0 +1,56 @@ +plugins { + id "com.android.application" + id "kotlin-android" + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id "dev.flutter.flutter-gradle-plugin" +} + +android { + namespace = "com.example.example" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8 + } + + defaultConfig { + applicationId "com.example.example" + minSdkVersion 21 + targetSdkVersion 34 + versionCode flutter.versionCode + versionName flutter.versionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + multiDexEnabled true + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.debug + } + } + namespace = "com.example.example" + + configurations.all { + resolutionStrategy.force 'org.hamcrest:hamcrest-core:1.3' + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.20" + implementation 'com.android.support:multidex:1.0.3' + implementation 'org.mockito:mockito-core:1.10.19' + testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:1.10.19' +} diff --git a/example/android/app/src/debug/AndroidManifest.xml b/packages/instabug_dio_interceptor/example/android/app/src/debug/AndroidManifest.xml similarity index 100% rename from example/android/app/src/debug/AndroidManifest.xml rename to packages/instabug_dio_interceptor/example/android/app/src/debug/AndroidManifest.xml diff --git a/packages/instabug_dio_interceptor/example/android/app/src/main/AndroidManifest.xml b/packages/instabug_dio_interceptor/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..bed9771bc --- /dev/null +++ b/packages/instabug_dio_interceptor/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + diff --git a/packages/instabug_dio_interceptor/example/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java b/packages/instabug_dio_interceptor/example/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java new file mode 100644 index 000000000..752fc185d --- /dev/null +++ b/packages/instabug_dio_interceptor/example/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java @@ -0,0 +1,25 @@ +// Generated file. +// +// If you wish to remove Flutter's multidex support, delete this entire file. +// +// Modifications to this file should be done in a copy under a different name +// as this file may be regenerated. + +package io.flutter.app; + +import android.app.Application; +import android.content.Context; +import androidx.annotation.CallSuper; +import androidx.multidex.MultiDex; + +/** + * Extension of {@link android.app.Application}, adding multidex support. + */ +public class FlutterMultiDexApplication extends Application { + @Override + @CallSuper + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + MultiDex.install(this); + } +} diff --git a/packages/instabug_dio_interceptor/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/packages/instabug_dio_interceptor/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt new file mode 100644 index 000000000..e793a000d --- /dev/null +++ b/packages/instabug_dio_interceptor/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/packages/instabug_dio_interceptor/example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/instabug_dio_interceptor/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 000000000..f74085f3f --- /dev/null +++ b/packages/instabug_dio_interceptor/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/drawable/launch_background.xml b/packages/instabug_dio_interceptor/example/android/app/src/main/res/drawable/launch_background.xml similarity index 100% rename from example/android/app/src/main/res/drawable/launch_background.xml rename to packages/instabug_dio_interceptor/example/android/app/src/main/res/drawable/launch_background.xml diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/instabug_dio_interceptor/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png rename to packages/instabug_dio_interceptor/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/instabug_dio_interceptor/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png rename to packages/instabug_dio_interceptor/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/packages/instabug_dio_interceptor/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to packages/instabug_dio_interceptor/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/instabug_dio_interceptor/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to packages/instabug_dio_interceptor/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/instabug_dio_interceptor/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to packages/instabug_dio_interceptor/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/packages/instabug_dio_interceptor/example/android/app/src/main/res/values-night/styles.xml b/packages/instabug_dio_interceptor/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 000000000..3db14bb53 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/instabug_dio_interceptor/example/android/app/src/main/res/values/styles.xml b/packages/instabug_dio_interceptor/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..d460d1e92 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/instabug_dio_interceptor/example/android/app/src/main/res/xml/network_security_config.xml b/packages/instabug_dio_interceptor/example/android/app/src/main/res/xml/network_security_config.xml new file mode 100644 index 000000000..be9989192 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/android/app/src/main/res/xml/network_security_config.xml @@ -0,0 +1,13 @@ + + + + localhost + api.instabug.com + + + + + + + + diff --git a/example/android/app/src/profile/AndroidManifest.xml b/packages/instabug_dio_interceptor/example/android/app/src/profile/AndroidManifest.xml similarity index 100% rename from example/android/app/src/profile/AndroidManifest.xml rename to packages/instabug_dio_interceptor/example/android/app/src/profile/AndroidManifest.xml diff --git a/example/android/build.gradle b/packages/instabug_dio_interceptor/example/android/build.gradle similarity index 100% rename from example/android/build.gradle rename to packages/instabug_dio_interceptor/example/android/build.gradle diff --git a/example/android/gradle.properties b/packages/instabug_dio_interceptor/example/android/gradle.properties similarity index 100% rename from example/android/gradle.properties rename to packages/instabug_dio_interceptor/example/android/gradle.properties diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/instabug_dio_interceptor/example/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from example/android/gradle/wrapper/gradle-wrapper.properties rename to packages/instabug_dio_interceptor/example/android/gradle/wrapper/gradle-wrapper.properties diff --git a/example/android/settings.gradle b/packages/instabug_dio_interceptor/example/android/settings.gradle similarity index 100% rename from example/android/settings.gradle rename to packages/instabug_dio_interceptor/example/android/settings.gradle diff --git a/packages/instabug_dio_interceptor/example/ios/.gitignore b/packages/instabug_dio_interceptor/example/ios/.gitignore new file mode 100644 index 000000000..7a7f9873a --- /dev/null +++ b/packages/instabug_dio_interceptor/example/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/packages/instabug_dio_interceptor/example/ios/Flutter/AppFrameworkInfo.plist b/packages/instabug_dio_interceptor/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000..7c5696400 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/packages/instabug_dio_interceptor/example/ios/Flutter/Debug.xcconfig b/packages/instabug_dio_interceptor/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000..ec97fc6f3 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/instabug_dio_interceptor/example/ios/Flutter/Release.xcconfig b/packages/instabug_dio_interceptor/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000..c4855bfe2 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/instabug_dio_interceptor/example/ios/Podfile b/packages/instabug_dio_interceptor/example/ios/Podfile new file mode 100644 index 000000000..ba26ef371 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '14.4' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/project.pbxproj b/packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..43b09ccb5 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,555 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 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 */; }; + AD44C4DB39F7C3968B8C56EB /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18B300F826F2074CB5E450C4 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 18B300F826F2074CB5E450C4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3E0436312822B722E186D653 /* 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 = ""; }; + 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 = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 90FF03378459C589A4D9DA6E /* 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 = ""; }; + 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 /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.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 = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DE25EB3DE5B281AB8980A728 /* 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 = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AD44C4DB39F7C3968B8C56EB /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3456E8E25F114A239880D241 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 18B300F826F2074CB5E450C4 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 4955E253C000584F8EA1A042 /* Pods */ = { + isa = PBXGroup; + children = ( + 90FF03378459C589A4D9DA6E /* Pods-Runner.debug.xcconfig */, + 3E0436312822B722E186D653 /* Pods-Runner.release.xcconfig */, + DE25EB3DE5B281AB8980A728 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 4955E253C000584F8EA1A042 /* Pods */, + 3456E8E25F114A239880D241 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + F412A5213E8CA6290AF8A003 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 9BDEDB79123E51897883C720 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + 9BDEDB79123E51897883C720 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F412A5213E8CA6290AF8A003 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = XNK224R4SF; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = XNK224R4SF; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = XNK224R4SF; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..5e31d3d34 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/instabug_dio_interceptor/example/ios/Runner.xcworkspace/contents.xcworkspacedata similarity index 100% rename from example/ios/Runner.xcworkspace/contents.xcworkspacedata rename to packages/instabug_dio_interceptor/example/ios/Runner.xcworkspace/contents.xcworkspacedata diff --git a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/instabug_dio_interceptor/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to packages/instabug_dio_interceptor/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/instabug_dio_interceptor/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to packages/instabug_dio_interceptor/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/packages/instabug_dio_interceptor/example/ios/Runner/AppDelegate.swift b/packages/instabug_dio_interceptor/example/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000..b63630348 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@main +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md rename to packages/instabug_dio_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md diff --git a/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/instabug_dio_interceptor/example/ios/Runner/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from example/ios/Runner/Base.lproj/LaunchScreen.storyboard rename to packages/instabug_dio_interceptor/example/ios/Runner/Base.lproj/LaunchScreen.storyboard diff --git a/example/ios/Runner/Base.lproj/Main.storyboard b/packages/instabug_dio_interceptor/example/ios/Runner/Base.lproj/Main.storyboard similarity index 100% rename from example/ios/Runner/Base.lproj/Main.storyboard rename to packages/instabug_dio_interceptor/example/ios/Runner/Base.lproj/Main.storyboard diff --git a/packages/instabug_dio_interceptor/example/ios/Runner/Info.plist b/packages/instabug_dio_interceptor/example/ios/Runner/Info.plist new file mode 100644 index 000000000..7f553465b --- /dev/null +++ b/packages/instabug_dio_interceptor/example/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/packages/instabug_dio_interceptor/example/ios/Runner/Runner-Bridging-Header.h b/packages/instabug_dio_interceptor/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000..308a2a560 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/packages/instabug_dio_interceptor/example/lib/main.dart b/packages/instabug_dio_interceptor/example/lib/main.dart new file mode 100644 index 000000000..fcd29a3cb --- /dev/null +++ b/packages/instabug_dio_interceptor/example/lib/main.dart @@ -0,0 +1,78 @@ +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:instabug_dio_interceptor/instabug_dio_interceptor.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; + +Future main() async { + runApp(const MyApp()); + + Instabug.init( + token: 'ed6f659591566da19b67857e1b9d40ab', + invocationEvents: [InvocationEvent.floatingButton], + ); + + final dio = Dio()..interceptors.add(InstabugDioInterceptor()); + final response = await dio.get('https://google.com'); + debugPrint(response.data); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({Key? key, required this.title}) : super(key: key); + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + int _counter = 0; + + void _incrementCounter() { + setState(() { + _counter++; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'You have pushed the button this many times:', + ), + Text( + '$_counter', + style: Theme.of(context).textTheme.headlineMedium, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: _incrementCounter, + tooltip: 'Increment', + child: const Icon(Icons.add), + ), + ); + } +} diff --git a/example/pubspec.lock b/packages/instabug_dio_interceptor/example/pubspec.lock similarity index 83% rename from example/pubspec.lock rename to packages/instabug_dio_interceptor/example/pubspec.lock index 99e8f9d56..7c9abf86c 100644 --- a/example/pubspec.lock +++ b/packages/instabug_dio_interceptor/example/pubspec.lock @@ -41,32 +41,43 @@ packages: url: "https://pub.dev" source: hosted version: "1.19.0" - fake_async: + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + dio: + dependency: "direct main" + description: + name: dio + sha256: d90ee57923d1828ac14e492ca49440f65477f4bb1263575900be731a3dac66a9 + url: "https://pub.dev" + source: hosted + version: "5.9.0" + dio_web_adapter: dependency: transitive description: - name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + name: dio_web_adapter + sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78" url: "https://pub.dev" source: hosted - version: "1.3.1" - file: + version: "2.1.1" + fake_async: dependency: transitive description: - name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "1.3.1" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" - flutter_driver: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" flutter_lints: dependency: "direct dev" description: @@ -80,19 +91,6 @@ packages: description: flutter source: sdk version: "0.0.0" - fuchsia_remote_debug_protocol: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - http: - dependency: "direct main" - description: - name: http - sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" - url: "https://pub.dev" - source: hosted - version: "0.13.6" http_parser: dependency: transitive description: @@ -101,21 +99,20 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" - instabug_flutter: + instabug_dio_interceptor: dependency: "direct main" description: path: ".." relative: true source: path - version: "15.0.2" - instabug_http_client: - dependency: "direct main" + version: "2.5.0" + instabug_flutter: + dependency: "direct overridden" description: - name: instabug_http_client - sha256: "7d52803c0dd639f6dddbe07333418eb251ae02f3f9f4d30402517533ca692784" - url: "https://pub.dev" - source: hosted - version: "2.4.0" + path: "../../instabug_flutter" + relative: true + source: path + version: "16.0.0" leak_tracker: dependency: transitive description: @@ -172,30 +169,22 @@ packages: 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" - platform: + mime: dependency: transitive description: - name: platform - sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" url: "https://pub.dev" source: hosted - version: "3.1.5" - process: + version: "2.0.0" + path: dependency: transitive description: - name: process - sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "1.9.0" sky_engine: dependency: transitive description: flutter @@ -233,14 +222,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - sync_http: - dependency: transitive - description: - name: sync_http - sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" - url: "https://pub.dev" - source: hosted - version: "0.3.1" term_glyph: dependency: transitive description: @@ -281,14 +262,14 @@ packages: url: "https://pub.dev" source: hosted version: "14.3.0" - webdriver: + web: dependency: transitive description: - name: webdriver - sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8" + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "1.1.1" sdks: dart: ">=3.5.0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/packages/instabug_dio_interceptor/example/pubspec.yaml b/packages/instabug_dio_interceptor/example/pubspec.yaml new file mode 100644 index 000000000..a2dbaf01b --- /dev/null +++ b/packages/instabug_dio_interceptor/example/pubspec.yaml @@ -0,0 +1,25 @@ +name: instabug_dio_interceptor_example +description: Demonstrates how to use the instabug_dio_interceptor package. + +publish_to: "none" + +version: 1.0.0+1 + +environment: + sdk: ">=2.12.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + cupertino_icons: ^1.0.2 + dio: ^5.0.0 + instabug_dio_interceptor: + path: ../ + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^1.0.0 + +flutter: + uses-material-design: true diff --git a/packages/instabug_dio_interceptor/example/pubspec_overrides.yaml b/packages/instabug_dio_interceptor/example/pubspec_overrides.yaml new file mode 100644 index 000000000..b7e298895 --- /dev/null +++ b/packages/instabug_dio_interceptor/example/pubspec_overrides.yaml @@ -0,0 +1,6 @@ +# melos_managed_dependency_overrides: instabug_dio_interceptor,instabug_flutter +dependency_overrides: + instabug_dio_interceptor: + path: .. + instabug_flutter: + path: ../../instabug_flutter diff --git a/packages/instabug_dio_interceptor/lib/instabug_dio_interceptor.dart b/packages/instabug_dio_interceptor/lib/instabug_dio_interceptor.dart new file mode 100644 index 000000000..37182fea0 --- /dev/null +++ b/packages/instabug_dio_interceptor/lib/instabug_dio_interceptor.dart @@ -0,0 +1,108 @@ +import 'package:dio/dio.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; + +class InstabugDioInterceptor extends Interceptor { + static final Map _requests = {}; + static final NetworkLogger _networklogger = NetworkLogger(); + + @override + Future onRequest( + RequestOptions options, + RequestInterceptorHandler handler, + ) async { + final headers = options.headers; + final startTime = DateTime.now(); + // ignore: invalid_use_of_internal_member + final w3Header = await _networklogger.getW3CHeader( + headers, + startTime.millisecondsSinceEpoch, + ); + if (w3Header?.isW3cHeaderFound == false && + w3Header?.w3CGeneratedHeader != null) { + headers['traceparent'] = w3Header?.w3CGeneratedHeader; + } + options.headers = headers; + final data = NetworkData( + startTime: startTime, + url: options.uri.toString(), + w3cHeader: w3Header, + method: options.method, + ); + _requests[options.hashCode] = data; + handler.next(options); + } + + @override + void onResponse( + Response response, + ResponseInterceptorHandler handler, + ) { + final data = _map(response); + _networklogger.networkLog(data); + handler.next(response); + } + + @override + // Keep `DioError` instead of `DioException` for backward-compatibility, for now. + // ignore: deprecated_member_use + void onError(DioError err, ErrorInterceptorHandler handler) { + if (err.response != null) { + final data = _map(err.response!); + _networklogger.networkLog(data); + } + + handler.next(err); + } + + static NetworkData _getRequestData(int requestHashCode) { + final data = _requests[requestHashCode]!; + _requests.remove(requestHashCode); + return data; + } + + NetworkData _map(Response response) { + final data = _getRequestData(response.requestOptions.hashCode); + final responseHeaders = {}; + final endTime = DateTime.now(); + + response.headers + .forEach((String name, dynamic value) => responseHeaders[name] = value); + + var responseContentType = ''; + if (responseHeaders.containsKey('content-type')) { + responseContentType = responseHeaders['content-type'].toString(); + } + + var requestBodySize = 0; + if (response.requestOptions.headers.containsKey('content-length')) { + requestBodySize = + int.parse(response.requestOptions.headers['content-length'] ?? '0'); + } else if (response.requestOptions.data != null) { + requestBodySize = response.requestOptions.data.toString().length; + } + + var responseBodySize = 0; + if (responseHeaders.containsKey('content-length')) { + // ignore: avoid_dynamic_calls + responseBodySize = int.parse(responseHeaders['content-length'][0] ?? '0'); + } else if (response.data != null) { + responseBodySize = response.data.toString().length; + } + + return data.copyWith( + endTime: endTime, + duration: endTime.difference(data.startTime).inMicroseconds, + url: response.requestOptions.uri.toString(), + method: response.requestOptions.method, + requestBody: response.requestOptions.data.toString(), + requestHeaders: response.requestOptions.headers, + requestContentType: response.requestOptions.contentType, + requestBodySize: requestBodySize, + status: response.statusCode, + responseBody: response.data.toString(), + responseHeaders: responseHeaders, + responseContentType: responseContentType, + responseBodySize: responseBodySize, + ); + } +} diff --git a/packages/instabug_dio_interceptor/pubspec.lock b/packages/instabug_dio_interceptor/pubspec.lock new file mode 100644 index 000000000..50e33bd59 --- /dev/null +++ b/packages/instabug_dio_interceptor/pubspec.lock @@ -0,0 +1,737 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" + url: "https://pub.dev" + source: hosted + version: "76.0.0" + _macros: + dependency: transitive + description: dart + source: sdk + version: "0.3.3" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" + url: "https://pub.dev" + source: hosted + version: "6.11.0" + args: + dependency: transitive + description: + name: args + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + url: "https://pub.dev" + source: hosted + version: "2.6.0" + 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" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" + url: "https://pub.dev" + source: hosted + version: "2.4.13" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 + url: "https://pub.dev" + source: hosted + version: "7.3.2" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + url: "https://pub.dev" + source: hosted + version: "8.9.2" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" + url: "https://pub.dev" + source: hosted + version: "4.10.1" + collection: + dependency: transitive + description: + name: collection + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + url: "https://pub.dev" + source: hosted + version: "1.19.0" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "802bd084fb82e55df091ec8ad1553a7331b61c08251eef19a508b6f3f3a9858d" + url: "https://pub.dev" + source: hosted + version: "1.13.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" + url: "https://pub.dev" + source: hosted + version: "2.3.7" + dio: + dependency: "direct main" + description: + name: dio + sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260" + url: "https://pub.dev" + source: hosted + version: "5.7.0" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + html: + dependency: transitive + description: + name: html + sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" + url: "https://pub.dev" + source: hosted + version: "0.15.6" + http: + dependency: transitive + description: + name: http + sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007 + url: "https://pub.dev" + source: hosted + version: "1.5.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + instabug_flutter: + dependency: "direct main" + description: + path: "../instabug_flutter" + relative: true + source: path + version: "16.0.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + url: "https://pub.dev" + source: hosted + version: "10.0.7" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + url: "https://pub.dev" + source: hosted + version: "3.0.8" + 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: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 + url: "https://pub.dev" + source: hosted + version: "3.0.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + macros: + dependency: transitive + description: + name: macros + sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656" + url: "https://pub.dev" + source: hosted + version: "0.1.3-main.0" + markdown: + dependency: transitive + description: + name: markdown + sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" + url: "https://pub.dev" + source: hosted + version: "7.3.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" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mockito: + dependency: "direct dev" + description: + name: mockito + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" + url: "https://pub.dev" + source: hosted + version: "5.4.4" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + pana: + dependency: "direct dev" + description: + name: pana + sha256: "3fc3fe8e7a9fd4827fa4d625a423eec95d305b2bc3538a3adf7fd6c49217af97" + url: "https://pub.dev" + source: hosted + version: "0.21.45" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + retry: + dependency: transitive + description: + name: retry + sha256: "822e118d5b3aafed083109c72d5f484c6dc66707885e07c0fbcb8b986bba7efc" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + safe_url_check: + dependency: transitive + description: + name: safe_url_check + sha256: "49a3e060a7869cbafc8f4845ca1ecbbaaa53179980a32f4fdfeab1607e90f41d" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" + 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: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + tar: + dependency: transitive + description: + name: tar + sha256: "22f67e2d77b51050436620b2a5de521c58ca6f0b75af1d9ab3c8cae2eae58fcd" + url: "https://pub.dev" + source: hosted + version: "1.0.5" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test: + dependency: transitive + description: + name: test + sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f" + url: "https://pub.dev" + source: hosted + version: "1.25.8" + test_api: + dependency: transitive + description: + name: test_api + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + url: "https://pub.dev" + source: hosted + version: "0.7.3" + test_core: + dependency: transitive + description: + name: test_core + sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d" + url: "https://pub.dev" + source: hosted + version: "0.6.5" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + url: "https://pub.dev" + source: hosted + version: "14.3.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" + url: "https://pub.dev" + source: hosted + version: "0.1.6" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/packages/instabug_dio_interceptor/pubspec.yaml b/packages/instabug_dio_interceptor/pubspec.yaml new file mode 100644 index 000000000..cadd6616d --- /dev/null +++ b/packages/instabug_dio_interceptor/pubspec.yaml @@ -0,0 +1,60 @@ +name: instabug_dio_interceptor +description: + This package is an add on to instabug_flutter. It intercepts any requests performed + with Dio Package and sends them to the report that will be sent to the dashboard. +version: 2.5.0 +homepage: https://github.com/Instabug/Instabug-Flutter#readme +repository: https://github.com/Instabug/Instabug-Flutter/tree/refactor/monorepo/packages/instabug_dio_interceptor + +environment: + sdk: '>=2.12.0 <4.0.0' + +dependencies: + dio: '>=4.0.0 <6.0.0' + flutter: + sdk: flutter + instabug_flutter: '>=14.0.0 <17.0.0' + + +dev_dependencies: + build_runner: ^2.0.3 + flutter_test: + sdk: flutter + mockito: ^5.0.10 + pana: ^0.21.0 +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/custom-fonts/#from-packages diff --git a/packages/instabug_dio_interceptor/pubspec_overrides.yaml b/packages/instabug_dio_interceptor/pubspec_overrides.yaml new file mode 100644 index 000000000..1f0beaf62 --- /dev/null +++ b/packages/instabug_dio_interceptor/pubspec_overrides.yaml @@ -0,0 +1,4 @@ +# melos_managed_dependency_overrides: instabug_flutter +dependency_overrides: + instabug_flutter: + path: ../instabug_flutter diff --git a/packages/instabug_dio_interceptor/release.sh b/packages/instabug_dio_interceptor/release.sh new file mode 100755 index 000000000..6b211fe17 --- /dev/null +++ b/packages/instabug_dio_interceptor/release.sh @@ -0,0 +1,13 @@ +#!/bin/sh +VERSION=$(egrep -o "version: ([0-9]-*.*)+[0-9]" pubspec.yaml | cut -d ":" -f 2) +if [ ! "${VERSION}" ] || [ -z "${VERSION}" ];then + echo "Instabug: err: Version Number not found." + exit 1 +else + mkdir -p .pub-cache + cat < $HOME/.pub-cache/credentials.json + ${PUB_CREDENTIALS} + +EOF + flutter packages pub publish -f +fi \ No newline at end of file diff --git a/packages/instabug_dio_interceptor/test/instabug_dio_interceptor_test.dart b/packages/instabug_dio_interceptor/test/instabug_dio_interceptor_test.dart new file mode 100644 index 000000000..2940dcc83 --- /dev/null +++ b/packages/instabug_dio_interceptor/test/instabug_dio_interceptor_test.dart @@ -0,0 +1,116 @@ +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:instabug_dio_interceptor/instabug_dio_interceptor.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter/src/generated/instabug.api.g.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'instabug_dio_interceptor_test.mocks.dart'; +import 'mock_adapter.dart'; + +class MyInterceptor extends InstabugDioInterceptor { + int requestCount = 0; + int resposneCount = 0; + int errorCount = 0; + + @override + Future onRequest( + RequestOptions options, + RequestInterceptorHandler handler, + ) async { + requestCount++; + super.onRequest(options, handler); + } + + @override + void onResponse( + Response response, + ResponseInterceptorHandler handler, + ) { + resposneCount++; + super.onResponse(response, handler); + } + + @override + // ignore: deprecated_member_use + void onError(DioError err, ErrorInterceptorHandler handler) { + errorCount++; + super.onError(err, handler); + } +} + +@GenerateMocks([ + InstabugHostApi, +]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + WidgetsFlutterBinding.ensureInitialized(); + + final mHost = MockInstabugHostApi(); + + late Dio dio; + late MyInterceptor instabugDioInterceptor; + const appToken = '068ba9a8c3615035e163dc5f829c73be'; + + setUpAll(() { + Instabug.$setHostApi(mHost); + NetworkLogger.$setHostApi(mHost); + when(mHost.isW3CFeatureFlagsEnabled()).thenAnswer( + (_) => Future>.value({ + 'isW3cCaughtHeaderEnabled': true, + 'isW3cExternalGeneratedHeaderEnabled': true, + 'isW3cExternalTraceIDEnabled': true, + }), + ); + }); + + setUp(() { + dio = Dio(); + dio.options.baseUrl = MockAdapter.mockBase; + dio.httpClientAdapter = MockAdapter(); + final events = []; + instabugDioInterceptor = MyInterceptor(); + dio.interceptors.add(instabugDioInterceptor); + Instabug.init(token: appToken, invocationEvents: events); + }); + + test('onResponse Test', () async { + try { + await dio.get('/test'); + // ignore: deprecated_member_use + } on DioError { + // ignor + } + + expect(instabugDioInterceptor.requestCount, 1); + expect(instabugDioInterceptor.resposneCount, 1); + expect(instabugDioInterceptor.errorCount, 0); + }); + + test('onError Test', () async { + try { + await dio.get('/test-error'); + // ignore: deprecated_member_use + } on DioError { + // ignor + } + + expect(instabugDioInterceptor.requestCount, 1); + expect(instabugDioInterceptor.resposneCount, 0); + expect(instabugDioInterceptor.errorCount, 1); + }); + + test('Stress Test', () async { + for (var i = 0; i < 1000; i++) { + try { + await dio.get('/test'); + // ignore: deprecated_member_use + } on DioError { + // ignor + } + } + expect(instabugDioInterceptor.requestCount, 1000); + }); +} diff --git a/packages/instabug_dio_interceptor/test/mock_adapter.dart b/packages/instabug_dio_interceptor/test/mock_adapter.dart new file mode 100644 index 000000000..934acfb0a --- /dev/null +++ b/packages/instabug_dio_interceptor/test/mock_adapter.dart @@ -0,0 +1,43 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:dio/dio.dart'; +import 'package:dio/io.dart'; + +class MockAdapter implements HttpClientAdapter { + static const String mockHost = 'mockserver'; + static const String mockBase = 'http://$mockHost'; + final IOHttpClientAdapter _adapter = IOHttpClientAdapter(); + + @override + Future fetch( + RequestOptions options, + Stream? requestStream, + Future? cancelFuture, + ) async { + final uri = options.uri; + + if (uri.host == mockHost) { + switch (uri.path) { + case '/test': + return ResponseBody.fromString( + jsonEncode({ + 'errCode': 0, + 'data': {'path': uri.path}, + }), + 200, + ); + + default: + return ResponseBody.fromString('', 404); + } + } + return _adapter.fetch(options, requestStream, cancelFuture); + } + + @override + void close({bool force = false}) { + _adapter.close(force: force); + } +} diff --git a/.metadata b/packages/instabug_flutter/.metadata similarity index 100% rename from .metadata rename to packages/instabug_flutter/.metadata diff --git a/.pubignore b/packages/instabug_flutter/.pubignore similarity index 100% rename from .pubignore rename to packages/instabug_flutter/.pubignore diff --git a/CHANGELOG.md b/packages/instabug_flutter/CHANGELOG.md similarity index 97% rename from CHANGELOG.md rename to packages/instabug_flutter/CHANGELOG.md index 0555125f6..d0798641c 100644 --- a/CHANGELOG.md +++ b/packages/instabug_flutter/CHANGELOG.md @@ -5,13 +5,21 @@ ### Added - Add support for Advanced UI customization with comprehensive theming capabilities ([#599](https://github.com/Instabug/Instabug-Flutter/pull/599)) -- + +- Add support for private views and automasking ([#519](https://github.com/Instabug/Instabug-Flutter/pull/519)) + +- Add support for user steps ([#519](https://github.com/Instabug/Instabug-Flutter/pull/519)) + - Add support for App variant. ([#585](https://github.com/Instabug/Instabug-Flutter/pull/585)) ### Changed - **BREAKING** Remove deprecated APIs ([#614](https://github.com/Instabug/Instabug-Flutter/pull/614)). See migration guide for more details. +- Bump Instabug iOS SDK to v15.1.1 ([#620](https://github.com/Instabug/Instabug-Flutter/pull/620)). [See release notes](https://github.com/Instabug/Instabug-iOS/releases/tag/16.0.1). + +- Bump Instabug Android SDK to v15.0.2 ([#620](https://github.com/Instabug/Instabug-Flutter/pull/620)). [See release notes](https://github.com/Instabug/Instabug-Android/releases/tag/v16.0.0). + ## [15.0.2](https://github.com/Instabug/Instabug-Flutter/compare/v14.3.0...15.0.2) (Jul 7, 2025) diff --git a/packages/instabug_flutter/Gemfile b/packages/instabug_flutter/Gemfile new file mode 100644 index 000000000..19b2c91d4 --- /dev/null +++ b/packages/instabug_flutter/Gemfile @@ -0,0 +1 @@ +source "https://rubygems.org" diff --git a/packages/instabug_flutter/Gemfile.lock b/packages/instabug_flutter/Gemfile.lock new file mode 100644 index 000000000..3c10ae234 --- /dev/null +++ b/packages/instabug_flutter/Gemfile.lock @@ -0,0 +1,11 @@ +GEM + remote: https://rubygems.org/ + specs: + +PLATFORMS + ruby + +DEPENDENCIES + +BUNDLED WITH + 1.17.2 diff --git a/LICENSE b/packages/instabug_flutter/LICENSE similarity index 100% rename from LICENSE rename to packages/instabug_flutter/LICENSE diff --git a/packages/instabug_flutter/README.md b/packages/instabug_flutter/README.md new file mode 100644 index 000000000..88080febd --- /dev/null +++ b/packages/instabug_flutter/README.md @@ -0,0 +1,116 @@ +# Instabug for Flutter + +[![pub package](https://img.shields.io/pub/v/instabug_flutter.svg)](https://pub.dev/packages/instabug_flutter) + +A Flutter plugin for [Instabug](https://instabug.com/). + +## Available Features + +| Feature | Status | +|:---------------------------------------------------------:|:-------:| +| [Bug Reporting](https://docs.instabug.com/docs/flutter-bug-reporting) | ✅ | +| [Crash Reporting](https://docs.instabug.com/docs/flutter-crash-reporting) | ✅ | +| [App Performance Monitoring](https://docs.instabug.com/docs/flutter-apm) | ✅ | +| [In-App Replies](https://docs.instabug.com/docs/flutter-in-app-replies) | ✅ | +| [In-App Surveys](https://docs.instabug.com/docs/flutter-in-app-surveys) | ✅ | +| [Feature Requests](https://docs.instabug.com/docs/flutter-in-app-feature-requests) | ✅ | + +* ✅ Stable +* ⚙️ Under active development + +## Integration + +### Installation + +1. Add Instabug to your `pubspec.yaml` file. + +```yaml +dependencies: + instabug_flutter: +``` + +2. Install the package by running the following command. + +```bash +flutter packages get +``` + +### Initializing Instabug + +Initialize the SDK in your `main` function. This starts the SDK with the default behavior and sets it to be shown when the device is shaken. + +```dart +import 'package:instabug_flutter/instabug_flutter.dart'; + +void main() { + WidgetsFlutterBinding.ensureInitialized(); + + Instabug.init( + token: 'APP_TOKEN', + invocationEvents: [InvocationEvent.shake], + ); + + runApp(MyApp()); +} +``` + +> :warning: If you're updating the SDK from versions prior to v11, please check our [migration guide](https://docs.instabug.com/docs/flutter-migration-guide). + +## Crash reporting + +Instabug automatically captures every crash of your app and sends relevant details to the crashes page of your dashboard. + +⚠️ **Crashes will only be reported in release mode and not in debug mode.** + +```dart +void main() { + runZonedGuarded( + () { + WidgetsFlutterBinding.ensureInitialized(); + + Instabug.init( + token: 'APP_TOKEN', + invocationEvents: [InvocationEvent.shake], + ); + + FlutterError.onError = (FlutterErrorDetails details) { + Zone.current.handleUncaughtError(details.exception, details.stack!); + }; + + runApp(MyApp()); + }, + CrashReporting.reportCrash, + ); +} +``` + +## Repro Steps +Repro Steps list all of the actions an app user took before reporting a bug or crash, grouped by the screens they visited in your app. + + To enable this feature, you need to add `InstabugNavigatorObserver` to the `navigatorObservers` : + ``` + runApp(MaterialApp( + navigatorObservers: [InstabugNavigatorObserver()], + )); + ``` + +## Network Logging +You can choose to attach all your network requests to the reports being sent to the dashboard. To enable the feature when using the `dart:io` package `HttpClient`, please refer to the [Instabug Dart IO Http Client](https://github.com/Instabug/instabug-dart-io-http-client) repository. + +We also support the packages `http` and `dio`. For details on how to enable network logging for these external packages, refer to the [Instabug Dart Http Adapter](https://github.com/Instabug/Instabug-Dart-http-Adapter) and the [Instabug Dio Interceptor](https://github.com/Instabug/Instabug-Dio-Interceptor) repositories. + +## Microphone and Photo Library Usage Description (iOS Only) + +Instabug needs access to the microphone and photo library to be able to let users add audio and video attachments. Starting from iOS 10, apps that don’t provide a usage description for those 2 permissions would be rejected when submitted to the App Store. + +For your app not to be rejected, you’ll need to add the following 2 keys to your app’s info.plist file with text explaining to the user why those permissions are needed: + +* `NSMicrophoneUsageDescription` +* `NSPhotoLibraryUsageDescription` + +If your app doesn’t already access the microphone or photo library, we recommend using a usage description like: + +* "`` needs access to the microphone to be able to attach voice notes." +* "`` needs access to your photo library for you to be able to attach images." + +**The permission alert for accessing the microphone/photo library will NOT appear unless users attempt to attach a voice note/photo while using Instabug.** diff --git a/android/.gitignore b/packages/instabug_flutter/android/.gitignore similarity index 100% rename from android/.gitignore rename to packages/instabug_flutter/android/.gitignore diff --git a/android/build.gradle b/packages/instabug_flutter/android/build.gradle similarity index 91% rename from android/build.gradle rename to packages/instabug_flutter/android/build.gradle index 0f1d8b852..1b072dc72 100644 --- a/android/build.gradle +++ b/packages/instabug_flutter/android/build.gradle @@ -1,5 +1,5 @@ group 'com.instabug.flutter' -version '15.0.2' +version '16.0.0' buildscript { repositories { @@ -47,11 +47,11 @@ android { } dependencies { - api 'com.instabug.library:instabug:15.0.2' + api 'com.instabug.library:instabug:16.0.0' testImplementation 'junit:junit:4.13.2' testImplementation "org.mockito:mockito-inline:3.12.1" testImplementation "io.mockk:mockk:1.13.13" - + testImplementation "org.robolectric:robolectric:4.12.2" } // add upload_symbols task diff --git a/android/gradle.properties b/packages/instabug_flutter/android/gradle.properties similarity index 100% rename from android/gradle.properties rename to packages/instabug_flutter/android/gradle.properties diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/packages/instabug_flutter/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from android/gradle/wrapper/gradle-wrapper.properties rename to packages/instabug_flutter/android/gradle/wrapper/gradle-wrapper.properties diff --git a/android/proguard-rules.txt b/packages/instabug_flutter/android/proguard-rules.txt similarity index 100% rename from android/proguard-rules.txt rename to packages/instabug_flutter/android/proguard-rules.txt diff --git a/android/settings.gradle b/packages/instabug_flutter/android/settings.gradle similarity index 100% rename from android/settings.gradle rename to packages/instabug_flutter/android/settings.gradle diff --git a/android/src/main/AndroidManifest.xml b/packages/instabug_flutter/android/src/main/AndroidManifest.xml similarity index 100% rename from android/src/main/AndroidManifest.xml rename to packages/instabug_flutter/android/src/main/AndroidManifest.xml diff --git a/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java similarity index 78% rename from android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java index bb3b043fa..39089fffe 100644 --- a/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java @@ -10,15 +10,20 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.instabug.flutter.generated.InstabugPrivateViewPigeon; import com.instabug.flutter.modules.ApmApi; import com.instabug.flutter.modules.BugReportingApi; import com.instabug.flutter.modules.CrashReportingApi; import com.instabug.flutter.modules.FeatureRequestsApi; import com.instabug.flutter.modules.InstabugApi; import com.instabug.flutter.modules.InstabugLogApi; +import com.instabug.flutter.modules.InstabugPrivateView; +import com.instabug.flutter.modules.PrivateViewManager; import com.instabug.flutter.modules.RepliesApi; import com.instabug.flutter.modules.SessionReplayApi; import com.instabug.flutter.modules.SurveysApi; +import com.instabug.flutter.modules.capturing.BoundryCaptureManager; +import com.instabug.flutter.modules.capturing.PixelCopyCaptureManager; import java.util.concurrent.Callable; @@ -35,6 +40,10 @@ public class InstabugFlutterPlugin implements FlutterPlugin, ActivityAware { private static Activity activity; + private static PrivateViewManager privateViewManager; + + + @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { register(binding.getApplicationContext(), binding.getBinaryMessenger(), (FlutterRenderer) binding.getTextureRegistry()); @@ -48,21 +57,31 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { @Override public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { activity = binding.getActivity(); + if (privateViewManager != null) { + privateViewManager.setActivity(activity); + } } @Override public void onDetachedFromActivityForConfigChanges() { activity = null; + privateViewManager.setActivity(null); + } @Override public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { activity = binding.getActivity(); + if (privateViewManager != null) { + privateViewManager.setActivity(activity); + } } @Override public void onDetachedFromActivity() { activity = null; + privateViewManager.setActivity(null); + } private static void register(Context context, BinaryMessenger messenger, FlutterRenderer renderer) { @@ -73,6 +92,9 @@ public Bitmap call() { } }; + privateViewManager = new PrivateViewManager(new InstabugPrivateViewPigeon.InstabugPrivateViewFlutterApi(messenger), new PixelCopyCaptureManager(), new BoundryCaptureManager(renderer)); + InstabugPrivateView.init(messenger, privateViewManager); + ApmApi.init(messenger); BugReportingApi.init(messenger); CrashReportingApi.init(messenger); @@ -82,6 +104,7 @@ public Bitmap call() { RepliesApi.init(messenger); SessionReplayApi.init(messenger); SurveysApi.init(messenger); + } @Nullable diff --git a/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/model/ScreenshotResult.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/model/ScreenshotResult.java new file mode 100644 index 000000000..66a3c51cb --- /dev/null +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/model/ScreenshotResult.java @@ -0,0 +1,21 @@ +package com.instabug.flutter.model; + +import android.graphics.Bitmap; + +public class ScreenshotResult { + private final float pixelRatio; + private final Bitmap screenshot; + + public ScreenshotResult(float pixelRatio, Bitmap screenshot) { + this.pixelRatio = pixelRatio; + this.screenshot = screenshot; + } + + public Bitmap getScreenshot() { + return screenshot; + } + + public float getPixelRatio() { + return pixelRatio; + } +} diff --git a/android/src/main/java/com/instabug/flutter/modules/ApmApi.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/ApmApi.java similarity index 100% rename from android/src/main/java/com/instabug/flutter/modules/ApmApi.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/ApmApi.java diff --git a/android/src/main/java/com/instabug/flutter/modules/BugReportingApi.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/BugReportingApi.java similarity index 100% rename from android/src/main/java/com/instabug/flutter/modules/BugReportingApi.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/BugReportingApi.java diff --git a/android/src/main/java/com/instabug/flutter/modules/CrashReportingApi.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/CrashReportingApi.java similarity index 100% rename from android/src/main/java/com/instabug/flutter/modules/CrashReportingApi.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/CrashReportingApi.java diff --git a/android/src/main/java/com/instabug/flutter/modules/FeatureRequestsApi.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/FeatureRequestsApi.java similarity index 100% rename from android/src/main/java/com/instabug/flutter/modules/FeatureRequestsApi.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/FeatureRequestsApi.java diff --git a/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java similarity index 89% rename from android/src/main/java/com/instabug/flutter/modules/InstabugApi.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java index 0afbbd975..3530cc99c 100644 --- a/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugApi.java @@ -21,6 +21,7 @@ import com.instabug.library.internal.crossplatform.CoreFeaturesState; import com.instabug.library.internal.crossplatform.FeaturesStateListener; import com.instabug.library.internal.crossplatform.InternalCore; +import com.instabug.flutter.util.privateViews.ScreenshotCaptor; import com.instabug.library.Feature; import com.instabug.library.Instabug; import com.instabug.library.InstabugColorTheme; @@ -29,9 +30,11 @@ 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; @@ -46,6 +49,8 @@ import java.io.InputStream; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -133,6 +138,26 @@ public void init(@NonNull String token, @NonNull List invocationEvents, builder.build(); Instabug.setScreenshotProvider(screenshotProvider); + try { + Class myClass = Class.forName("com.instabug.library.Instabug"); + // Enable/Disable native user steps capturing + Method method = myClass.getDeclaredMethod("shouldDisableNativeUserStepsCapturing", boolean.class); + method.setAccessible(true); + method.invoke(null, true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void enableAutoMasking(@NonNull List autoMasking) { + int[] autoMaskingArray = new int[autoMasking.size()]; + for (int i = 0; i < autoMasking.size(); i++) { + String key = autoMasking.get(i); + autoMaskingArray[i] = ArgsRegistry.autoMasking.get(key); + } + + Instabug.setAutoMaskScreenshotsTypes(Arrays.copyOf(autoMaskingArray, autoMaskingArray.length)); } @Override @@ -177,6 +202,33 @@ public void logOut() { Instabug.logoutUser(); } + @Override + public void setEnableUserSteps(@NonNull Boolean isEnabled) { + Instabug.setTrackingUserStepsState(isEnabled ? Feature.State.ENABLED : Feature.State.DISABLED); + } + + @Override + + public void logUserSteps(@NonNull String gestureType, @NonNull String message, @Nullable String viewName) { + try { + final String stepType = ArgsRegistry.gestureStepType.get(gestureType); + final long timeStamp = System.currentTimeMillis(); + String view = ""; + + Method method = Reflection.getMethod(Class.forName("com.instabug.library.Instabug"), "addUserStep", + long.class, String.class, String.class, String.class, String.class); + if (method != null) { + if (viewName != null) { + view = viewName; + } + + method.invoke(null, timeStamp, stepType, message, null, view); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + @Override public void setLocale(@NonNull String locale) { final InstabugLocale resolvedLocale = ArgsRegistry.locales.get(locale); @@ -195,9 +247,6 @@ public void setWelcomeMessageMode(@NonNull String mode) { Instabug.setWelcomeMessageState(resolvedMode); } - @Override - public void setPrimaryColor(@NonNull Long color) { - } @Override public void setSessionProfilerEnabled(@NonNull Boolean enabled) { @@ -507,6 +556,24 @@ 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); + } + }); + } + }); + } @Override public void setNetworkLogBodyEnabled(@NonNull Boolean isEnabled) { diff --git a/android/src/main/java/com/instabug/flutter/modules/InstabugLogApi.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugLogApi.java similarity index 100% rename from android/src/main/java/com/instabug/flutter/modules/InstabugLogApi.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugLogApi.java diff --git a/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugPrivateView.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugPrivateView.java new file mode 100644 index 000000000..53ed0ac23 --- /dev/null +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/InstabugPrivateView.java @@ -0,0 +1,47 @@ +package com.instabug.flutter.modules; + +import android.os.Handler; +import android.os.Looper; + +import com.instabug.flutter.generated.InstabugPrivateViewPigeon; +import com.instabug.flutter.util.privateViews.ScreenshotCaptor; +import com.instabug.library.internal.crossplatform.InternalCore; + +import io.flutter.plugin.common.BinaryMessenger; + +public class InstabugPrivateView implements InstabugPrivateViewPigeon.InstabugPrivateViewHostApi { + PrivateViewManager privateViewManager; + + 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; + InstabugPrivateViewPigeon.InstabugPrivateViewHostApi.setup(messenger, this); + init(); + } + + static long time = System.currentTimeMillis(); + + @Override + public void init() { + InstabugApi.setScreenshotCaptor(new ScreenshotCaptor() { + @Override + public void capture(CapturingCallback listener) { + + (new Handler(Looper.getMainLooper())).postDelayed(new Runnable() { + @Override + public void run() { + time = System.currentTimeMillis(); + privateViewManager.mask(listener); + + } + }, 300); + + + } + }, InternalCore.INSTANCE); + } +} diff --git a/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/PrivateViewManager.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/PrivateViewManager.java new file mode 100644 index 000000000..fd105be5a --- /dev/null +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/PrivateViewManager.java @@ -0,0 +1,147 @@ +package com.instabug.flutter.modules; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.os.Build; + +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; + +import com.instabug.flutter.generated.InstabugPrivateViewPigeon; +import com.instabug.flutter.model.ScreenshotResult; +import com.instabug.flutter.modules.capturing.CaptureManager; +import com.instabug.flutter.modules.capturing.ScreenshotResultCallback; +import com.instabug.flutter.util.ThreadManager; +import com.instabug.flutter.util.privateViews.ScreenshotCaptor; + +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicReference; + +public class PrivateViewManager { + private static final String THREAD_NAME = "IBG-Flutter-Screenshot"; + public static final String EXCEPTION_MESSAGE = "IBG-Flutter-Screenshot: error capturing screenshot"; + + private final ExecutorService screenshotExecutor = Executors.newSingleThreadExecutor(runnable -> { + Thread thread = new Thread(runnable); + thread.setName(THREAD_NAME); + return thread; + }); + + private final InstabugPrivateViewPigeon.InstabugPrivateViewFlutterApi instabugPrivateViewApi; + private Activity activity; + final CaptureManager pixelCopyScreenshotCaptor; + final CaptureManager boundryScreenshotCaptor; + + public PrivateViewManager(@NonNull InstabugPrivateViewPigeon.InstabugPrivateViewFlutterApi instabugPrivateViewApi, CaptureManager pixelCopyCaptureManager, CaptureManager boundryCaptureManager) { + this.instabugPrivateViewApi = instabugPrivateViewApi; + this.pixelCopyScreenshotCaptor = pixelCopyCaptureManager; + this.boundryScreenshotCaptor = boundryCaptureManager; + + + } + + public void setActivity(Activity activity) { + this.activity = activity; + } + + + public void mask(ScreenshotCaptor.CapturingCallback capturingCallback) { + if (activity != null) { + CountDownLatch latch = new CountDownLatch(1); + AtomicReference> privateViews = new AtomicReference<>(); + final ScreenshotResultCallback boundryScreenshotResult = new ScreenshotResultCallback() { + + @Override + public void onScreenshotResult(ScreenshotResult screenshotResult) { + processScreenshot(screenshotResult, privateViews, latch, capturingCallback); + + } + + @Override + public void onError() { + capturingCallback.onCapturingFailure(new Exception(EXCEPTION_MESSAGE)); + } + }; + + try { + ThreadManager.runOnMainThread(new Runnable() { + @Override + public void run() { + instabugPrivateViewApi.getPrivateViews(result -> { + privateViews.set(result); + latch.countDown(); + }); + } + }); + + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + pixelCopyScreenshotCaptor.capture(activity, new ScreenshotResultCallback() { + @Override + public void onScreenshotResult(ScreenshotResult result) { + processScreenshot(result, privateViews, latch, capturingCallback); + + } + + @Override + public void onError() { + boundryScreenshotCaptor.capture(activity, boundryScreenshotResult); + + } + }); + } else { + boundryScreenshotCaptor.capture(activity, boundryScreenshotResult); + } + + } catch (Exception e) { + capturingCallback.onCapturingFailure(e); + } + } else { + capturingCallback.onCapturingFailure(new Exception(EXCEPTION_MESSAGE)); + } + } + + + private void processScreenshot(ScreenshotResult result, AtomicReference> privateViews, CountDownLatch latch, ScreenshotCaptor.CapturingCallback capturingCallback) { + screenshotExecutor.execute(() -> { + try { + latch.await(); // Wait + Bitmap bitmap = result.getScreenshot(); + maskPrivateViews(result, privateViews.get()); + capturingCallback.onCapturingSuccess(bitmap); + long lastTime = System.currentTimeMillis(); + System.out.println("Time:" + (lastTime - InstabugPrivateView.time)); + + } catch (InterruptedException e) { + capturingCallback.onCapturingFailure(e); + } + }); + } + + @VisibleForTesting + public void maskPrivateViews(ScreenshotResult result, List privateViews) { + try { + if (privateViews == null || privateViews.isEmpty()) return; + + Bitmap bitmap = result.getScreenshot(); + float pixelRatio = result.getPixelRatio(); + Canvas canvas = new Canvas(bitmap); + Paint paint = new Paint(); // Default color is black + + for (int i = 0; i < privateViews.size(); i += 4) { + float left = privateViews.get(i).floatValue() * pixelRatio; + float top = privateViews.get(i + 1).floatValue() * pixelRatio; + float right = privateViews.get(i + 2).floatValue() * pixelRatio; + float bottom = privateViews.get(i + 3).floatValue() * pixelRatio; + canvas.drawRect(left, top, right, bottom, paint); // Mask private view + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/android/src/main/java/com/instabug/flutter/modules/RepliesApi.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/RepliesApi.java similarity index 100% rename from android/src/main/java/com/instabug/flutter/modules/RepliesApi.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/RepliesApi.java diff --git a/android/src/main/java/com/instabug/flutter/modules/SessionReplayApi.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/SessionReplayApi.java similarity index 100% rename from android/src/main/java/com/instabug/flutter/modules/SessionReplayApi.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/SessionReplayApi.java diff --git a/android/src/main/java/com/instabug/flutter/modules/SurveysApi.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/SurveysApi.java similarity index 100% rename from android/src/main/java/com/instabug/flutter/modules/SurveysApi.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/SurveysApi.java diff --git a/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/BoundryCaptureManager.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/BoundryCaptureManager.java new file mode 100644 index 000000000..6f8409749 --- /dev/null +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/BoundryCaptureManager.java @@ -0,0 +1,43 @@ +package com.instabug.flutter.modules.capturing; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.util.DisplayMetrics; +import android.view.View; + +import com.instabug.flutter.model.ScreenshotResult; +import com.instabug.flutter.util.ThreadManager; + +import io.flutter.embedding.engine.renderer.FlutterRenderer; + +public class BoundryCaptureManager implements CaptureManager { + FlutterRenderer renderer; + + public BoundryCaptureManager(FlutterRenderer renderer) { + this.renderer = renderer; + } + + @Override + public void capture(Activity activity, ScreenshotResultCallback screenshotResultCallback) { + ThreadManager.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + if (activity == null) { + screenshotResultCallback.onError(); + return; + } + View rootView = activity.getWindow().getDecorView().getRootView(); + rootView.setDrawingCacheEnabled(true); + Bitmap bitmap = renderer.getBitmap(); + rootView.setDrawingCacheEnabled(false); + DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics(); + screenshotResultCallback.onScreenshotResult(new ScreenshotResult(displayMetrics.density, bitmap)); + + } catch (Exception e) { + screenshotResultCallback.onError(); + } + } + }); + } +} diff --git a/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/CaptureManager.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/CaptureManager.java new file mode 100644 index 000000000..f15aa4780 --- /dev/null +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/CaptureManager.java @@ -0,0 +1,7 @@ +package com.instabug.flutter.modules.capturing; + +import android.app.Activity; + +public interface CaptureManager { + void capture(Activity activity, ScreenshotResultCallback screenshotResultCallback); +} diff --git a/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/PixelCopyCaptureManager.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/PixelCopyCaptureManager.java new file mode 100644 index 000000000..be19f1ca6 --- /dev/null +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/PixelCopyCaptureManager.java @@ -0,0 +1,86 @@ +package com.instabug.flutter.modules.capturing; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.util.DisplayMetrics; +import android.view.PixelCopy; +import android.view.SurfaceView; + +import androidx.annotation.RequiresApi; + +import com.instabug.flutter.model.ScreenshotResult; +import com.instabug.library.util.memory.MemoryUtils; + +import io.flutter.embedding.android.FlutterActivity; +import io.flutter.embedding.android.FlutterFragment; +import io.flutter.embedding.android.FlutterView; + +public class PixelCopyCaptureManager implements CaptureManager { + + @RequiresApi(api = Build.VERSION_CODES.N) + @Override + public void capture(Activity activity, ScreenshotResultCallback screenshotResultCallback) { + FlutterView flutterView = getFlutterView(activity); + if (flutterView == null || !isValidFlutterView(flutterView)) { + screenshotResultCallback.onError(); + return; + } + + SurfaceView surfaceView = (SurfaceView) flutterView.getChildAt(0); + Bitmap bitmap = createBitmapFromSurface(surfaceView); + + if (bitmap == null) { + screenshotResultCallback.onError(); + return; + } + + PixelCopy.request(surfaceView, bitmap, copyResult -> { + if (copyResult == PixelCopy.SUCCESS) { + DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics(); + screenshotResultCallback.onScreenshotResult(new ScreenshotResult(displayMetrics.density, bitmap)); + } else { + screenshotResultCallback.onError(); + } + }, new Handler(Looper.getMainLooper())); + } + + private FlutterView getFlutterView(Activity activity) { + FlutterView flutterViewInActivity = activity.findViewById(FlutterActivity.FLUTTER_VIEW_ID); + FlutterView flutterViewInFragment = activity.findViewById(FlutterFragment.FLUTTER_VIEW_ID); + return flutterViewInActivity != null ? flutterViewInActivity : flutterViewInFragment; + } + + private boolean isValidFlutterView(FlutterView flutterView) { + boolean hasChildren = flutterView.getChildCount() > 0; + boolean isSurfaceView = flutterView.getChildAt(0) instanceof SurfaceView; + return hasChildren && isSurfaceView; + } + + private Bitmap createBitmapFromSurface(SurfaceView surfaceView) { + int width = surfaceView.getWidth(); + int height = surfaceView.getHeight(); + + if (width <= 0 || height <= 0) { + return null; + } + Bitmap bitmap; + try { + if (((long) width * height * 4) < MemoryUtils.getFreeMemory(surfaceView.getContext())) { + // ARGB_8888 store each pixel in 4 bytes + bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + } else { + // RGB_565 store each pixel in 2 bytes + bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + } + + } catch (IllegalArgumentException | OutOfMemoryError e) { + bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + } + + + return bitmap; + } +} diff --git a/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/ScreenshotResultCallback.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/ScreenshotResultCallback.java new file mode 100644 index 000000000..e01b9b95d --- /dev/null +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/modules/capturing/ScreenshotResultCallback.java @@ -0,0 +1,9 @@ +package com.instabug.flutter.modules.capturing; + + +import com.instabug.flutter.model.ScreenshotResult; + +public interface ScreenshotResultCallback { + void onScreenshotResult(ScreenshotResult screenshotResult); + void onError(); +} diff --git a/android/src/main/java/com/instabug/flutter/util/ArgsRegistry.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/util/ArgsRegistry.java similarity index 94% rename from android/src/main/java/com/instabug/flutter/util/ArgsRegistry.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/util/ArgsRegistry.java index c38028707..db41068da 100644 --- a/android/src/main/java/com/instabug/flutter/util/ArgsRegistry.java +++ b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/util/ArgsRegistry.java @@ -9,6 +9,7 @@ import com.instabug.featuresrequest.ActionType; import com.instabug.library.InstabugColorTheme; import com.instabug.library.InstabugCustomTextPlaceHolder.Key; +import com.instabug.library.MaskingType; import com.instabug.library.OnSdkDismissCallback.DismissType; import com.instabug.library.ReproMode; import com.instabug.library.extendedbugreport.ExtendedBugReport; @@ -16,6 +17,7 @@ import com.instabug.library.invocation.InstabugInvocationEvent; import com.instabug.library.invocation.util.InstabugFloatingButtonEdge; import com.instabug.library.invocation.util.InstabugVideoRecordingButtonPosition; +import com.instabug.library.model.StepType; import com.instabug.library.ui.onboarding.WelcomeMessage; import java.util.HashMap; @@ -57,6 +59,14 @@ public T get(Object key) { put("ColorTheme.light", InstabugColorTheme.InstabugColorThemeLight); put("ColorTheme.dark", InstabugColorTheme.InstabugColorThemeDark); }}; + + public static final ArgsMap autoMasking = new ArgsMap() {{ + put("AutoMasking.labels", MaskingType.LABELS); + put("AutoMasking.textInputs", MaskingType.TEXT_INPUTS); + put("AutoMasking.media", MaskingType.MEDIA); + put("AutoMasking.none", MaskingType.MASK_NOTHING); + }}; + public static ArgsMap nonFatalExceptionLevel = new ArgsMap() {{ put("NonFatalExceptionLevel.critical", IBGNonFatalException.Level.CRITICAL); put("NonFatalExceptionLevel.error", IBGNonFatalException.Level.ERROR); @@ -212,4 +222,13 @@ public T get(Object key) { put("CustomTextPlaceHolderKey.messagesNotificationAndOthers", Key.CHATS_MULTIPLE_MESSAGE_NOTIFICATION); put("CustomTextPlaceHolderKey.insufficientContentMessage", Key.COMMENT_FIELD_INSUFFICIENT_CONTENT); }}; + + public static final ArgsMap gestureStepType = new ArgsMap() {{ + put("GestureType.swipe", StepType.SWIPE); + put("GestureType.scroll", StepType.SCROLL); + put("GestureType.tap", StepType.TAP); + put("GestureType.pinch", StepType.PINCH); + put("GestureType.longPress", StepType.LONG_PRESS); + put("GestureType.doubleTap", StepType.DOUBLE_TAP); + }}; } diff --git a/android/src/main/java/com/instabug/flutter/util/Reflection.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/util/Reflection.java similarity index 100% rename from android/src/main/java/com/instabug/flutter/util/Reflection.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/util/Reflection.java diff --git a/android/src/main/java/com/instabug/flutter/util/ThreadManager.java b/packages/instabug_flutter/android/src/main/java/com/instabug/flutter/util/ThreadManager.java similarity index 100% rename from android/src/main/java/com/instabug/flutter/util/ThreadManager.java rename to packages/instabug_flutter/android/src/main/java/com/instabug/flutter/util/ThreadManager.java 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/android/src/test/java/com/instabug/flutter/ApmApiTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/ApmApiTest.java similarity index 100% rename from android/src/test/java/com/instabug/flutter/ApmApiTest.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/ApmApiTest.java diff --git a/android/src/test/java/com/instabug/flutter/ArgsRegistryTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/ArgsRegistryTest.java similarity index 100% rename from android/src/test/java/com/instabug/flutter/ArgsRegistryTest.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/ArgsRegistryTest.java diff --git a/android/src/test/java/com/instabug/flutter/BugReportingApiTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/BugReportingApiTest.java similarity index 100% rename from android/src/test/java/com/instabug/flutter/BugReportingApiTest.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/BugReportingApiTest.java diff --git a/android/src/test/java/com/instabug/flutter/CrashReportingApiTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/CrashReportingApiTest.java similarity index 100% rename from android/src/test/java/com/instabug/flutter/CrashReportingApiTest.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/CrashReportingApiTest.java diff --git a/android/src/test/java/com/instabug/flutter/FeatureRequestsApiTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/FeatureRequestsApiTest.java similarity index 100% rename from android/src/test/java/com/instabug/flutter/FeatureRequestsApiTest.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/FeatureRequestsApiTest.java diff --git a/android/src/test/java/com/instabug/flutter/InstabugApiTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/InstabugApiTest.java similarity index 90% rename from android/src/test/java/com/instabug/flutter/InstabugApiTest.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/InstabugApiTest.java index 8e9999e52..00c529fd3 100644 --- a/android/src/test/java/com/instabug/flutter/InstabugApiTest.java +++ b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/InstabugApiTest.java @@ -6,8 +6,10 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockConstruction; @@ -30,6 +32,7 @@ import com.instabug.bug.BugReporting; import com.instabug.flutter.generated.InstabugPigeon; import com.instabug.flutter.modules.InstabugApi; +import com.instabug.flutter.util.ArgsRegistry; import com.instabug.flutter.util.GlobalMocks; import com.instabug.flutter.util.MockReflected; import com.instabug.library.Feature; @@ -38,6 +41,7 @@ import com.instabug.library.InstabugCustomTextPlaceHolder; import com.instabug.library.IssueType; import com.instabug.library.LogLevel; +import com.instabug.library.MaskingType; import com.instabug.library.Platform; import com.instabug.library.ReproConfigurations; import com.instabug.library.ReproMode; @@ -46,8 +50,14 @@ import com.instabug.library.internal.crossplatform.FeaturesStateListener; import com.instabug.library.internal.crossplatform.InternalCore; import com.instabug.library.featuresflags.model.IBGFeatureFlag; +import com.instabug.library.internal.crossplatform.CoreFeature; +import com.instabug.library.internal.crossplatform.FeaturesStateListener; +import com.instabug.library.internal.crossplatform.InternalCore; +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 com.instabug.survey.Surveys; import com.instabug.survey.callbacks.OnShowCallback; @@ -78,10 +88,18 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.mockito.verification.VerificationMode; + +import kotlin.jvm.functions.Function1; + +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.mockito.verification.VerificationMode; import android.graphics.Typeface; +import android.graphics.Typeface; + public class InstabugApiTest { private final Callable screenshotProvider = () -> mock(Bitmap.class); private final Application mContext = mock(Application.class); @@ -709,5 +727,56 @@ public void testSetFullscreenDisabled() { mInstabug.verify(() -> Instabug.setFullscreen(isEnabled)); } + @Test + public void testSetScreenshotCaptor() { + InternalCore internalCore = spy(InternalCore.INSTANCE); + + InstabugApi.setScreenshotCaptor(any(), internalCore); + verify(internalCore)._setScreenshotCaptor(any(ScreenshotCaptor.class)); + } + + @Test + public void testSetUserStepsEnabledGivenTrue() { + boolean isEnabled = true; + + api.setEnableUserSteps(isEnabled); + + mInstabug.verify(() -> Instabug.setTrackingUserStepsState(Feature.State.ENABLED)); + } + + @Test + public void testSetUserStepsEnabledGivenFalse() { + boolean isEnabled = false; + + api.setEnableUserSteps(isEnabled); + + mInstabug.verify(() -> Instabug.setTrackingUserStepsState(Feature.State.DISABLED)); + } + + @Test + public void testLogUserSteps() { + + final String gestureType = "GestureType.tap"; + final String message = "message"; + final String view = "view"; + + api.logUserSteps(gestureType, message,view); + + reflected.verify(() -> MockReflected.addUserStep(anyLong(), eq(ArgsRegistry.gestureStepType.get(gestureType)), eq(message), isNull(), eq(view))); + + } + + @Test + public void testAutoMasking() { + String maskLabel = "AutoMasking.labels"; + String maskTextInputs = "AutoMasking.textInputs"; + String maskMedia = "AutoMasking.media"; + String maskNone = "AutoMasking.none"; + + + api.enableAutoMasking(List.of(maskLabel, maskMedia, maskTextInputs,maskNone)); + + mInstabug.verify(() -> Instabug.setAutoMaskScreenshotsTypes(MaskingType.LABELS,MaskingType.MEDIA,MaskingType.TEXT_INPUTS,MaskingType.MASK_NOTHING)); + } } diff --git a/android/src/test/java/com/instabug/flutter/InstabugLogApiTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/InstabugLogApiTest.java similarity index 100% rename from android/src/test/java/com/instabug/flutter/InstabugLogApiTest.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/InstabugLogApiTest.java diff --git a/android/src/test/java/com/instabug/flutter/RepliesApiTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/RepliesApiTest.java similarity index 100% rename from android/src/test/java/com/instabug/flutter/RepliesApiTest.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/RepliesApiTest.java diff --git a/android/src/test/java/com/instabug/flutter/SessionReplayApiTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/SessionReplayApiTest.java similarity index 100% rename from android/src/test/java/com/instabug/flutter/SessionReplayApiTest.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/SessionReplayApiTest.java diff --git a/android/src/test/java/com/instabug/flutter/SurveysApiTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/SurveysApiTest.java similarity index 100% rename from android/src/test/java/com/instabug/flutter/SurveysApiTest.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/SurveysApiTest.java diff --git a/android/src/test/java/com/instabug/flutter/util/Callback.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/Callback.java similarity index 100% rename from android/src/test/java/com/instabug/flutter/util/Callback.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/Callback.java diff --git a/android/src/test/java/com/instabug/flutter/util/GlobalMocks.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/GlobalMocks.java similarity index 93% rename from android/src/test/java/com/instabug/flutter/util/GlobalMocks.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/GlobalMocks.java index 9ab7802ec..797921341 100644 --- a/android/src/test/java/com/instabug/flutter/util/GlobalMocks.java +++ b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/GlobalMocks.java @@ -113,6 +113,14 @@ public static void setUp() throws NoSuchMethodException { Method mEndScreenLoadingCP = MockReflected.class.getDeclaredMethod("endScreenLoadingCP", Long.class, Long.class); mEndScreenLoadingCP.setAccessible(true); reflection.when(() -> Reflection.getMethod(Class.forName("com.instabug.apm.APM"), "endScreenLoadingCP", Long.class, Long.class)).thenReturn(mEndScreenLoadingCP); + + + Method mAddUserStepCp = MockReflected.class.getDeclaredMethod("addUserStep", + long.class, String.class, String.class, String.class, String.class); + mAddUserStepCp.setAccessible(true); + reflection.when(() -> Reflection.getMethod(Class.forName("com.instabug.library.Instabug"), "addUserStep", + long.class, String.class, String.class, String.class, String.class)).thenReturn(mAddUserStepCp);; + } public static void close() { diff --git a/android/src/test/java/com/instabug/flutter/util/MockReflected.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/MockReflected.java similarity index 92% rename from android/src/test/java/com/instabug/flutter/util/MockReflected.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/MockReflected.java index 9bf03cc53..74249675a 100644 --- a/android/src/test/java/com/instabug/flutter/util/MockReflected.java +++ b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/MockReflected.java @@ -5,6 +5,7 @@ import com.instabug.apm.networkinterception.cp.APMCPNetworkLog; import com.instabug.crash.models.IBGNonFatalException; +import com.instabug.library.model.StepType; import org.json.JSONObject; @@ -53,4 +54,6 @@ public static void startUiTraceCP(String screenName, Long microTimeStamp, Long t public static void reportScreenLoadingCP(Long startTimeStampMicro, Long durationMicro, Long uiTraceId) {} public static void endScreenLoadingCP(Long timeStampMicro, Long uiTraceId) {} + public static void addUserStep(long timestamp, @StepType String stepType, String message, String label, String viewType) { + } } diff --git a/android/src/test/java/com/instabug/flutter/util/MockResult.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/MockResult.java similarity index 100% rename from android/src/test/java/com/instabug/flutter/util/MockResult.java rename to packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/MockResult.java diff --git a/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/private_views/BoundryScreenshotCaptorTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/private_views/BoundryScreenshotCaptorTest.java new file mode 100644 index 000000000..a555345e0 --- /dev/null +++ b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/private_views/BoundryScreenshotCaptorTest.java @@ -0,0 +1,77 @@ +package com.instabug.flutter.util.private_views; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.robolectric.Shadows.shadowOf; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.os.Looper; + +import com.instabug.flutter.model.ScreenshotResult; +import com.instabug.flutter.modules.capturing.BoundryCaptureManager; +import com.instabug.flutter.modules.capturing.CaptureManager; +import com.instabug.flutter.modules.capturing.ScreenshotResultCallback; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatcher; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import io.flutter.embedding.engine.renderer.FlutterRenderer; + +@RunWith(RobolectricTestRunner.class) +@Config(sdk = {28}, manifest = Config.NONE) +public class BoundryScreenshotCaptorTest { + private Activity activityMock; + private Bitmap bitmap; + private CaptureManager captureManager; + + @Before + public void setUp() { + FlutterRenderer rendererMock = mock(FlutterRenderer.class); + activityMock = spy(Robolectric.buildActivity(Activity.class).setup().create().start().resume().get()); + bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888); + when(rendererMock.getBitmap()).thenReturn(bitmap); + captureManager = new BoundryCaptureManager(rendererMock); + } + + @Test + public void testCaptureGivenEmptyActivity() { + ScreenshotResultCallback mockCallback = mock(ScreenshotResultCallback.class); + + captureManager.capture(null, mockCallback); + shadowOf(Looper.getMainLooper()).idle(); + + verify(mockCallback).onError(); + verify(mockCallback, never()).onScreenshotResult(any(ScreenshotResult.class)); + + } + + @Test + public void testCapture() { + ScreenshotResultCallback mockCallback = mock(ScreenshotResultCallback.class); + captureManager.capture(activityMock, mockCallback); + shadowOf(Looper.getMainLooper()).idle(); + + verify(mockCallback, never()).onError(); + verify(mockCallback).onScreenshotResult(argThat(new ArgumentMatcher() { + @Override + public boolean matches(ScreenshotResult argument) { + return (Math.abs(activityMock.getResources().getDisplayMetrics().density - argument.getPixelRatio()) < 0.01)&& + bitmap == argument.getScreenshot(); + + } + })); + } + + +} diff --git a/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/private_views/PixelCopyScreenshotCaptorTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/private_views/PixelCopyScreenshotCaptorTest.java new file mode 100644 index 000000000..868712312 --- /dev/null +++ b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/private_views/PixelCopyScreenshotCaptorTest.java @@ -0,0 +1,91 @@ +package com.instabug.flutter.util.private_views; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.robolectric.Shadows.shadowOf; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.os.Looper; +import android.view.SurfaceView; + +import com.instabug.flutter.model.ScreenshotResult; +import com.instabug.flutter.modules.capturing.CaptureManager; +import com.instabug.flutter.modules.capturing.PixelCopyCaptureManager; +import com.instabug.flutter.modules.capturing.ScreenshotResultCallback; +import com.instabug.library.util.memory.MemoryUtils; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockedStatic; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import io.flutter.embedding.android.FlutterActivity; +import io.flutter.embedding.android.FlutterView; +import io.flutter.embedding.engine.renderer.FlutterRenderer; + +@RunWith(RobolectricTestRunner.class) +@Config(sdk = {28}, manifest = Config.NONE) +public class PixelCopyScreenshotCaptorTest { + private Activity activityMock; + private Bitmap bitmap; + private CaptureManager captureManager; + + @Before + public void setUp() { + FlutterRenderer rendererMock = mock(FlutterRenderer.class); + activityMock = spy(Robolectric.buildActivity(Activity.class).setup().create().start().resume().get()); + bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888); + when(rendererMock.getBitmap()).thenReturn(bitmap); + captureManager = new PixelCopyCaptureManager(); + } + + @Test + public void testCaptureWithPixelCopyGivenEmptyView() { + + ScreenshotResultCallback mockScreenshotResultCallback = mock(ScreenshotResultCallback.class); + when(activityMock.findViewById(FlutterActivity.FLUTTER_VIEW_ID)).thenReturn(null); + captureManager.capture(activityMock,mockScreenshotResultCallback); + + verify(mockScreenshotResultCallback).onError(); + } + + @Test + public void testCaptureWithPixelCopy() { + try (MockedStatic mockedStatic = mockStatic(MemoryUtils.class)) { + mockedStatic.when(() -> MemoryUtils.getFreeMemory(any())).thenReturn(Long.MAX_VALUE); + + mockFlutterViewInPixelCopy(); + + ScreenshotResultCallback mockScreenshotResultCallback = mock(ScreenshotResultCallback.class); + + + captureManager.capture(activityMock, mockScreenshotResultCallback); + shadowOf(Looper.getMainLooper()).idle(); + + verify(mockScreenshotResultCallback, timeout(1000)).onScreenshotResult(any(ScreenshotResult.class)); // PixelCopy success + + } + } + + + private void mockFlutterViewInPixelCopy() { + + SurfaceView mockSurfaceView = mock(SurfaceView.class); + FlutterView flutterView = mock(FlutterView.class); + when(flutterView.getChildAt(0)).thenReturn(mockSurfaceView); + when(flutterView.getChildCount()).thenReturn(1); + + when(activityMock.findViewById(FlutterActivity.FLUTTER_VIEW_ID)).thenReturn(flutterView); + when(mockSurfaceView.getWidth()).thenReturn(100); + when(mockSurfaceView.getHeight()).thenReturn(100); + } +} diff --git a/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/private_views/PrivateViewManagerTest.java b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/private_views/PrivateViewManagerTest.java new file mode 100644 index 000000000..a996fb8a2 --- /dev/null +++ b/packages/instabug_flutter/android/src/test/java/com/instabug/flutter/util/private_views/PrivateViewManagerTest.java @@ -0,0 +1,146 @@ +package com.instabug.flutter.util.private_views; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.robolectric.Shadows.shadowOf; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.os.Build; +import android.os.Looper; +import android.view.SurfaceView; + +import com.instabug.flutter.generated.InstabugPrivateViewPigeon; +import com.instabug.flutter.model.ScreenshotResult; +import com.instabug.flutter.modules.PrivateViewManager; +import com.instabug.flutter.modules.capturing.BoundryCaptureManager; +import com.instabug.flutter.modules.capturing.CaptureManager; +import com.instabug.flutter.modules.capturing.PixelCopyCaptureManager; +import com.instabug.flutter.util.privateViews.ScreenshotCaptor; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.util.Arrays; +import java.util.List; + +import io.flutter.embedding.android.FlutterActivity; +import io.flutter.embedding.android.FlutterView; +import io.flutter.embedding.engine.renderer.FlutterRenderer; + +@RunWith(RobolectricTestRunner.class) +@Config(sdk = {28}, manifest = Config.NONE) +public class PrivateViewManagerTest { + + private PrivateViewManager privateViewManager; + private InstabugPrivateViewPigeon.InstabugPrivateViewFlutterApi InstabugPrivateViewFlutterApiMock; + private Activity activityMock; + private Bitmap bitmap; + private CaptureManager pixelCopyScreenCaptor, boundryScreenCaptor; + + @Before + public void setUp() { + InstabugPrivateViewFlutterApiMock = mock(InstabugPrivateViewPigeon.InstabugPrivateViewFlutterApi.class); + FlutterRenderer rendererMock = mock(FlutterRenderer.class); + activityMock = spy(Robolectric.buildActivity(Activity.class).setup().create().start().resume().get()); + bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888); + when(rendererMock.getBitmap()).thenReturn(bitmap); + pixelCopyScreenCaptor = spy(new PixelCopyCaptureManager()); + boundryScreenCaptor = spy(new BoundryCaptureManager(rendererMock)); + privateViewManager = spy(new PrivateViewManager(InstabugPrivateViewFlutterApiMock, pixelCopyScreenCaptor, boundryScreenCaptor)); + privateViewManager.setActivity(activityMock); + + } + + + @Test + public void testMaskGivenEmptyActivity() { + com.instabug.flutter.util.privateViews.ScreenshotCaptor.CapturingCallback capturingCallbackMock = mock(ScreenshotCaptor.CapturingCallback.class); + privateViewManager.setActivity(null); + privateViewManager.mask(capturingCallbackMock); + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Throwable.class); + verify(capturingCallbackMock).onCapturingFailure(argumentCaptor.capture()); + assertEquals( PrivateViewManager.EXCEPTION_MESSAGE, argumentCaptor.getValue().getMessage()); + } + + @Test + public void testMask() throws InterruptedException { + com.instabug.flutter.util.privateViews.ScreenshotCaptor.CapturingCallback capturingCallbackMock = mock(com.instabug.flutter.util.privateViews.ScreenshotCaptor.CapturingCallback.class); + doAnswer(invocation -> { + InstabugPrivateViewPigeon.InstabugPrivateViewFlutterApi.Reply> callback = invocation.getArgument(0); // Get the callback + callback.reply(Arrays.asList(10.0, 20.0, 100.0, 200.0)); // Trigger the success callback + return null; + }).when(InstabugPrivateViewFlutterApiMock).getPrivateViews(any(InstabugPrivateViewPigeon.InstabugPrivateViewFlutterApi.Reply.class)); // Mock the method call + + + // Trigger the mask operation + privateViewManager.mask(capturingCallbackMock); + // Mock that latch.await() has been called + shadowOf(Looper.getMainLooper()).idle(); + + // Simulate a successful bitmap capture + verify(capturingCallbackMock, timeout(1000)).onCapturingSuccess(bitmap); + } + + + private void mockFlutterViewInPixelCopy() { + SurfaceView mockSurfaceView = mock(SurfaceView.class); + FlutterView flutterView = mock(FlutterView.class); + when(flutterView.getChildAt(0)).thenReturn(mockSurfaceView); + when(flutterView.getChildCount()).thenReturn(1); + + when(activityMock.findViewById(FlutterActivity.FLUTTER_VIEW_ID)).thenReturn(flutterView); + when(mockSurfaceView.getWidth()).thenReturn(100); + when(mockSurfaceView.getHeight()).thenReturn(100); + } + + + @Test + public void testMaskPrivateViews() { + ScreenshotResult mockResult = mock(ScreenshotResult.class); + when(mockResult.getScreenshot()).thenReturn(Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888)); + when(mockResult.getPixelRatio()).thenReturn(2.0f); + + List privateViews = Arrays.asList(10.0, 20.0, 100.0, 200.0); + + privateViewManager.maskPrivateViews(mockResult, privateViews); + + assertNotNull(mockResult.getScreenshot()); + } + + @Test + @Config(sdk = {Build.VERSION_CODES.M}) + public void testMaskShouldGetScreenshotWhenAPIVersionLessThan28() { + ScreenshotCaptor.CapturingCallback capturingCallbackMock = mock(ScreenshotCaptor.CapturingCallback.class); + privateViewManager.mask(capturingCallbackMock); + shadowOf(Looper.getMainLooper()).idle(); + + verify(boundryScreenCaptor).capture(any(), any()); + + } + + @Test + public void testMaskShouldCallPixelCopyWhenAPIVersionMoreThan28() { + com.instabug.flutter.util.privateViews.ScreenshotCaptor.CapturingCallback capturingCallbackMock = mock(com.instabug.flutter.util.privateViews.ScreenshotCaptor.CapturingCallback.class); + mockFlutterViewInPixelCopy(); + privateViewManager.mask(capturingCallbackMock); + shadowOf(Looper.getMainLooper()).idle(); + verify(boundryScreenCaptor, never()).capture(any(), any()); + verify(pixelCopyScreenCaptor).capture(any(), any()); + + + } +} \ No newline at end of file diff --git a/android/upload_symbols.gradle b/packages/instabug_flutter/android/upload_symbols.gradle similarity index 100% rename from android/upload_symbols.gradle rename to packages/instabug_flutter/android/upload_symbols.gradle diff --git a/packages/instabug_flutter/dangerfile.ts b/packages/instabug_flutter/dangerfile.ts new file mode 100644 index 000000000..670ae0b05 --- /dev/null +++ b/packages/instabug_flutter/dangerfile.ts @@ -0,0 +1,37 @@ +import { danger, fail, schedule, warn } from 'danger'; +import collectCoverage, { ReportType } from '@instabug/danger-plugin-coverage'; + +const hasSourceChanges = danger.git.modified_files.some((file) => + file.startsWith('lib/') +); +const declaredTrivial = + !hasSourceChanges || + danger.github.issue.labels.some((label) => label.name === 'trivial'); + +// Make sure PR has a description. +async function hasDescription() { + const linesOfCode = (await danger.git.linesOfCode()) ?? 0; + const hasNoDescription = danger.github.pr.body.includes( + '> Description goes here' + ); + if (hasNoDescription && linesOfCode > 10) { + fail( + 'Please provide a summary of the changes in the pull request description.' + ); + } + + if (!danger.git.modified_files.includes('CHANGELOG.md') && !declaredTrivial) { + warn( + 'You have not included a CHANGELOG entry! \nYou can find it at [CHANGELOG.md](https://github.com/Instabug/Instabug-Flutter/blob/master/CHANGELOG.md).' + ); + } +} + +schedule(hasDescription()); + +collectCoverage({ + label: 'Dart', + type: ReportType.LCOV, + filePath: 'coverage/lcov.info', + threshold: 80, +}); diff --git a/example/.gitignore b/packages/instabug_flutter/example/.gitignore similarity index 100% rename from example/.gitignore rename to packages/instabug_flutter/example/.gitignore diff --git a/example/.metadata b/packages/instabug_flutter/example/.metadata similarity index 100% rename from example/.metadata rename to packages/instabug_flutter/example/.metadata diff --git a/example/README.md b/packages/instabug_flutter/example/README.md similarity index 100% rename from example/README.md rename to packages/instabug_flutter/example/README.md diff --git a/example/android/.gitignore b/packages/instabug_flutter/example/android/.gitignore similarity index 100% rename from example/android/.gitignore rename to packages/instabug_flutter/example/android/.gitignore diff --git a/example/android/app/build.gradle b/packages/instabug_flutter/example/android/app/build.gradle similarity index 99% rename from example/android/app/build.gradle rename to packages/instabug_flutter/example/android/app/build.gradle index 8e777d514..f29331c1f 100644 --- a/example/android/app/build.gradle +++ b/packages/instabug_flutter/example/android/app/build.gradle @@ -1,3 +1,4 @@ + plugins { id "com.android.application" id "kotlin-android" diff --git a/packages/instabug_flutter/example/android/app/src/debug/AndroidManifest.xml b/packages/instabug_flutter/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..f880684a6 --- /dev/null +++ b/packages/instabug_flutter/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/example/android/app/src/main/AndroidManifest.xml b/packages/instabug_flutter/example/android/app/src/main/AndroidManifest.xml similarity index 100% rename from example/android/app/src/main/AndroidManifest.xml rename to packages/instabug_flutter/example/android/app/src/main/AndroidManifest.xml diff --git a/example/android/app/src/main/kotlin/com/example/InstabugSample/InstabugExampleMethodCallHandler.kt b/packages/instabug_flutter/example/android/app/src/main/kotlin/com/example/InstabugSample/InstabugExampleMethodCallHandler.kt similarity index 100% rename from example/android/app/src/main/kotlin/com/example/InstabugSample/InstabugExampleMethodCallHandler.kt rename to packages/instabug_flutter/example/android/app/src/main/kotlin/com/example/InstabugSample/InstabugExampleMethodCallHandler.kt diff --git a/example/android/app/src/main/kotlin/com/example/InstabugSample/MainActivity.kt b/packages/instabug_flutter/example/android/app/src/main/kotlin/com/example/InstabugSample/MainActivity.kt similarity index 100% rename from example/android/app/src/main/kotlin/com/example/InstabugSample/MainActivity.kt rename to packages/instabug_flutter/example/android/app/src/main/kotlin/com/example/InstabugSample/MainActivity.kt diff --git a/packages/instabug_flutter/example/android/app/src/main/res/drawable/launch_background.xml b/packages/instabug_flutter/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000..304732f88 --- /dev/null +++ b/packages/instabug_flutter/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/instabug_flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/instabug_flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/instabug_flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/instabug_flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/instabug_flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/example/android/app/src/main/res/values/styles.xml b/packages/instabug_flutter/example/android/app/src/main/res/values/styles.xml similarity index 100% rename from example/android/app/src/main/res/values/styles.xml rename to packages/instabug_flutter/example/android/app/src/main/res/values/styles.xml diff --git a/example/android/app/src/main/res/xml/network_security_config.xml b/packages/instabug_flutter/example/android/app/src/main/res/xml/network_security_config.xml similarity index 100% rename from example/android/app/src/main/res/xml/network_security_config.xml rename to packages/instabug_flutter/example/android/app/src/main/res/xml/network_security_config.xml diff --git a/packages/instabug_flutter/example/android/app/src/profile/AndroidManifest.xml b/packages/instabug_flutter/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000..f880684a6 --- /dev/null +++ b/packages/instabug_flutter/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/packages/instabug_flutter/example/android/build.gradle b/packages/instabug_flutter/example/android/build.gradle new file mode 100644 index 000000000..6cc62edd7 --- /dev/null +++ b/packages/instabug_flutter/example/android/build.gradle @@ -0,0 +1,21 @@ +rootProject.buildDir = '../build' + +//android { +// namespace 'com.instabug.flutter.example' +//} +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') + tasks.withType(Test) { + // Prevent tests in moduleA from running + if (project.name == 'video_player_android') { + exclude '**/*' + } + } +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/packages/instabug_flutter/example/android/gradle.properties b/packages/instabug_flutter/example/android/gradle.properties new file mode 100644 index 000000000..b9a9a2464 --- /dev/null +++ b/packages/instabug_flutter/example/android/gradle.properties @@ -0,0 +1,6 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false diff --git a/example/android/gradle/wrapper/gradle-wrapper.jar b/packages/instabug_flutter/example/android/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from example/android/gradle/wrapper/gradle-wrapper.jar rename to packages/instabug_flutter/example/android/gradle/wrapper/gradle-wrapper.jar diff --git a/packages/instabug_flutter/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/instabug_flutter/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..4cf0c849a --- /dev/null +++ b/packages/instabug_flutter/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip diff --git a/example/android/gradlew b/packages/instabug_flutter/example/android/gradlew similarity index 100% rename from example/android/gradlew rename to packages/instabug_flutter/example/android/gradlew diff --git a/example/android/gradlew.bat b/packages/instabug_flutter/example/android/gradlew.bat similarity index 96% rename from example/android/gradlew.bat rename to packages/instabug_flutter/example/android/gradlew.bat index aec99730b..8a0b282aa 100644 --- a/example/android/gradlew.bat +++ b/packages/instabug_flutter/example/android/gradlew.bat @@ -1,90 +1,90 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/packages/instabug_flutter/example/android/settings.gradle b/packages/instabug_flutter/example/android/settings.gradle new file mode 100644 index 000000000..32cfc43dc --- /dev/null +++ b/packages/instabug_flutter/example/android/settings.gradle @@ -0,0 +1,27 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + maven { url 'https://storage.googleapis.com/flutter-plugins' } + + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.1.0" apply false + id "org.jetbrains.kotlin.android" version "1.8.22" apply false +} + +include ":app" diff --git a/example/android/settings_aar.gradle b/packages/instabug_flutter/example/android/settings_aar.gradle similarity index 100% rename from example/android/settings_aar.gradle rename to packages/instabug_flutter/example/android/settings_aar.gradle diff --git a/packages/instabug_flutter/example/assets/img.png b/packages/instabug_flutter/example/assets/img.png new file mode 100644 index 0000000000000000000000000000000000000000..fff04770f0f3a9e8a34bce7c805a3f02a9862c09 GIT binary patch literal 181305 zcmced^;cBi8}H8yHBt`UFm#82bfdI@AOebnbT`rrA)$05T_PYYAW}n@lG2?6(%mzc z@4BD+FWg`DIqR%-*4k(9XFtz-zxMk?X=^GI;8NoP06?Is@=ON+zz?@z0D}E+IrIK| z0|0P9^_l!DZ{xiH9B-q^`tvg?G71NY^ihRJtnp#-VVM0xc$f+*A6Z)B!_qEGE>9An zh~9UtP4kI*6?Ox)6-&)LC(_J0P`5O_yc&ViuEDD*e6^Y8-^wANP{9H7Kw!H1^VkX@Q{Y|EF^Oe%2X>kosnFoU-M|h2Q#RxkP zyvle-fx~85XfWypUaa(|zU5BT(;1~B6Py6j|2L6)CT4skG%b5~j4dd$xV{fr#_bcU z;Ms|J_E|sDV_ni22QP#O?u~d(dG2~!W+wtlK#Iv%vP+rchara90`^$-CTb9>X~mlV zTpd&W9`av!?3q{`os@(u;7Ko4o3r?fZDNm+EU+sjp*R7oj<*PVgs~}Jf3AE)d(VYc z+K^=w=)dmx$^LPA+)M&qVQuUy3BOlXk%gK=?q02l_0z9)9ZNLe9D7S@e|&tw5xW>` zZatr`;qbp{j~Jk&)zIFSbkL-UU}7(5H3{nz1sXvgh{XcaMv%8Vd zx_ymS$Ao_oT$x%wr;m$_w&?B1wAqU|noYMvn08WaV>)$T;3I7Rw=^`F&G(@Zj{}CD zNu@i~HH}#L^`b7}I|u~`oJ{OB@OQ;k_J~+6Vg+i^`Eo@svkUcQafcEkVxsi&SZZX| zJZl8L5dgbK!g*(w;cbPGfFXrF^xW#Pk==);&SUg<9@Zh0Gj;NbaHN^{0{+5jX%o6; z15Jntm+r1f0@kr84OAFSMZpAJot>{-7%!+ayh)ML7|H81xz+bl4M}@*e$@}1l!0!^ z`B`Wuh|=C3t?gf~uPC}aMMXQ3%Q3OlxX&HJR2M5JKA{JM&3~ZR@mZ`GOhw;+BCS63 zknCA?`zON&NR1r0K``MGaedx7zR>{}jGEZIlJCSQ0-_Wxxoc#7s5)VIBg?B^ex1La zO*1Uf?7#P2B&9`0oM{P>X1RTMCm%TSKo|}@POdX_f*llWY42R}v!1#pY8>5k4`Dwa ze_f4XlkSBZk$`QlKWd24{Y{C62bhVBky8+{D)~(C+L~N!k*_|^Jr<+Sh29)H-RdXZ z?c|J1wC1|dOgpsd!)<%kLq51@qrM@KEDr&btUfc^cWY{gca6!3(~B0$&S1m0_aj{K zpB?&7th&(E&F)8|#fRIJ>U|ml;_JKiFsk*KL-s^fwy{fh0~IdGIz|-`Pz+68`aQmu zTy~R%_b4Re4RbxIwjjLUp z1x@4!fdWcQ3G(1uR9|pFcNFyKjRcibRRnW%b2VDO{IGft9qqG_qgD8%otB8)bpZn$ zdlZ6@?oqwQRZi^~8h|ZFxmbuLt)Xd{jOl68#JWf9DoT8*=xwx6pTtk}@&m;GZNN zI{0;dBK!<-^HDWX;zMdtU!R(tP9n>2CVL&d&$GarQN@#tOc_?|Tyee5t}c&kfN-Em zoNEOdH}ClSl7>Jk{VMdi92ATRFVjL?x;4M+qvD67 ~Nvh~D=@9ARS#oVi~x7R+z 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%0A2OJ-@K{7M6{*i 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�8=-8{0Uhe8lV%#(} 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 Q8t{6^epLEUA!!`)fAjQ(rT_o{ literal 0 HcmV?d00001 diff --git a/example/ios/.gitignore b/packages/instabug_flutter/example/ios/.gitignore similarity index 100% rename from example/ios/.gitignore rename to packages/instabug_flutter/example/ios/.gitignore diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/packages/instabug_flutter/example/ios/Flutter/AppFrameworkInfo.plist similarity index 100% rename from example/ios/Flutter/AppFrameworkInfo.plist rename to packages/instabug_flutter/example/ios/Flutter/AppFrameworkInfo.plist diff --git a/example/ios/Flutter/Debug.xcconfig b/packages/instabug_flutter/example/ios/Flutter/Debug.xcconfig similarity index 100% rename from example/ios/Flutter/Debug.xcconfig rename to packages/instabug_flutter/example/ios/Flutter/Debug.xcconfig diff --git a/example/ios/Flutter/Release.xcconfig b/packages/instabug_flutter/example/ios/Flutter/Release.xcconfig similarity index 100% rename from example/ios/Flutter/Release.xcconfig rename to packages/instabug_flutter/example/ios/Flutter/Release.xcconfig diff --git a/example/ios/InstabugTests/ApmApiTests.m b/packages/instabug_flutter/example/ios/InstabugTests/ApmApiTests.m similarity index 100% rename from example/ios/InstabugTests/ApmApiTests.m rename to packages/instabug_flutter/example/ios/InstabugTests/ApmApiTests.m diff --git a/example/ios/InstabugTests/ArgsRegistryTests.m b/packages/instabug_flutter/example/ios/InstabugTests/ArgsRegistryTests.m similarity index 100% rename from example/ios/InstabugTests/ArgsRegistryTests.m rename to packages/instabug_flutter/example/ios/InstabugTests/ArgsRegistryTests.m diff --git a/example/ios/InstabugTests/BugReportingApiTests.m b/packages/instabug_flutter/example/ios/InstabugTests/BugReportingApiTests.m similarity index 100% rename from example/ios/InstabugTests/BugReportingApiTests.m rename to packages/instabug_flutter/example/ios/InstabugTests/BugReportingApiTests.m diff --git a/example/ios/InstabugTests/CrashReportingApiTests.m b/packages/instabug_flutter/example/ios/InstabugTests/CrashReportingApiTests.m similarity index 100% rename from example/ios/InstabugTests/CrashReportingApiTests.m rename to packages/instabug_flutter/example/ios/InstabugTests/CrashReportingApiTests.m diff --git a/example/ios/InstabugTests/FeatureRequestsApiTests.m b/packages/instabug_flutter/example/ios/InstabugTests/FeatureRequestsApiTests.m similarity index 100% rename from example/ios/InstabugTests/FeatureRequestsApiTests.m rename to packages/instabug_flutter/example/ios/InstabugTests/FeatureRequestsApiTests.m diff --git a/example/ios/InstabugTests/Info.plist b/packages/instabug_flutter/example/ios/InstabugTests/Info.plist similarity index 100% rename from example/ios/InstabugTests/Info.plist rename to packages/instabug_flutter/example/ios/InstabugTests/Info.plist diff --git a/example/ios/InstabugTests/InstabugApiTests.m b/packages/instabug_flutter/example/ios/InstabugTests/InstabugApiTests.m similarity index 95% rename from example/ios/InstabugTests/InstabugApiTests.m rename to packages/instabug_flutter/example/ios/InstabugTests/InstabugApiTests.m index 3e1abf332..e156199db 100644 --- a/example/ios/InstabugTests/InstabugApiTests.m +++ b/packages/instabug_flutter/example/ios/InstabugTests/InstabugApiTests.m @@ -137,14 +137,6 @@ - (void)testSetWelcomeMessageMode { OCMVerify([self.mInstabug setWelcomeMessageMode:IBGWelcomeMessageModeBeta]); } -- (void)testSetPrimaryColor { - NSNumber *color = @0xFF0000; - FlutterError *error; - - [self.api setPrimaryColorColor:color error:&error]; - - OCMVerify([self.mInstabug setTintColor:[OCMArg isKindOfClass:[UIColor class]]]); -} - (void)testSetSessionProfilerEnabled { NSNumber *isEnabled = @1; @@ -630,5 +622,32 @@ - (void)testSetFullscreen { // Since this is an empty implementation, we just verify the method can be called without error XCTAssertNil(error); } +- (void)testSetEnableUserStepsIsEnabled{ + NSNumber *isEnabled = @1; + FlutterError *error; + + [self.api setEnableUserStepsIsEnabled:isEnabled error:&error]; + + OCMVerify([self.mInstabug setTrackUserSteps:YES]); + +} +- (void)testLogUserStepsGestureType{ + NSString* message = @"message"; + NSString* view = @"viewName"; + FlutterError *error; + + [self.api logUserStepsGestureType:@"GestureType.tap" message:message viewName:view error: &error]; + + XCTAssertNil(error, @"Error should be nil"); + +} +- (void)testAutoMasking { + NSArray *autoMaskingTypes = @[@"AutoMasking.labels", @"AutoMasking.textInputs",@"AutoMasking.media",@"AutoMasking.none"]; + FlutterError *error; + + [self.api enableAutoMaskingAutoMasking:autoMaskingTypes error:&error]; + + OCMVerify([self.mInstabug setAutoMaskScreenshots: (IBGAutoMaskScreenshotOptionMaskNothing | IBGAutoMaskScreenshotOptionTextInputs | IBGAutoMaskScreenshotOptionLabels | IBGAutoMaskScreenshotOptionMedia)]); +} @end diff --git a/example/ios/InstabugTests/InstabugLogApiTests.m b/packages/instabug_flutter/example/ios/InstabugTests/InstabugLogApiTests.m similarity index 100% rename from example/ios/InstabugTests/InstabugLogApiTests.m rename to packages/instabug_flutter/example/ios/InstabugTests/InstabugLogApiTests.m diff --git a/packages/instabug_flutter/example/ios/InstabugTests/PrivateViewApiTests.m b/packages/instabug_flutter/example/ios/InstabugTests/PrivateViewApiTests.m new file mode 100644 index 000000000..ac3f17efc --- /dev/null +++ b/packages/instabug_flutter/example/ios/InstabugTests/PrivateViewApiTests.m @@ -0,0 +1,191 @@ +#import +#import +#import +#import +#import "FlutterPluginRegistrar+FlutterEngine.h" + + +@interface MockFlutterPluginRegistrar : NSObject +@end + +@implementation MockFlutterPluginRegistrar + +@end + + +@interface PrivateViewApiTests : XCTestCase +@property (nonatomic, strong) PrivateViewApi *api; +@property (nonatomic, strong) id mockFlutterApi; +@property (nonatomic, strong) id mockRegistrar; +@property (nonatomic, strong) id mockFlutterViewController; +@property (nonatomic, strong) id mockEngine; + +@end + +@implementation PrivateViewApiTests + +#pragma mark - Setup / Teardown + +- (void)setUp { + [super setUp]; + + + self.mockFlutterApi = OCMClassMock([InstabugPrivateViewFlutterApi class]); + + + MockFlutterPluginRegistrar *mockRegistrar = [[MockFlutterPluginRegistrar alloc] init]; + + self.mockRegistrar = OCMPartialMock(mockRegistrar); + + self.mockEngine = OCMClassMock([FlutterEngine class]); + OCMStub([self.mockRegistrar flutterEngine]).andReturn(self.mockEngine); + + self.mockFlutterViewController = OCMClassMock([UIViewController class]); + + OCMStub([self.mockEngine viewController]).andReturn(_mockFlutterViewController); + + self.api = OCMPartialMock([[PrivateViewApi alloc] initWithFlutterApi:self.mockFlutterApi registrar: self.mockRegistrar]); +} + +- (void)tearDown { + [self.mockFlutterApi stopMocking]; + [self.mockRegistrar stopMocking]; + [self.mockFlutterViewController stopMocking]; + [self.mockEngine stopMocking]; + + self.api = nil; + + [super tearDown]; +} + +#pragma mark - Tests + +- (void)testMask_Success { + XCTestExpectation *expectation = [self expectationWithDescription:@"Mask method success"]; + + CGSize imageSize = CGSizeMake(100, 100); // 100x100 pixels + + // Step 2: Create the image using UIGraphicsImageRenderer + UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:imageSize]; + + UIImage *screenshot = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) { + // Draw a red rectangle as an example + [[UIColor redColor] setFill]; + CGRect rect = CGRectMake(0, 0, imageSize.width, imageSize.height); + UIRectFill(rect); + }]; + + NSArray *rectangles = @[@10, @20, @30, @40]; + UIView *mockView = [[UIView alloc] initWithFrame:CGRectMake(10, 20, 30, 40)]; + + OCMStub([self.mockFlutterApi getPrivateViewsWithCompletion:([OCMArg invokeBlockWithArgs:rectangles, [NSNull null], nil])]); + + + + OCMStub([self.mockFlutterViewController view]).andReturn(mockView); + + + [self.api mask:screenshot completion:^(UIImage *result) { + XCTAssertNotNil(result, @"Masked image should be returned."); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:1 handler:nil]; +} + + +- (void)testGetFlutterViewOrigin_ValidView { + UIView *mockView = [[UIView alloc] initWithFrame:CGRectMake(10, 20, 100, 100)]; + + OCMStub([self.mockFlutterViewController view]).andReturn(mockView); + + UIWindow* testWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + [testWindow addSubview:mockView]; + + CGPoint origin = [self.api getFlutterViewOrigin]; + + XCTAssertEqual(origin.x, 10); + XCTAssertEqual(origin.y, 20); +} + +- (void)testGetFlutterViewOrigin_NilView { + + OCMStub([self.mockFlutterViewController view]).andReturn(nil); +// + CGPoint origin = [self.api getFlutterViewOrigin]; + + XCTAssertEqual(origin.x, 0); + XCTAssertEqual(origin.y, 0); +} + +- (void)testDrawMaskedImage { + CGSize size = CGSizeMake(100, 100); + UIGraphicsBeginImageContext(size); + UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + NSArray *privateViews = @[ + [NSValue valueWithCGRect:CGRectMake(10, 10, 20, 20)], + [NSValue valueWithCGRect:CGRectMake(30, 30, 10, 10)] + ]; + + UIImage *result = [self.api drawMaskedImage:screenshot withPrivateViews:privateViews]; + + XCTAssertNotNil(result); + XCTAssertEqual(result.size.width, 100); + XCTAssertEqual(result.size.height, 100); +} + +- (void)testConvertToRectangles_ValidInput { + NSArray *rectangles = @[@10, @20, @30, @40]; + UIView *mockView = [[UIView alloc] initWithFrame:CGRectMake(5, 5, 100, 100)]; + OCMStub([self.mockFlutterViewController view]).andReturn(mockView); + + + NSArray *converted = [self.api convertToRectangles:rectangles]; + + XCTAssertEqual(converted.count, 1); + CGRect rect = [converted[0] CGRectValue]; + XCTAssertTrue(CGRectEqualToRect(rect, CGRectMake(10, 20, 21, 21))); +} + +- (void)testConcurrentMaskCalls { + XCTestExpectation *expectation = [self expectationWithDescription:@"Handle concurrent calls"]; + + CGSize imageSize = CGSizeMake(100, 100); // 100x100 pixels + + // Step 2: Create the image using UIGraphicsImageRenderer + UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:imageSize]; + + UIImage *screenshot = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) { + // Draw a red rectangle as an example + [[UIColor redColor] setFill]; + CGRect rect = CGRectMake(0, 0, imageSize.width, imageSize.height); + UIRectFill(rect); + }]; + + NSArray *rectangles = @[@10, @20, @30, @40]; + + + OCMStub([self.mockFlutterApi getPrivateViewsWithCompletion:([OCMArg invokeBlockWithArgs:rectangles, [NSNull null], nil])]); + + + dispatch_group_t group = dispatch_group_create(); + + for (int i = 0; i < 5; i++) { + dispatch_group_enter(group); + + [self.api mask:screenshot completion:^(UIImage *result) { + XCTAssertNotNil(result, @"Each call should return a valid image."); + dispatch_group_leave(group); + }]; + } + + dispatch_group_notify(group, dispatch_get_main_queue(), ^{ + [expectation fulfill]; + }); + + [self waitForExpectationsWithTimeout:2 handler:nil]; +} + +@end diff --git a/packages/instabug_flutter/example/ios/InstabugTests/PrivateViewHostApiTests.m b/packages/instabug_flutter/example/ios/InstabugTests/PrivateViewHostApiTests.m new file mode 100644 index 000000000..27b2599ec --- /dev/null +++ b/packages/instabug_flutter/example/ios/InstabugTests/PrivateViewHostApiTests.m @@ -0,0 +1,57 @@ +#import +#import +#import +#import "PrivateViewApi.h" +#import "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/example/ios/InstabugTests/RepliesApiTests.m b/packages/instabug_flutter/example/ios/InstabugTests/RepliesApiTests.m similarity index 100% rename from example/ios/InstabugTests/RepliesApiTests.m rename to packages/instabug_flutter/example/ios/InstabugTests/RepliesApiTests.m diff --git a/example/ios/InstabugTests/SessionReplayApiTests.m b/packages/instabug_flutter/example/ios/InstabugTests/SessionReplayApiTests.m similarity index 100% rename from example/ios/InstabugTests/SessionReplayApiTests.m rename to packages/instabug_flutter/example/ios/InstabugTests/SessionReplayApiTests.m diff --git a/example/ios/InstabugTests/SurveysApiTests.m b/packages/instabug_flutter/example/ios/InstabugTests/SurveysApiTests.m similarity index 100% rename from example/ios/InstabugTests/SurveysApiTests.m rename to packages/instabug_flutter/example/ios/InstabugTests/SurveysApiTests.m diff --git a/example/ios/InstabugTests/Util/Apm+Test.h b/packages/instabug_flutter/example/ios/InstabugTests/Util/Apm+Test.h similarity index 100% rename from example/ios/InstabugTests/Util/Apm+Test.h rename to packages/instabug_flutter/example/ios/InstabugTests/Util/Apm+Test.h diff --git a/example/ios/InstabugTests/Util/IBGCrashReporting+CP.h b/packages/instabug_flutter/example/ios/InstabugTests/Util/IBGCrashReporting+CP.h similarity index 100% rename from example/ios/InstabugTests/Util/IBGCrashReporting+CP.h rename to packages/instabug_flutter/example/ios/InstabugTests/Util/IBGCrashReporting+CP.h diff --git a/example/ios/InstabugTests/Util/IBGNetworkLogger+Test.h b/packages/instabug_flutter/example/ios/InstabugTests/Util/IBGNetworkLogger+Test.h similarity index 100% rename from example/ios/InstabugTests/Util/IBGNetworkLogger+Test.h rename to packages/instabug_flutter/example/ios/InstabugTests/Util/IBGNetworkLogger+Test.h diff --git a/example/ios/InstabugTests/Util/IBGSurvey+Test.h b/packages/instabug_flutter/example/ios/InstabugTests/Util/IBGSurvey+Test.h similarity index 100% rename from example/ios/InstabugTests/Util/IBGSurvey+Test.h rename to packages/instabug_flutter/example/ios/InstabugTests/Util/IBGSurvey+Test.h diff --git a/example/ios/InstabugTests/Util/Instabug+Test.h b/packages/instabug_flutter/example/ios/InstabugTests/Util/Instabug+Test.h similarity index 100% rename from example/ios/InstabugTests/Util/Instabug+Test.h rename to packages/instabug_flutter/example/ios/InstabugTests/Util/Instabug+Test.h diff --git a/example/ios/Podfile b/packages/instabug_flutter/example/ios/Podfile similarity index 100% rename from example/ios/Podfile rename to packages/instabug_flutter/example/ios/Podfile diff --git a/packages/instabug_flutter/example/ios/Podfile.lock b/packages/instabug_flutter/example/ios/Podfile.lock new file mode 100644 index 000000000..ad3bc6f81 --- /dev/null +++ b/packages/instabug_flutter/example/ios/Podfile.lock @@ -0,0 +1,40 @@ +PODS: + - Flutter (1.0.0) + - Instabug (16.0.1) + - instabug_flutter (16.0.0): + - Flutter + - Instabug (= 16.0.1) + - OCMock (3.6) + - video_player_avfoundation (0.0.1): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - Flutter (from `Flutter`) + - instabug_flutter (from `.symlinks/plugins/instabug_flutter/ios`) + - OCMock (= 3.6) + - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`) + +SPEC REPOS: + trunk: + - Instabug + - OCMock + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + instabug_flutter: + :path: ".symlinks/plugins/instabug_flutter/ios" + video_player_avfoundation: + :path: ".symlinks/plugins/video_player_avfoundation/darwin" + +SPEC CHECKSUMS: + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + Instabug: f31a27e70cb6580aef656d1abf8c57a5bb5633d0 + instabug_flutter: 30131c9ec54d3a7a44ff74ac7ad51e3562813374 + OCMock: 5ea90566be239f179ba766fd9fbae5885040b992 + video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b + +PODFILE CHECKSUM: 986d650b5bc8e230d8a9612663af4b3b1a9d6236 + +COCOAPODS: 1.16.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/packages/instabug_flutter/example/ios/Runner.xcodeproj/project.pbxproj similarity index 100% rename from example/ios/Runner.xcodeproj/project.pbxproj rename to packages/instabug_flutter/example/ios/Runner.xcodeproj/project.pbxproj diff --git a/packages/instabug_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/instabug_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/packages/instabug_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/instabug_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/instabug_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/packages/instabug_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/instabug_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/instabug_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/packages/instabug_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/instabug_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme similarity index 100% rename from example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme rename to packages/instabug_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme diff --git a/packages/instabug_flutter/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/instabug_flutter/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..21a3cc14c --- /dev/null +++ b/packages/instabug_flutter/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/packages/instabug_flutter/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/instabug_flutter/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/packages/instabug_flutter/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/instabug_flutter/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/instabug_flutter/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/packages/instabug_flutter/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/example/ios/Runner/AppDelegate.swift b/packages/instabug_flutter/example/ios/Runner/AppDelegate.swift similarity index 100% rename from example/ios/Runner/AppDelegate.swift rename to packages/instabug_flutter/example/ios/Runner/AppDelegate.swift diff --git a/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..d36b1fab2 --- /dev/null +++ b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 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 literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 zcmVjJBgitF5mAp-i>4+KS_oR{|13AP->1TD4=w)g|)JHOx|a2Wk1Va z!k)vP$UcQ#mdj%wNQoaJ!w>jv_6&JPyutpQps?s5dmDQ>`%?Bvj>o<%kYG!YW6H-z zu`g$@mp`;qDR!51QaS}|ZToSuAGcJ7$2HF0z`ln4t!#Yg46>;vGG9N9{V@9z#}6v* zfP?}r6b{*-C*)(S>NECI_E~{QYzN5SXRmVnP<=gzP+_Sp(Aza_hKlZ{C1D&l*(7IKXxQC1Z9#6wx}YrGcn~g%;icdw>T0Rf^w0{ z$_wn1J+C0@!jCV<%Go5LA45e{5gY9PvZp8uM$=1}XDI+9m7!A95L>q>>oe0$nC->i zeexUIvq%Uk<-$>DiDb?!In)lAmtuMWxvWlk`2>4lNuhSsjAf2*2tjT`y;@d}($o)S zn(+W&hJ1p0xy@oxP%AM15->wPLp{H!k)BdBD$toBpJh+crWdsNV)qsHaqLg2_s|Ih z`8E9z{E3sA!}5aKu?T!#enD(wLw?IT?k-yWVHZ8Akz4k5(TZJN^zZgm&zM28sfTD2BYJ|Fde3Xzh;;S` z=GXTnY4Xc)8nYoz6&vF;P7{xRF-{|2Xs5>a5)@BrnQ}I(_x7Cgpx#5&Td^4Q9_FnQ zX5so*;#8-J8#c$OlA&JyPp$LKUhC~-e~Ij!L%uSMu!-VZG7Hx-L{m2DVR2i=GR(_% zCVD!4N`I)&Q5S`?P&fQZ=4#Dgt_v2-DzkT}K(9gF0L(owe-Id$Rc2qZVLqI_M_DyO z9@LC#U28_LU{;wGZ&))}0R2P4MhajKCd^K#D+JJ&JIXZ_p#@+7J9A&P<0kdRujtQ_ zOy>3=C$kgi6$0pW06KaLz!21oOryKM3ZUOWqppndxfH}QpgjEJ`j7Tzn5bk6K&@RA?vl##y z$?V~1E(!wB5rH`>3nc&@)|#<1dN2cMzzm=PGhQ|Yppne(C-Vlt450IXc`J4R0W@I7 zd1e5uW6juvO%ni(WX7BsKx3MLngO7rHO;^R5I~0^nE^9^E_eYLgiR9&KnJ)pBbfno zSVnW$0R+&6jOOsZ82}nJ126+c|%svPo;TeUku<2G7%?$oft zyaO;tVo}(W)VsTUhq^XmFi#2z%-W9a{7mXn{uzivYQ_d6b7VJG{77naW(vHt-uhnY zVN#d!JTqVh(7r-lhtXVU6o})aZbDt_;&wJVGl2FKYFBFpU-#9U)z#(A%=IVnqytR$SY-sO( z($oNE09{D^@OuYPz&w~?9>Fl5`g9u&ecFGhqX=^#fmR=we0CJw+5xna*@oHnkahk+ z9aWeE3v|An+O5%?4fA&$Fgu~H_YmqR!yIU!bFCk4!#pAj%(lI(A5n)n@Id#M)O9Yx zJU9oKy{sRAIV3=5>(s8n{8ryJ!;ho}%pn6hZKTKbqk=&m=f*UnK$zW3YQP*)pw$O* zIfLA^!-bmBl6%d_n$#tP8Zd_(XdA*z*WH|E_yILwjtI~;jK#v-6jMl^?<%Y%`gvpwv&cFb$||^v4D&V=aNy?NGo620jL3VZnA%s zH~I|qPzB~e(;p;b^gJr7Ure#7?8%F0m4vzzPy^^(q4q1OdthF}Fi*RmVZN1OwTsAP zn9CZP`FazX3^kG(KodIZ=Kty8DLTy--UKfa1$6XugS zk%6v$Kmxt6U!YMx0JQ)0qX*{CXwZZk$vEROidEc7=J-1;peNat!vS<3P-FT5po>iE z!l3R+<`#x|+_hw!HjQGV=8!q|76y8L7N8gP3$%0kfush|u0uU^?dKBaeRSBUpOZ0c z62;D&Mdn2}N}xHRFTRI?zRv=>=AjHgH}`2k4WK=#AHB)UFrR-J87GgX*x5fL^W2#d z=(%K8-oZfMO=i{aWRDg=FX}UubM4eotRDcn;OR#{3q=*?3mE3_oJ-~prjhxh%PgQT zyn)Qozaq0@o&|LEgS{Ind4Swsr;b`u185hZPOBLL<`d2%^Yp1?oL)=jnLi;Zo0ZDliTtQ^b5SmfIMe{T==zZkbvn$KTQGlbG8w}s@M3TZnde;1Am46P3juKb zl9GU&3F=q`>j!`?SyH#r@O59%@aMX^rx}Nxe<>NqpUp5=lX1ojGDIR*-D^SDuvCKF z?3$xG(gVUsBERef_YjPFl^rU9EtD{pt z0CXwpN7BN3!8>hajGaTVk-wl=9rxmfWtIhC{mheHgStLi^+Nz12a?4r(fz)?3A%at zMlvQmL<2-R)-@G1wJ0^zQK%mR=r4d{Y3fHp){nWXUL#|CqXl(+v+qDh>FkF9`eWrW zfr^D%LNfOcTNvtx0JXR35J0~Jpi2#P3Q&80w+nqNfc}&G0A~*)lGHKv=^FE+b(37|)zL;KLF>oiGfb(?&1 zV3XRu!Sw>@quKiab%g6jun#oZ%!>V#A%+lNc?q>6+VvyAn=kf_6z^(TZUa4Eelh{{ zqFX-#dY(EV@7l$NE&kv9u9BR8&Ojd#ZGJ6l8_BW}^r?DIS_rU2(XaGOK z225E@kH5Opf+CgD^{y29jD4gHbGf{1MD6ggQ&%>UG4WyPh5q_tb`{@_34B?xfSO*| zZv8!)q;^o-bz`MuxXk*G^}(6)ACb@=Lfs`Hxoh>`Y0NE8QRQ!*p|SH@{r8=%RKd4p z+#Ty^-0kb=-H-O`nAA3_6>2z(D=~Tbs(n8LHxD0`R0_ATFqp-SdY3(bZ3;VUM?J=O zKCNsxsgt@|&nKMC=*+ZqmLHhX1KHbAJs{nGVMs6~TiF%Q)P@>!koa$%oS zjXa=!5>P`vC-a}ln!uH1ooeI&v?=?v7?1n~P(wZ~0>xWxd_Aw;+}9#eULM7M8&E?Y zC-ZLhi3RoM92SXUb-5i-Lmt5_rfjE{6y^+24`y$1lywLyHO!)Boa7438K4#iLe?rh z2O~YGSgFUBH?og*6=r9rme=peP~ah`(8Zt7V)j5!V0KPFf_mebo3z95U8(up$-+EA^9dTRLq>Yl)YMBuch9%=e5B`Vnb>o zt03=kq;k2TgGe4|lGne&zJa~h(UGutjP_zr?a7~#b)@15XNA>Dj(m=gg2Q5V4-$)D|Q9}R#002ovPDHLkV1o7DH3k3x literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000..89c2725b7 --- /dev/null +++ b/packages/instabug_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/instabug_flutter/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/instabug_flutter/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..f2e259c7c --- /dev/null +++ b/packages/instabug_flutter/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/instabug_flutter/example/ios/Runner/Base.lproj/Main.storyboard b/packages/instabug_flutter/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000..f3c28516f --- /dev/null +++ b/packages/instabug_flutter/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/Runner/Info.plist b/packages/instabug_flutter/example/ios/Runner/Info.plist similarity index 100% rename from example/ios/Runner/Info.plist rename to packages/instabug_flutter/example/ios/Runner/Info.plist diff --git a/example/ios/Runner/InstabugExampleMethodCallHandler.h b/packages/instabug_flutter/example/ios/Runner/InstabugExampleMethodCallHandler.h similarity index 100% rename from example/ios/Runner/InstabugExampleMethodCallHandler.h rename to packages/instabug_flutter/example/ios/Runner/InstabugExampleMethodCallHandler.h diff --git a/example/ios/Runner/InstabugExampleMethodCallHandler.m b/packages/instabug_flutter/example/ios/Runner/InstabugExampleMethodCallHandler.m similarity index 100% rename from example/ios/Runner/InstabugExampleMethodCallHandler.m rename to packages/instabug_flutter/example/ios/Runner/InstabugExampleMethodCallHandler.m diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/packages/instabug_flutter/example/ios/Runner/Runner-Bridging-Header.h similarity index 100% rename from example/ios/Runner/Runner-Bridging-Header.h rename to packages/instabug_flutter/example/ios/Runner/Runner-Bridging-Header.h diff --git a/example/lib/main.dart b/packages/instabug_flutter/example/lib/main.dart similarity index 85% rename from example/lib/main.dart rename to packages/instabug_flutter/example/lib/main.dart index bccdbfc68..fa81b0b9f 100644 --- a/example/lib/main.dart +++ b/packages/instabug_flutter/example/lib/main.dart @@ -6,6 +6,8 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:instabug_flutter_example/src/components/apm_switch.dart'; +import 'package:instabug_flutter_example/src/components/apm_switch.dart'; +import 'package:instabug_flutter_example/src/screens/private_view_page.dart'; import 'package:instabug_http_client/instabug_http_client.dart'; import 'package:instabug_flutter_example/src/app_routes.dart'; import 'package:instabug_flutter_example/src/widget/nested_view.dart'; @@ -19,6 +21,7 @@ import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager import 'src/widget/section_title.dart'; part 'src/screens/crashes_page.dart'; +part 'src/screens/user_steps_page.dart'; part 'src/screens/complex_page.dart'; @@ -55,7 +58,13 @@ void main() { Zone.current.handleUncaughtError(details.exception, details.stack!); }; - runApp(const MyApp()); + runApp( + const InstabugWidget(automasking: [ + AutoMasking.labels, + AutoMasking.textInputs, + AutoMasking.media + ], child: MyApp()), + ); }, CrashReporting.reportCrash, ); diff --git a/example/lib/src/app_routes.dart b/packages/instabug_flutter/example/lib/src/app_routes.dart similarity index 100% rename from example/lib/src/app_routes.dart rename to packages/instabug_flutter/example/lib/src/app_routes.dart diff --git a/example/lib/src/components/apm_switch.dart b/packages/instabug_flutter/example/lib/src/components/apm_switch.dart similarity index 100% rename from example/lib/src/components/apm_switch.dart rename to packages/instabug_flutter/example/lib/src/components/apm_switch.dart diff --git a/example/lib/src/components/fatal_crashes_content.dart b/packages/instabug_flutter/example/lib/src/components/fatal_crashes_content.dart similarity index 100% rename from example/lib/src/components/fatal_crashes_content.dart rename to packages/instabug_flutter/example/lib/src/components/fatal_crashes_content.dart diff --git a/example/lib/src/components/flows_content.dart b/packages/instabug_flutter/example/lib/src/components/flows_content.dart similarity index 100% rename from example/lib/src/components/flows_content.dart rename to packages/instabug_flutter/example/lib/src/components/flows_content.dart diff --git a/example/lib/src/components/network_content.dart b/packages/instabug_flutter/example/lib/src/components/network_content.dart similarity index 89% rename from example/lib/src/components/network_content.dart rename to packages/instabug_flutter/example/lib/src/components/network_content.dart index 23eaa4dd2..d531e17bd 100644 --- a/example/lib/src/components/network_content.dart +++ b/packages/instabug_flutter/example/lib/src/components/network_content.dart @@ -18,15 +18,17 @@ class _NetworkContentState extends State { Widget build(BuildContext context) { return Column( children: [ - InstabugClipboardInput( - label: 'Endpoint Url', - controller: endpointUrlController, + InstabugPrivateView( + child: InstabugClipboardInput( + label: 'Endpoint Url', + controller: endpointUrlController, + ), ), InstabugButton( text: 'Send Request To Url', onPressed: () => _sendRequestToUrl(endpointUrlController.text), ), - const Text("W3C Header Section"), + Text("W3C Header Section"), InstabugButton( text: 'Send Request With Custom traceparent header', onPressed: () => _sendRequestToUrl(endpointUrlController.text, diff --git a/example/lib/src/components/non_fatal_crashes_content.dart b/packages/instabug_flutter/example/lib/src/components/non_fatal_crashes_content.dart similarity index 100% rename from example/lib/src/components/non_fatal_crashes_content.dart rename to packages/instabug_flutter/example/lib/src/components/non_fatal_crashes_content.dart diff --git a/example/lib/src/components/page.dart b/packages/instabug_flutter/example/lib/src/components/page.dart similarity index 100% rename from example/lib/src/components/page.dart rename to packages/instabug_flutter/example/lib/src/components/page.dart diff --git a/example/lib/src/native/instabug_flutter_example_method_channel.dart b/packages/instabug_flutter/example/lib/src/native/instabug_flutter_example_method_channel.dart similarity index 100% rename from example/lib/src/native/instabug_flutter_example_method_channel.dart rename to packages/instabug_flutter/example/lib/src/native/instabug_flutter_example_method_channel.dart diff --git a/example/lib/src/screens/apm_page.dart b/packages/instabug_flutter/example/lib/src/screens/apm_page.dart similarity index 100% rename from example/lib/src/screens/apm_page.dart rename to packages/instabug_flutter/example/lib/src/screens/apm_page.dart diff --git a/example/lib/src/screens/complex_page.dart b/packages/instabug_flutter/example/lib/src/screens/complex_page.dart similarity index 100% rename from example/lib/src/screens/complex_page.dart rename to packages/instabug_flutter/example/lib/src/screens/complex_page.dart diff --git a/example/lib/src/screens/crashes_page.dart b/packages/instabug_flutter/example/lib/src/screens/crashes_page.dart similarity index 100% rename from example/lib/src/screens/crashes_page.dart rename to packages/instabug_flutter/example/lib/src/screens/crashes_page.dart diff --git a/example/lib/src/screens/my_home_page.dart b/packages/instabug_flutter/example/lib/src/screens/my_home_page.dart similarity index 91% rename from example/lib/src/screens/my_home_page.dart rename to packages/instabug_flutter/example/lib/src/screens/my_home_page.dart index 5f7d50a88..f0fc1d14b 100644 --- a/example/lib/src/screens/my_home_page.dart +++ b/packages/instabug_flutter/example/lib/src/screens/my_home_page.dart @@ -35,6 +35,10 @@ class _MyHomePageState extends State { BugReporting.setInvocationEvents([InvocationEvent.floatingButton]); } + void disableInstabug() { + Instabug.setEnabled(false); + } + void setOnDismissCallback() { BugReporting.setOnDismissCallback((dismissType, reportType) { showDialog( @@ -161,6 +165,26 @@ class _MyHomePageState extends State { ); } + void _navigateToPrivateViewPage() { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const PrivateViewPage(), + settings: const RouteSettings(name: PrivateViewPage.screenName), + ), + ); + } + + void _navigateToUserStepsPage() { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const UserStepsPage(), + settings: const RouteSettings(name: UserStepsPage.screenName), + ), + ); + } + @override Widget build(BuildContext context) { return Page( @@ -178,6 +202,10 @@ class _MyHomePageState extends State { onPressed: restartInstabug, text: 'Restart Instabug', ), + InstabugButton( + onPressed: disableInstabug, + text: 'Disable Instabug', + ), const SectionTitle('Primary Color'), InstabugTextField( controller: primaryColorController, @@ -290,9 +318,11 @@ class _MyHomePageState extends State { onPressed: showManualSurvey, text: 'Show Multiple Questions Survey', ), - InstabugButton( - onPressed: showFeatureRequests, - text: 'Show Feature Requests', + InstabugPrivateView( + child: InstabugButton( + onPressed: showFeatureRequests, + text: 'Show Feature Requests', + ), ), InstabugButton( onPressed: _navigateToCrashes, @@ -306,6 +336,10 @@ class _MyHomePageState extends State { onPressed: _navigateToComplex, text: 'Complex', ), + InstabugButton( + onPressed: _navigateToPrivateViewPage, + text: 'Private views', + ), const SectionTitle('Sessions Replay'), InstabugButton( onPressed: getCurrentSessionReplaylink, @@ -334,6 +368,10 @@ class _MyHomePageState extends State { ), ], ), + InstabugButton( + text: 'User Steps', + onPressed: _navigateToUserStepsPage, + ), SectionTitle('FeatureFlags'), InstabugTextField( controller: featureFlagsController, diff --git a/packages/instabug_flutter/example/lib/src/screens/private_view_page.dart b/packages/instabug_flutter/example/lib/src/screens/private_view_page.dart new file mode 100644 index 000000000..5b7829e65 --- /dev/null +++ b/packages/instabug_flutter/example/lib/src/screens/private_view_page.dart @@ -0,0 +1,258 @@ +import 'package:flutter/material.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter_example/src/widget/section_title.dart'; +import 'package:video_player/video_player.dart'; + +class PrivateViewPage extends StatefulWidget { + static const screenName = 'private'; + + const PrivateViewPage({Key? key}) : super(key: key); + + @override + _PrivateViewPageState createState() => _PrivateViewPageState(); +} + +class _PrivateViewPageState extends State { + late VideoPlayerController _controller; + double _currentSliderValue = 20.0; + + RangeValues _currentRangeValues = const RangeValues(40, 80); + + String? _sliderStatus; + + bool? isChecked = true; + + int? _selectedValue = 1; + + bool light = true; + double _scale = 1.0; // Initial scale of the image + + TextEditingController _controller2 = TextEditingController(); + + String _currentValue = ''; + List _items = List.generate(20, (index) => 'Item ${index + 1}'); + + @override + void initState() { + super.initState(); + _controller = VideoPlayerController.networkUrl( + Uri.parse( + 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'), + )..initialize().then((_) { + setState(() {}); + }); + _controller2.addListener(() { + setState(() { + _currentValue = _controller2.text; + }); + }); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + void _handleRadioValueChanged(int? value) { + setState(() { + _selectedValue = value; + }); + } + + int count = 200; + final list = List.generate( + 20, + (_) => InstabugPrivateView( + child: Container( + margin: const EdgeInsets.all(2), + width: 4, + height: 4, + color: Colors.red, + ), + )); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text("Private Views page")), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 16), + const InstabugPrivateView( + child: Text( + 'Private TextView', + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 16), + Wrap( + children: list, + ), + const SizedBox(height: 16), + InstabugPrivateView( + child: ElevatedButton( + onPressed: () { + const snackBar = SnackBar( + content: Text('Hello, you clicked on a private button'), + ); + ScaffoldMessenger.of(context).showSnackBar(snackBar); + }, + child: const Text('I am a private button'), + ), + ), + const SizedBox(height: 16), + const BackButton(), + const SectionTitle('TextInput'), + Column( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + // Set the padding value + child: Column( + children: [ + TextField( + key: const Key('text_field'), + controller: _controller2, + // Bind the controller to the TextField + decoration: const InputDecoration( + labelText: + "Type something in a text field with key", + border: OutlineInputBorder(), + ), + ), + InstabugPrivateView( + child: TextField( + controller: _controller2, + // Bind the controller to the TextField + decoration: const InputDecoration( + labelText: "Private view", + border: OutlineInputBorder(), + ), + ), + ), + InstabugPrivateView( + child: TextField( + controller: _controller2, + // Bind the controller to the TextField + obscureText: true, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: 'Password', + ), + ), + ), + TextFormField( + obscureText: true, + controller: _controller2, + // Bind the controller to the TextField + decoration: const InputDecoration( + icon: Icon(Icons.person), + hintText: 'What do people call you?', + labelText: 'Name *', + ), + onSaved: (String? value) { + // This optional block of code can be used to run + // code when the user saves the form. + }, + validator: (String? value) { + return (value != null && value.contains('@')) + ? 'Do not use the @ char.' + : null; + }, + ), + ], + ), + ), + ], + ), + InstabugPrivateView( + child: Image.asset( + 'assets/img.png', + // Add this image to your assets folder + height: 100, + ), + ), + const SizedBox(height: 33), + const InstabugPrivateView( + child: TextField( + obscureText: true, + decoration: InputDecoration( + hintText: 'password', + labelText: 'Password', + border: OutlineInputBorder(), + ), + ), + ), + const SizedBox(height: 16), + const TextField( + keyboardType: TextInputType.emailAddress, + decoration: InputDecoration( + hintText: 'Email', + labelText: 'Email', + border: OutlineInputBorder(), + ), + ), + const SizedBox(height: 16), + const Column( + children: [ + InstabugPrivateView( + child: Text( + 'Private TextView in column', + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ), + SizedBox( + height: 10, + ), + Text( + 'TextView in column', + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ], + ), + const SizedBox(height: 24), + Container( + height: 300, + child: _controller.value.isInitialized + ? AspectRatio( + aspectRatio: _controller.value.aspectRatio, + child: VideoPlayer(_controller), + ) + : const Center(child: CircularProgressIndicator()), + ), + const SizedBox(height: 24), + const SizedBox(height: 24), + const SizedBox(height: 24), + SizedBox( + height: 200, + child: CustomScrollView( + slivers: [ + InstabugSliverPrivateView( + sliver: SliverToBoxAdapter( + child: Container( + color: Colors.red, + child: const Text( + "Private Sliver Widget", + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ), + ), + ) + ], + ), + ) + ], + ), + ), + ), + ); + } +} diff --git a/example/lib/src/screens/screen_capture_premature_extension_page.dart b/packages/instabug_flutter/example/lib/src/screens/screen_capture_premature_extension_page.dart similarity index 100% rename from example/lib/src/screens/screen_capture_premature_extension_page.dart rename to packages/instabug_flutter/example/lib/src/screens/screen_capture_premature_extension_page.dart diff --git a/example/lib/src/screens/screen_loading_page.dart b/packages/instabug_flutter/example/lib/src/screens/screen_loading_page.dart similarity index 100% rename from example/lib/src/screens/screen_loading_page.dart rename to packages/instabug_flutter/example/lib/src/screens/screen_loading_page.dart diff --git a/packages/instabug_flutter/example/lib/src/screens/user_steps_page.dart b/packages/instabug_flutter/example/lib/src/screens/user_steps_page.dart new file mode 100644 index 000000000..f97cfacc2 --- /dev/null +++ b/packages/instabug_flutter/example/lib/src/screens/user_steps_page.dart @@ -0,0 +1,262 @@ +part of '../../main.dart'; + +class UserStepsPage extends StatefulWidget { + static const screenName = 'user_steps'; + + const UserStepsPage({Key? key}) : super(key: key); + + @override + _UserStepsPageState createState() => _UserStepsPageState(); +} + +class _UserStepsPageState extends State { + double _currentSliderValue = 20.0; + + RangeValues _currentRangeValues = const RangeValues(40, 80); + + String? _sliderStatus; + + bool? isChecked = true; + + int? _selectedValue = 1; + + bool light = true; + double _scale = 1.0; // Initial scale of the image + + TextEditingController _controller = TextEditingController(); + + String _currentValue = ''; + List _items = List.generate(20, (index) => 'Item ${index + 1}'); + + @override + void initState() { + super.initState(); + + _controller.addListener(() { + setState(() { + _currentValue = _controller.text; + }); + }); + } + + void _handleRadioValueChanged(int? value) { + setState(() { + _selectedValue = value; + }); + } + + @override + Widget build(BuildContext context) { + return Page( + title: 'User Steps', + children: [ + BackButton(), + NotificationListener( + onNotification: (ScrollNotification notification) { + return false; + }, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: List.generate( + 100, + (_) => InkWell( + onTap: () {}, + child: Container( + width: 100, + height: 100, + color: Colors.red, + margin: EdgeInsets.all(8), + ), + ), + ), + ), + ), + ), + SectionTitle('Sliders'), + Slider( + value: _currentSliderValue, + max: 100, + divisions: 5, + label: _currentSliderValue.round().toString(), + onChanged: (double value) { + setState(() { + _currentSliderValue = value; + }); + }, + ), + RangeSlider( + values: _currentRangeValues, + max: 100, + divisions: 5, + labels: RangeLabels( + _currentRangeValues.start.round().toString(), + _currentRangeValues.end.round().toString(), + ), + onChanged: (RangeValues values) { + setState(() { + _currentRangeValues = values; + }); + }, + ), + SectionTitle('Images'), + Row( + children: [ + Image.asset( + 'assets/img.png', + height: 100, + ), + Image.network( + "https://t3.ftcdn.net/jpg/00/50/07/64/360_F_50076454_TCvZEw37VyB5ZhcwEjkJHddtuV1cFmKY.jpg", + height: 100, + ), + ], + ), + InstabugButton(text: "I'm a button"), + ElevatedButton(onPressed: () {}, child: Text("data")), + SectionTitle('Toggles'), + Row( + children: [ + Checkbox( + tristate: true, + value: isChecked, + onChanged: (bool? value) { + setState(() { + isChecked = value; + }); + }, + ), + Radio( + value: 0, + groupValue: _selectedValue, + onChanged: _handleRadioValueChanged, + ), + Switch( + value: light, + activeColor: Colors.red, + onChanged: (bool value) { + setState(() { + light = value; + }); + }, + ), + ], + ), + GestureDetector( + onScaleUpdate: (details) { + setState(() { + _scale = details.scale; + _scale = _scale.clamp(1.0, + 3.0); // Limit zoom between 1x and 3x// Update scale based on pinch gesture + }); + }, + onScaleEnd: (details) { + // You can add logic to reset or clamp the scale if needed + if (_scale < 1.0) { + _scale = 1.0; // Prevent shrinking below original size + } + }, + child: Transform.scale( + scale: _scale, // Apply the scale transformation + child: Image.asset( + "assets/img.png", + height: 300, + ), + ), + ), + SectionTitle('TextInput'), + Column( + children: [ + Padding( + padding: EdgeInsets.all(16.0), // Set the padding value + child: Column( + children: [ + TextField( + key: Key('text_field'), + controller: _controller, + // Bind the controller to the TextField + decoration: InputDecoration( + labelText: "Type something in a text field with key", + border: OutlineInputBorder(), + ), + ), + TextField( + controller: _controller, + // Bind the controller to the TextField + decoration: InputDecoration( + labelText: "Private view", + border: OutlineInputBorder(), + ), + ), + TextField( + controller: _controller, + // Bind the controller to the TextField + obscureText: true, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Password', + ), + ), + TextFormField( + obscureText: true, + controller: _controller, + // Bind the controller to the TextField + decoration: const InputDecoration( + icon: Icon(Icons.person), + hintText: 'What do people call you?', + labelText: 'Name *', + ), + onSaved: (String? value) { + // This optional block of code can be used to run + // code when the user saves the form. + }, + validator: (String? value) { + return (value != null && value.contains('@')) + ? 'Do not use the @ char.' + : null; + }, + ), + ], + ), + ), + ListView.builder( + itemCount: _items.length, + shrinkWrap: true, + itemBuilder: (context, index) { + return Dismissible( + key: Key(_items[index]), + // Unique key for each item + onDismissed: (direction) { + // Remove the item from the list + setState(() { + _items.removeAt(index); + }); + + // Show a snackbar or other UI feedback on dismissal + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Item dismissed')), + ); + }, + background: Container(color: Colors.red), + // Background color when swiped + direction: DismissDirection.endToStart, + // Swipe direction (left to right) + child: ListTile( + title: Text(_items[index]), + ), + ); + }, + ), + ], + ), + ], + ); + } + + @override + void dispose() { + _controller + .dispose(); // Dispose of the controller when the widget is destroyed + super.dispose(); + } +} diff --git a/example/lib/src/utils/show_messages.dart b/packages/instabug_flutter/example/lib/src/utils/show_messages.dart similarity index 100% rename from example/lib/src/utils/show_messages.dart rename to packages/instabug_flutter/example/lib/src/utils/show_messages.dart diff --git a/example/lib/src/widget/instabug_button.dart b/packages/instabug_flutter/example/lib/src/widget/instabug_button.dart similarity index 100% rename from example/lib/src/widget/instabug_button.dart rename to packages/instabug_flutter/example/lib/src/widget/instabug_button.dart diff --git a/example/lib/src/widget/instabug_clipboard_icon_button.dart b/packages/instabug_flutter/example/lib/src/widget/instabug_clipboard_icon_button.dart similarity index 100% rename from example/lib/src/widget/instabug_clipboard_icon_button.dart rename to packages/instabug_flutter/example/lib/src/widget/instabug_clipboard_icon_button.dart diff --git a/example/lib/src/widget/instabug_clipboard_input.dart b/packages/instabug_flutter/example/lib/src/widget/instabug_clipboard_input.dart similarity index 100% rename from example/lib/src/widget/instabug_clipboard_input.dart rename to packages/instabug_flutter/example/lib/src/widget/instabug_clipboard_input.dart diff --git a/example/lib/src/widget/instabug_text_field.dart b/packages/instabug_flutter/example/lib/src/widget/instabug_text_field.dart similarity index 100% rename from example/lib/src/widget/instabug_text_field.dart rename to packages/instabug_flutter/example/lib/src/widget/instabug_text_field.dart diff --git a/example/lib/src/widget/nested_view.dart b/packages/instabug_flutter/example/lib/src/widget/nested_view.dart similarity index 77% rename from example/lib/src/widget/nested_view.dart rename to packages/instabug_flutter/example/lib/src/widget/nested_view.dart index e61099f8c..8ef9e46ad 100644 --- a/example/lib/src/widget/nested_view.dart +++ b/packages/instabug_flutter/example/lib/src/widget/nested_view.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:instabug_flutter_example/main.dart'; class NestedView extends StatelessWidget { @@ -31,10 +32,12 @@ class NestedView extends StatelessWidget { Row( children: List.generate( breadth, - (index) => NestedView( - depth: depth - 1, - breadth: breadth, - child: child, + (index) => InstabugPrivateView( + child: NestedView( + depth: depth - 1, + breadth: breadth, + child: child, + ), ), ), ), diff --git a/example/lib/src/widget/section_title.dart b/packages/instabug_flutter/example/lib/src/widget/section_title.dart similarity index 100% rename from example/lib/src/widget/section_title.dart rename to packages/instabug_flutter/example/lib/src/widget/section_title.dart diff --git a/packages/instabug_flutter/example/pubspec.lock b/packages/instabug_flutter/example/pubspec.lock new file mode 100644 index 000000000..b520eba0d --- /dev/null +++ b/packages/instabug_flutter/example/pubspec.lock @@ -0,0 +1,370 @@ +# 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: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + url: "https://pub.dev" + source: hosted + version: "1.19.0" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_driver: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 + url: "https://pub.dev" + source: hosted + version: "1.0.4" + 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" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + html: + dependency: transitive + description: + name: html + sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" + url: "https://pub.dev" + source: hosted + version: "0.15.6" + http: + dependency: "direct main" + description: + name: http + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + url: "https://pub.dev" + source: hosted + version: "0.13.6" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + instabug_flutter: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "16.0.0" + instabug_http_client: + dependency: "direct main" + description: + path: "../../instabug_http_client" + relative: true + source: path + version: "2.6.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + url: "https://pub.dev" + source: hosted + version: "10.0.7" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + url: "https://pub.dev" + source: hosted + version: "3.0.8" + 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: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c + url: "https://pub.dev" + source: hosted + version: "1.0.1" + 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" + platform: + dependency: transitive + description: + name: platform + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + process: + dependency: transitive + description: + name: process + sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" + url: "https://pub.dev" + source: hosted + version: "5.0.2" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + 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: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + 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: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + sync_http: + dependency: transitive + description: + name: sync_http + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" + source: hosted + version: "0.3.1" + 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: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + url: "https://pub.dev" + source: hosted + version: "0.7.3" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + 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: "0d55b1f1a31e5ad4c4967bfaa8ade0240b07d20ee4af1dfef5f531056512961a" + url: "https://pub.dev" + source: hosted + version: "2.10.0" + video_player_android: + dependency: transitive + description: + name: video_player_android + sha256: "28dcc4122079f40f93a0965b3679aff1a5f4251cf79611bd8011f937eb6b69de" + url: "https://pub.dev" + source: hosted + version: "2.8.4" + video_player_avfoundation: + dependency: transitive + description: + name: video_player_avfoundation + sha256: f52261d11f97bf14c43e8ed5714f71d8ce4538552b8cc87f45e5d87d3c205e41 + url: "https://pub.dev" + source: hosted + version: "2.8.3" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + sha256: cf2a1d29a284db648fd66cbd18aacc157f9862d77d2cc790f6f9678a46c1db5a + url: "https://pub.dev" + source: hosted + version: "6.4.0" + video_player_web: + dependency: transitive + description: + name: video_player_web + sha256: "9f3c00be2ef9b76a95d94ac5119fb843dca6f2c69e6c9968f6f2b6c9e7afbdeb" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + vm_service: + dependency: transitive + description: + name: vm_service + 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: "1.1.1" + webdriver: + dependency: transitive + description: + name: webdriver + sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8" + url: "https://pub.dev" + source: hosted + version: "3.0.4" +sdks: + dart: ">=3.6.0 <4.0.0" + flutter: ">=3.27.0" diff --git a/example/pubspec.yaml b/packages/instabug_flutter/example/pubspec.yaml similarity index 99% rename from example/pubspec.yaml rename to packages/instabug_flutter/example/pubspec.yaml index dfd49f2aa..2f766b535 100644 --- a/example/pubspec.yaml +++ b/packages/instabug_flutter/example/pubspec.yaml @@ -27,7 +27,7 @@ dependencies: instabug_flutter: path: ../ instabug_http_client: ^2.4.0 - + video_player: dev_dependencies: flutter_driver: sdk: flutter diff --git a/packages/instabug_flutter/example/pubspec_overrides.yaml b/packages/instabug_flutter/example/pubspec_overrides.yaml new file mode 100644 index 000000000..c41d20248 --- /dev/null +++ b/packages/instabug_flutter/example/pubspec_overrides.yaml @@ -0,0 +1,6 @@ +# melos_managed_dependency_overrides: instabug_flutter,instabug_http_client +dependency_overrides: + instabug_flutter: + path: ../ + instabug_http_client: + path: ../../instabug_http_client diff --git a/example/test_driver/example.dart b/packages/instabug_flutter/example/test_driver/example.dart similarity index 100% rename from example/test_driver/example.dart rename to packages/instabug_flutter/example/test_driver/example.dart diff --git a/ios/.gitignore b/packages/instabug_flutter/ios/.gitignore similarity index 100% rename from ios/.gitignore rename to packages/instabug_flutter/ios/.gitignore diff --git a/ios/Assets/.gitkeep b/packages/instabug_flutter/ios/Assets/.gitkeep similarity index 100% rename from ios/Assets/.gitkeep rename to packages/instabug_flutter/ios/Assets/.gitkeep diff --git a/ios/Classes/InstabugFlutterPlugin.h b/packages/instabug_flutter/ios/Classes/InstabugFlutterPlugin.h similarity index 100% rename from ios/Classes/InstabugFlutterPlugin.h rename to packages/instabug_flutter/ios/Classes/InstabugFlutterPlugin.h diff --git a/ios/Classes/InstabugFlutterPlugin.m b/packages/instabug_flutter/ios/Classes/InstabugFlutterPlugin.m similarity index 74% rename from ios/Classes/InstabugFlutterPlugin.m rename to packages/instabug_flutter/ios/Classes/InstabugFlutterPlugin.m index 9b9182ae7..12ab5a58b 100644 --- a/ios/Classes/InstabugFlutterPlugin.m +++ b/packages/instabug_flutter/ios/Classes/InstabugFlutterPlugin.m @@ -9,6 +9,8 @@ #import "RepliesApi.h" #import "SessionReplayApi.h" #import "SurveysApi.h" +#import "PrivateViewApi.h" +#import "PrivateViewHostApi.h" @implementation InstabugFlutterPlugin @@ -22,6 +24,9 @@ + (void)registerWithRegistrar:(NSObject *)registrar { InitRepliesApi([registrar messenger]); InitSessionReplayApi([registrar messenger]); InitSurveysApi([registrar messenger]); + PrivateViewApi* privateViewApi = InitPrivateViewApi([registrar messenger],registrar); + InitPrivateViewApi([registrar messenger], registrar); + InitPrivateViewHostApi([registrar messenger], privateViewApi); } @end diff --git a/ios/Classes/Modules/ApmApi.h b/packages/instabug_flutter/ios/Classes/Modules/ApmApi.h similarity index 100% rename from ios/Classes/Modules/ApmApi.h rename to packages/instabug_flutter/ios/Classes/Modules/ApmApi.h diff --git a/ios/Classes/Modules/ApmApi.m b/packages/instabug_flutter/ios/Classes/Modules/ApmApi.m similarity index 100% rename from ios/Classes/Modules/ApmApi.m rename to packages/instabug_flutter/ios/Classes/Modules/ApmApi.m diff --git a/ios/Classes/Modules/BugReportingApi.h b/packages/instabug_flutter/ios/Classes/Modules/BugReportingApi.h similarity index 100% rename from ios/Classes/Modules/BugReportingApi.h rename to packages/instabug_flutter/ios/Classes/Modules/BugReportingApi.h diff --git a/ios/Classes/Modules/BugReportingApi.m b/packages/instabug_flutter/ios/Classes/Modules/BugReportingApi.m similarity index 100% rename from ios/Classes/Modules/BugReportingApi.m rename to packages/instabug_flutter/ios/Classes/Modules/BugReportingApi.m diff --git a/ios/Classes/Modules/CrashReportingApi.h b/packages/instabug_flutter/ios/Classes/Modules/CrashReportingApi.h similarity index 100% rename from ios/Classes/Modules/CrashReportingApi.h rename to packages/instabug_flutter/ios/Classes/Modules/CrashReportingApi.h diff --git a/ios/Classes/Modules/CrashReportingApi.m b/packages/instabug_flutter/ios/Classes/Modules/CrashReportingApi.m similarity index 100% rename from ios/Classes/Modules/CrashReportingApi.m rename to packages/instabug_flutter/ios/Classes/Modules/CrashReportingApi.m diff --git a/ios/Classes/Modules/FeatureRequestsApi.h b/packages/instabug_flutter/ios/Classes/Modules/FeatureRequestsApi.h similarity index 100% rename from ios/Classes/Modules/FeatureRequestsApi.h rename to packages/instabug_flutter/ios/Classes/Modules/FeatureRequestsApi.h diff --git a/ios/Classes/Modules/FeatureRequestsApi.m b/packages/instabug_flutter/ios/Classes/Modules/FeatureRequestsApi.m similarity index 100% rename from ios/Classes/Modules/FeatureRequestsApi.m rename to packages/instabug_flutter/ios/Classes/Modules/FeatureRequestsApi.m diff --git a/ios/Classes/Modules/InstabugApi.h b/packages/instabug_flutter/ios/Classes/Modules/InstabugApi.h similarity index 70% rename from ios/Classes/Modules/InstabugApi.h rename to packages/instabug_flutter/ios/Classes/Modules/InstabugApi.h index 7030617c9..777013ee0 100644 --- a/ios/Classes/Modules/InstabugApi.h +++ b/packages/instabug_flutter/ios/Classes/Modules/InstabugApi.h @@ -6,5 +6,6 @@ extern void InitInstabugApi(id messenger); - (UIImage *)getImageForAsset:(NSString *)assetName; - (UIFont *)getFontForAsset:(NSString *)assetName error:(FlutterError *_Nullable *_Nonnull)error; ++ (void)setScreenshotMaskingHandler:(nullable void (^)(UIImage *_Nonnull, void (^_Nonnull)(UIImage *_Nonnull)))maskingHandler; @end diff --git a/ios/Classes/Modules/InstabugApi.m b/packages/instabug_flutter/ios/Classes/Modules/InstabugApi.m similarity index 93% rename from ios/Classes/Modules/InstabugApi.m rename to packages/instabug_flutter/ios/Classes/Modules/InstabugApi.m index 84f574b58..7e5ea5ba3 100644 --- a/ios/Classes/Modules/InstabugApi.m +++ b/packages/instabug_flutter/ios/Classes/Modules/InstabugApi.m @@ -7,6 +7,7 @@ #import "ArgsRegistry.h" #import "../Util/IBGAPM+PrivateAPIs.h" +#import "../Util/Instabug+CP.h" #define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16)) / 255.0 green:((float)((rgbValue & 0xFF00) >> 8)) / 255.0 blue:((float)(rgbValue & 0xFF)) / 255.0 alpha:((float)((rgbValue & 0xFF000000) >> 24)) / 255.0]; extern void InitInstabugApi(id messenger) { @@ -63,6 +64,7 @@ - (void)initToken:(nonnull NSString *)token invocationEvents:(nonnull NSArray *)autoMasking error:(FlutterError * _Nullable __autoreleasing * _Nonnull)error { + IBGAutoMaskScreenshotOption resolvedEvents = 0; + + for (NSString *event in autoMasking) { + resolvedEvents |= (ArgsRegistry.autoMasking[event]).integerValue; + } + + [Instabug setAutoMaskScreenshots: resolvedEvents]; + +} ++ (void)setScreenshotMaskingHandler:(nullable void (^)(UIImage * _Nonnull __strong, void (^ _Nonnull __strong)(UIImage * _Nonnull __strong)))maskingHandler { + [Instabug setScreenshotMaskingHandler:maskingHandler]; +} + +- (void)setNetworkLogBodyEnabledIsEnabled:(NSNumber *)isEnabled error:(FlutterError *_Nullable *_Nonnull)error { IBGNetworkLogger.logBodyEnabled = [isEnabled boolValue]; } diff --git a/ios/Classes/Modules/InstabugLogApi.h b/packages/instabug_flutter/ios/Classes/Modules/InstabugLogApi.h similarity index 100% rename from ios/Classes/Modules/InstabugLogApi.h rename to packages/instabug_flutter/ios/Classes/Modules/InstabugLogApi.h diff --git a/ios/Classes/Modules/InstabugLogApi.m b/packages/instabug_flutter/ios/Classes/Modules/InstabugLogApi.m similarity index 100% rename from ios/Classes/Modules/InstabugLogApi.m rename to packages/instabug_flutter/ios/Classes/Modules/InstabugLogApi.m diff --git a/packages/instabug_flutter/ios/Classes/Modules/PrivateViewApi.h b/packages/instabug_flutter/ios/Classes/Modules/PrivateViewApi.h new file mode 100644 index 000000000..80aa0bd36 --- /dev/null +++ b/packages/instabug_flutter/ios/Classes/Modules/PrivateViewApi.h @@ -0,0 +1,34 @@ +#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_flutter/ios/Classes/Modules/PrivateViewApi.m b/packages/instabug_flutter/ios/Classes/Modules/PrivateViewApi.m new file mode 100644 index 000000000..be3e988a4 --- /dev/null +++ b/packages/instabug_flutter/ios/Classes/Modules/PrivateViewApi.m @@ -0,0 +1,144 @@ +#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; +} + +static long long currentTimeMillis; + + +- (void)mask:(UIImage *)screenshot + completion:(void (^)(UIImage *))completion { + + __weak typeof(self) weakSelf = self; + // Wait for the Cupertino animation to complete + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self.flutterApi getPrivateViewsWithCompletion:^(NSArray *rectangles, FlutterError *error) { + UIImage *capturedScreenshot = [self captureScreenshot]; + [weakSelf handlePrivateViewsResult:rectangles + error:error + screenshot:capturedScreenshot + completion:completion]; + }]; + }); +} + +#pragma mark - Private Methods + +// Method to capture a screenshot of the app's main window +- (UIImage *)captureScreenshot { + CGSize imageSize = UIScreen.mainScreen.bounds.size; + UIGraphicsBeginImageContextWithOptions(imageSize, NO, UIScreen.mainScreen.scale); + + // Iterate over all windows, including the keyboard window + for (UIWindow *window in UIApplication.sharedApplication.windows) { + [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES]; + } + + UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return screenshot; +} + +// 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]; + static long long currentTimeMillis2; + currentTimeMillis2 = (long long)([[NSDate date] timeIntervalSince1970] * 1000); + + long long timeDifference = currentTimeMillis2 - currentTimeMillis; + + completion(maskedScreenshot); + NSLog(@"Time Difference: %lld ms (Last: %lld, Current: %lld)", timeDifference, currentTimeMillis2, currentTimeMillis); + + +} + +// 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_flutter/ios/Classes/Modules/PrivateViewHostApi.h b/packages/instabug_flutter/ios/Classes/Modules/PrivateViewHostApi.h new file mode 100644 index 000000000..54ced156c --- /dev/null +++ b/packages/instabug_flutter/ios/Classes/Modules/PrivateViewHostApi.h @@ -0,0 +1,7 @@ +#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_flutter/ios/Classes/Modules/PrivateViewHostApi.m b/packages/instabug_flutter/ios/Classes/Modules/PrivateViewHostApi.m new file mode 100644 index 000000000..e7dbea5cf --- /dev/null +++ b/packages/instabug_flutter/ios/Classes/Modules/PrivateViewHostApi.m @@ -0,0 +1,33 @@ +// +// 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/ios/Classes/Modules/RepliesApi.h b/packages/instabug_flutter/ios/Classes/Modules/RepliesApi.h similarity index 100% rename from ios/Classes/Modules/RepliesApi.h rename to packages/instabug_flutter/ios/Classes/Modules/RepliesApi.h diff --git a/ios/Classes/Modules/RepliesApi.m b/packages/instabug_flutter/ios/Classes/Modules/RepliesApi.m similarity index 100% rename from ios/Classes/Modules/RepliesApi.m rename to packages/instabug_flutter/ios/Classes/Modules/RepliesApi.m diff --git a/ios/Classes/Modules/SessionReplayApi.h b/packages/instabug_flutter/ios/Classes/Modules/SessionReplayApi.h similarity index 100% rename from ios/Classes/Modules/SessionReplayApi.h rename to packages/instabug_flutter/ios/Classes/Modules/SessionReplayApi.h diff --git a/ios/Classes/Modules/SessionReplayApi.m b/packages/instabug_flutter/ios/Classes/Modules/SessionReplayApi.m similarity index 100% rename from ios/Classes/Modules/SessionReplayApi.m rename to packages/instabug_flutter/ios/Classes/Modules/SessionReplayApi.m diff --git a/ios/Classes/Modules/SurveysApi.h b/packages/instabug_flutter/ios/Classes/Modules/SurveysApi.h similarity index 100% rename from ios/Classes/Modules/SurveysApi.h rename to packages/instabug_flutter/ios/Classes/Modules/SurveysApi.h diff --git a/ios/Classes/Modules/SurveysApi.m b/packages/instabug_flutter/ios/Classes/Modules/SurveysApi.m similarity index 100% rename from ios/Classes/Modules/SurveysApi.m rename to packages/instabug_flutter/ios/Classes/Modules/SurveysApi.m diff --git a/ios/Classes/Util/ArgsRegistry.h b/packages/instabug_flutter/ios/Classes/Util/ArgsRegistry.h similarity index 91% rename from ios/Classes/Util/ArgsRegistry.h rename to packages/instabug_flutter/ios/Classes/Util/ArgsRegistry.h index 28e8ecefd..a0eec42e6 100644 --- a/ios/Classes/Util/ArgsRegistry.h +++ b/packages/instabug_flutter/ios/Classes/Util/ArgsRegistry.h @@ -18,8 +18,11 @@ typedef NSDictionary ArgsDictionary; + (ArgsDictionary *)extendedBugReportStates; + (ArgsDictionary *)reproModes; + (ArgsDictionary *)nonFatalExceptionLevel; ++ (ArgsDictionary *)autoMasking; + (ArgsDictionary *)locales; ++ (ArgsDictionary *)userStepsGesture; + + (NSDictionary *)placeholders; + (ArgsDictionary *) userConsentActionTypes; diff --git a/ios/Classes/Util/ArgsRegistry.m b/packages/instabug_flutter/ios/Classes/Util/ArgsRegistry.m similarity index 93% rename from ios/Classes/Util/ArgsRegistry.m rename to packages/instabug_flutter/ios/Classes/Util/ArgsRegistry.m index c4732550e..99ec591ed 100644 --- a/ios/Classes/Util/ArgsRegistry.m +++ b/packages/instabug_flutter/ios/Classes/Util/ArgsRegistry.m @@ -44,6 +44,18 @@ + (ArgsDictionary *)floatingButtonEdges { }; } ++ (ArgsDictionary *)autoMasking { + return @{ + @"AutoMasking.labels" : @(IBGAutoMaskScreenshotOptionLabels), + @"AutoMasking.textInputs" : @(IBGAutoMaskScreenshotOptionTextInputs), + @"AutoMasking.media" : @(IBGAutoMaskScreenshotOptionMedia), + @"AutoMasking.none" : @(IBGAutoMaskScreenshotOptionMaskNothing +), + + }; +} + + + (ArgsDictionary *)recordButtonPositions { return @{ @"Position.topLeft" : @(IBGPositionTopLeft), @@ -218,4 +230,15 @@ + (ArgsDictionary *) userConsentActionTypes { @"UserConsentActionType.noChat": @(IBGActionTypeNoChat) }; } + ++ (ArgsDictionary *) userStepsGesture { + return @{ + @"GestureType.swipe" : @(IBGUIEventTypeSwipe), + @"GestureType.scroll" : @(IBGUIEventTypeScroll), + @"GestureType.tap" : @(IBGUIEventTypeTap), + @"GestureType.pinch" : @(IBGUIEventTypePinch), + @"GestureType.longPress" : @(IBGUIEventTypeLongPress), + @"GestureType.doubleTap" : @(IBGUIEventTypeDoubleTap), + }; +} @end diff --git a/packages/instabug_flutter/ios/Classes/Util/FlutterPluginRegistrar+FlutterEngine.h b/packages/instabug_flutter/ios/Classes/Util/FlutterPluginRegistrar+FlutterEngine.h new file mode 100644 index 000000000..ae31cbcd4 --- /dev/null +++ b/packages/instabug_flutter/ios/Classes/Util/FlutterPluginRegistrar+FlutterEngine.h @@ -0,0 +1,8 @@ +#import + +@interface NSObject (FlutterEngineAccess) + +// Method to access FlutterEngine +- (FlutterEngine *)flutterEngine; + +@end diff --git a/packages/instabug_flutter/ios/Classes/Util/FlutterPluginRegistrar+FlutterEngine.m b/packages/instabug_flutter/ios/Classes/Util/FlutterPluginRegistrar+FlutterEngine.m new file mode 100644 index 000000000..4e5109d3a --- /dev/null +++ b/packages/instabug_flutter/ios/Classes/Util/FlutterPluginRegistrar+FlutterEngine.m @@ -0,0 +1,13 @@ + +#import "FlutterPluginRegistrar+FlutterEngine.h" + +@implementation NSObject (FlutterEngineAccess) + +- (FlutterEngine *)flutterEngine { + if ([self respondsToSelector:@selector(engine)]) { + return (FlutterEngine *)[self performSelector:@selector(engine)]; + } + return nil; +} + +@end diff --git a/ios/Classes/Util/IBGAPM+PrivateAPIs.h b/packages/instabug_flutter/ios/Classes/Util/IBGAPM+PrivateAPIs.h similarity index 100% rename from ios/Classes/Util/IBGAPM+PrivateAPIs.h rename to packages/instabug_flutter/ios/Classes/Util/IBGAPM+PrivateAPIs.h diff --git a/ios/Classes/Util/IBGCrashReporting+CP.h b/packages/instabug_flutter/ios/Classes/Util/IBGCrashReporting+CP.h similarity index 100% rename from ios/Classes/Util/IBGCrashReporting+CP.h rename to packages/instabug_flutter/ios/Classes/Util/IBGCrashReporting+CP.h diff --git a/ios/Classes/Util/IBGNetworkLogger+CP.h b/packages/instabug_flutter/ios/Classes/Util/IBGNetworkLogger+CP.h similarity index 100% rename from ios/Classes/Util/IBGNetworkLogger+CP.h rename to packages/instabug_flutter/ios/Classes/Util/IBGNetworkLogger+CP.h diff --git a/packages/instabug_flutter/ios/Classes/Util/Instabug+CP.h b/packages/instabug_flutter/ios/Classes/Util/Instabug+CP.h new file mode 100644 index 000000000..5e1ef85bb --- /dev/null +++ b/packages/instabug_flutter/ios/Classes/Util/Instabug+CP.h @@ -0,0 +1,9 @@ + +#import + +@interface Instabug (CP) + ++ (void)setScreenshotMaskingHandler:(nullable void (^)(UIImage *, void (^)(UIImage *)))maskingHandler; +@property(nonatomic, assign, class) BOOL sendEventsSwizzling; + +@end diff --git a/ios/Classes/Util/NativeUtils/IBGTimeIntervalUnits.h b/packages/instabug_flutter/ios/Classes/Util/NativeUtils/IBGTimeIntervalUnits.h similarity index 100% rename from ios/Classes/Util/NativeUtils/IBGTimeIntervalUnits.h rename to packages/instabug_flutter/ios/Classes/Util/NativeUtils/IBGTimeIntervalUnits.h diff --git a/ios/instabug_flutter.podspec b/packages/instabug_flutter/ios/instabug_flutter.podspec similarity index 92% rename from ios/instabug_flutter.podspec rename to packages/instabug_flutter/ios/instabug_flutter.podspec index 785f1c07b..02608b997 100644 --- a/ios/instabug_flutter.podspec +++ b/packages/instabug_flutter/ios/instabug_flutter.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'instabug_flutter' - s.version = '15.0.2' + s.version = '16.0.0' s.summary = 'Flutter plugin for integrating the Instabug SDK.' s.author = 'Instabug' s.homepage = 'https://www.instabug.com/platforms/flutter' @@ -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.1.1' + s.dependency 'Instabug', '16.0.1' end diff --git a/lib/instabug_flutter.dart b/packages/instabug_flutter/lib/instabug_flutter.dart similarity index 74% rename from lib/instabug_flutter.dart rename to packages/instabug_flutter/lib/instabug_flutter.dart index 2cc2e8eca..7911163a7 100644 --- a/lib/instabug_flutter.dart +++ b/packages/instabug_flutter/lib/instabug_flutter.dart @@ -19,6 +19,11 @@ export 'src/modules/session_replay.dart'; export 'src/modules/surveys.dart'; // Utils export 'src/utils/instabug_navigator_observer.dart'; +export 'src/utils/instabug_widget.dart'; +export 'src/utils/private_views/instabug_private_view.dart'; +export 'src/utils/private_views/instabug_sliver_private_view.dart'; +export 'src/utils/private_views/private_views_manager.dart' show AutoMasking; export 'src/utils/screen_loading/instabug_capture_screen_loading.dart'; export 'src/utils/screen_loading/route_matcher.dart'; export 'src/utils/screen_name_masker.dart' show ScreenNameMaskingCallback; +export 'src/utils/user_steps/instabug_user_steps.dart'; diff --git a/lib/src/models/crash_data.dart b/packages/instabug_flutter/lib/src/models/crash_data.dart similarity index 100% rename from lib/src/models/crash_data.dart rename to packages/instabug_flutter/lib/src/models/crash_data.dart diff --git a/lib/src/models/exception_data.dart b/packages/instabug_flutter/lib/src/models/exception_data.dart similarity index 100% rename from lib/src/models/exception_data.dart rename to packages/instabug_flutter/lib/src/models/exception_data.dart diff --git a/lib/src/models/feature_flag.dart b/packages/instabug_flutter/lib/src/models/feature_flag.dart similarity index 100% rename from lib/src/models/feature_flag.dart rename to packages/instabug_flutter/lib/src/models/feature_flag.dart diff --git a/lib/src/models/generated_w3c_header.dart b/packages/instabug_flutter/lib/src/models/generated_w3c_header.dart similarity index 100% rename from lib/src/models/generated_w3c_header.dart rename to packages/instabug_flutter/lib/src/models/generated_w3c_header.dart diff --git a/lib/src/models/instabug_route.dart b/packages/instabug_flutter/lib/src/models/instabug_route.dart similarity index 100% rename from lib/src/models/instabug_route.dart rename to packages/instabug_flutter/lib/src/models/instabug_route.dart diff --git a/lib/src/models/network_data.dart b/packages/instabug_flutter/lib/src/models/network_data.dart similarity index 100% rename from lib/src/models/network_data.dart rename to packages/instabug_flutter/lib/src/models/network_data.dart diff --git a/lib/src/models/theme_config.dart b/packages/instabug_flutter/lib/src/models/theme_config.dart similarity index 100% rename from lib/src/models/theme_config.dart rename to packages/instabug_flutter/lib/src/models/theme_config.dart diff --git a/lib/src/models/trace_partial_id.dart b/packages/instabug_flutter/lib/src/models/trace_partial_id.dart similarity index 100% rename from lib/src/models/trace_partial_id.dart rename to packages/instabug_flutter/lib/src/models/trace_partial_id.dart diff --git a/lib/src/models/w3c_feature_flags.dart b/packages/instabug_flutter/lib/src/models/w3c_feature_flags.dart similarity index 100% rename from lib/src/models/w3c_feature_flags.dart rename to packages/instabug_flutter/lib/src/models/w3c_feature_flags.dart diff --git a/lib/src/models/w3c_header.dart b/packages/instabug_flutter/lib/src/models/w3c_header.dart similarity index 100% rename from lib/src/models/w3c_header.dart rename to packages/instabug_flutter/lib/src/models/w3c_header.dart diff --git a/lib/src/modules/apm.dart b/packages/instabug_flutter/lib/src/modules/apm.dart similarity index 100% rename from lib/src/modules/apm.dart rename to packages/instabug_flutter/lib/src/modules/apm.dart diff --git a/lib/src/modules/bug_reporting.dart b/packages/instabug_flutter/lib/src/modules/bug_reporting.dart similarity index 99% rename from lib/src/modules/bug_reporting.dart rename to packages/instabug_flutter/lib/src/modules/bug_reporting.dart index b19147d3d..3bbd80d39 100644 --- a/lib/src/modules/bug_reporting.dart +++ b/packages/instabug_flutter/lib/src/modules/bug_reporting.dart @@ -258,7 +258,7 @@ class BugReporting implements BugReportingFlutterApi { ]) async { return _host.setCommentMinimumCharacterCount( limit, - reportTypes?.mapToString(), + reportTypes.mapToString(), ); } diff --git a/lib/src/modules/crash_reporting.dart b/packages/instabug_flutter/lib/src/modules/crash_reporting.dart similarity index 100% rename from lib/src/modules/crash_reporting.dart rename to packages/instabug_flutter/lib/src/modules/crash_reporting.dart diff --git a/lib/src/modules/feature_requests.dart b/packages/instabug_flutter/lib/src/modules/feature_requests.dart similarity index 100% rename from lib/src/modules/feature_requests.dart rename to packages/instabug_flutter/lib/src/modules/feature_requests.dart diff --git a/lib/src/modules/instabug.dart b/packages/instabug_flutter/lib/src/modules/instabug.dart similarity index 96% rename from lib/src/modules/instabug.dart rename to packages/instabug_flutter/lib/src/modules/instabug.dart index b0073b42a..185f763f7 100644 --- a/lib/src/modules/instabug.dart +++ b/packages/instabug_flutter/lib/src/modules/instabug.dart @@ -22,6 +22,7 @@ import 'package:instabug_flutter/src/utils/feature_flags_manager.dart'; import 'package:instabug_flutter/src/utils/ibg_build_info.dart'; import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/screen_name_masker.dart'; +import 'package:instabug_flutter/src/utils/user_steps/user_step_details.dart'; import 'package:meta/meta.dart'; enum InvocationEvent { @@ -467,6 +468,18 @@ class Instabug { return _host.willRedirectToStore(); } + /// Sets the fullscreen mode for Instabug UI. + /// + /// [isFullscreen] - Whether to enable fullscreen mode or not. + /// + /// Example: + /// ```dart + /// Instabug.setFullscreen(true); + /// ``` + static Future setFullscreen(bool isEnabled) async { + return _host.setFullscreen(isEnabled); + } + /// 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 @@ -502,15 +515,19 @@ class Instabug { return _host.setTheme(themeConfig.toMap()); } - /// Sets the fullscreen mode for Instabug UI. - /// - /// [isFullscreen] - Whether to enable fullscreen mode or not. - /// - /// Example: - /// ```dart - /// Instabug.setFullscreen(true); - /// ``` - static Future setFullscreen(bool isEnabled) async { - return _host.setFullscreen(isEnabled); + /// Enables and disables user interaction steps. + /// [boolean] isEnabled + static Future enableUserSteps(bool isEnabled) async { + return _host.setEnableUserSteps(isEnabled); + } + + /// Enables and disables manual invocation and prompt options for bug and feedback. + /// [boolean] isEnabled + static Future logUserSteps( + GestureType gestureType, + String message, + String? viewName, + ) async { + return _host.logUserSteps(gestureType.toString(), message, viewName); } } diff --git a/lib/src/modules/instabug_log.dart b/packages/instabug_flutter/lib/src/modules/instabug_log.dart similarity index 100% rename from lib/src/modules/instabug_log.dart rename to packages/instabug_flutter/lib/src/modules/instabug_log.dart diff --git a/lib/src/modules/network_logger.dart b/packages/instabug_flutter/lib/src/modules/network_logger.dart similarity index 100% rename from lib/src/modules/network_logger.dart rename to packages/instabug_flutter/lib/src/modules/network_logger.dart diff --git a/lib/src/modules/replies.dart b/packages/instabug_flutter/lib/src/modules/replies.dart similarity index 100% rename from lib/src/modules/replies.dart rename to packages/instabug_flutter/lib/src/modules/replies.dart diff --git a/lib/src/modules/session_replay.dart b/packages/instabug_flutter/lib/src/modules/session_replay.dart similarity index 100% rename from lib/src/modules/session_replay.dart rename to packages/instabug_flutter/lib/src/modules/session_replay.dart diff --git a/lib/src/modules/surveys.dart b/packages/instabug_flutter/lib/src/modules/surveys.dart similarity index 100% rename from lib/src/modules/surveys.dart rename to packages/instabug_flutter/lib/src/modules/surveys.dart diff --git a/lib/src/utils/enum_converter.dart b/packages/instabug_flutter/lib/src/utils/enum_converter.dart similarity index 100% rename from lib/src/utils/enum_converter.dart rename to packages/instabug_flutter/lib/src/utils/enum_converter.dart diff --git a/lib/src/utils/feature_flags_manager.dart b/packages/instabug_flutter/lib/src/utils/feature_flags_manager.dart similarity index 100% rename from lib/src/utils/feature_flags_manager.dart rename to packages/instabug_flutter/lib/src/utils/feature_flags_manager.dart diff --git a/lib/src/utils/ibg_build_info.dart b/packages/instabug_flutter/lib/src/utils/ibg_build_info.dart similarity index 100% rename from lib/src/utils/ibg_build_info.dart rename to packages/instabug_flutter/lib/src/utils/ibg_build_info.dart diff --git a/lib/src/utils/ibg_date_time.dart b/packages/instabug_flutter/lib/src/utils/ibg_date_time.dart similarity index 100% rename from lib/src/utils/ibg_date_time.dart rename to packages/instabug_flutter/lib/src/utils/ibg_date_time.dart diff --git a/lib/src/utils/instabug_logger.dart b/packages/instabug_flutter/lib/src/utils/instabug_logger.dart similarity index 100% rename from lib/src/utils/instabug_logger.dart rename to packages/instabug_flutter/lib/src/utils/instabug_logger.dart diff --git a/lib/src/utils/instabug_montonic_clock.dart b/packages/instabug_flutter/lib/src/utils/instabug_montonic_clock.dart similarity index 100% rename from lib/src/utils/instabug_montonic_clock.dart rename to packages/instabug_flutter/lib/src/utils/instabug_montonic_clock.dart diff --git a/lib/src/utils/instabug_navigator_observer.dart b/packages/instabug_flutter/lib/src/utils/instabug_navigator_observer.dart similarity index 66% rename from lib/src/utils/instabug_navigator_observer.dart rename to packages/instabug_flutter/lib/src/utils/instabug_navigator_observer.dart index d9d6b02db..ccf2cf38b 100644 --- a/lib/src/utils/instabug_navigator_observer.dart +++ b/packages/instabug_flutter/lib/src/utils/instabug_navigator_observer.dart @@ -22,22 +22,23 @@ class InstabugNavigatorObserver extends NavigatorObserver { route: newRoute, name: maskedScreenName, ); + //ignore: invalid_null_aware_operator + WidgetsBinding.instance?.addPostFrameCallback((_) async { + // Starts a the new UI trace which is exclusive to screen loading + ScreenLoadingManager.I.startUiTrace(maskedScreenName, screenName); + // If there is a step that hasn't been pushed yet + if (_steps.isNotEmpty) { + await reportScreenChange(_steps.last.name); + // Report the last step and remove it from the list + _steps.removeLast(); + } + + // Add the new step to the list + _steps.add(route); - // Starts a the new UI trace which is exclusive to screen loading - ScreenLoadingManager.I.startUiTrace(maskedScreenName, screenName); - // If there is a step that hasn't been pushed yet - if (_steps.isNotEmpty) { - // Report the last step and remove it from the list - Instabug.reportScreenChange(_steps.last.name); - _steps.removeLast(); - } - - // Add the new step to the list - _steps.add(route); - Future.delayed(const Duration(milliseconds: 1000), () { // If this route is in the array, report it and remove it from the list if (_steps.contains(route)) { - Instabug.reportScreenChange(route.name); + await reportScreenChange(route.name); _steps.remove(route); } }); @@ -47,6 +48,13 @@ class InstabugNavigatorObserver extends NavigatorObserver { } } + Future reportScreenChange(String name) async { + // Wait for the animation to complete + await Future.delayed(const Duration(milliseconds: 100)); + + Instabug.reportScreenChange(name); + } + @override void didPop(Route route, Route? previousRoute) { if (previousRoute != null) { diff --git a/packages/instabug_flutter/lib/src/utils/instabug_widget.dart b/packages/instabug_flutter/lib/src/utils/instabug_widget.dart new file mode 100644 index 000000000..f63ca8776 --- /dev/null +++ b/packages/instabug_flutter/lib/src/utils/instabug_widget.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter/src/generated/instabug_private_view.api.g.dart'; +import 'package:instabug_flutter/src/utils/private_views/private_views_manager.dart'; +import 'package:meta/meta.dart'; + +@internal +final instabugWidgetKey = GlobalKey(debugLabel: 'instabug_screenshot_widget'); + +class InstabugWidget extends StatefulWidget { + final Widget child; + final bool enablePrivateViews; + final bool enableUserSteps; + final List? automasking; + + const InstabugWidget({ + Key? key, + required this.child, + this.enableUserSteps = true, + this.enablePrivateViews = true, + this.automasking, + }) : super(key: key); + + @override + State createState() => _InstabugWidgetState(); +} + +class _InstabugWidgetState extends State { + @override + void initState() { + if (widget.enablePrivateViews) { + _enableInstabugMaskingPrivateViews(); + } + if (widget.automasking != null) { + PrivateViewsManager.I.addAutoMasking(widget.automasking!); + } + super.initState(); + } + + @override + Widget build(BuildContext context) { + final child = widget.enableUserSteps + ? InstabugUserSteps(child: widget.child) + : widget.child; + + if (widget.enablePrivateViews) { + return RepaintBoundary( + key: instabugWidgetKey, + child: child, + ); + } + return child; + } +} + +void _enableInstabugMaskingPrivateViews() { + final api = InstabugPrivateViewHostApi(); + api.init(); + InstabugPrivateViewFlutterApi.setup(PrivateViewsManager.I); +} diff --git a/lib/src/utils/iterable_ext.dart b/packages/instabug_flutter/lib/src/utils/iterable_ext.dart similarity index 100% rename from lib/src/utils/iterable_ext.dart rename to packages/instabug_flutter/lib/src/utils/iterable_ext.dart diff --git a/lib/src/utils/network_manager.dart b/packages/instabug_flutter/lib/src/utils/network_manager.dart similarity index 100% rename from lib/src/utils/network_manager.dart rename to packages/instabug_flutter/lib/src/utils/network_manager.dart diff --git a/packages/instabug_flutter/lib/src/utils/private_views/instabug_private_view.dart b/packages/instabug_flutter/lib/src/utils/private_views/instabug_private_view.dart new file mode 100644 index 000000000..6903bd47b --- /dev/null +++ b/packages/instabug_flutter/lib/src/utils/private_views/instabug_private_view.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class InstabugPrivateView extends StatelessWidget { + final Widget child; + + const InstabugPrivateView({required this.child, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return child; + } +} diff --git a/packages/instabug_flutter/lib/src/utils/private_views/instabug_sliver_private_view.dart b/packages/instabug_flutter/lib/src/utils/private_views/instabug_sliver_private_view.dart new file mode 100644 index 000000000..1ea626f5a --- /dev/null +++ b/packages/instabug_flutter/lib/src/utils/private_views/instabug_sliver_private_view.dart @@ -0,0 +1,14 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class InstabugSliverPrivateView extends StatelessWidget { + final Widget sliver; + + const InstabugSliverPrivateView({required this.sliver, Key? key}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return sliver; + } +} diff --git a/packages/instabug_flutter/lib/src/utils/private_views/private_views_manager.dart b/packages/instabug_flutter/lib/src/utils/private_views/private_views_manager.dart new file mode 100644 index 000000000..c6a8b1da6 --- /dev/null +++ b/packages/instabug_flutter/lib/src/utils/private_views/private_views_manager.dart @@ -0,0 +1,180 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter/src/generated/instabug.api.g.dart'; +import 'package:instabug_flutter/src/generated/instabug_private_view.api.g.dart'; +import 'package:instabug_flutter/src/utils/enum_converter.dart'; +import 'package:instabug_flutter/src/utils/user_steps/widget_utils.dart'; + +enum AutoMasking { labels, textInputs, media, none } + +extension ValidationMethod on AutoMasking { + bool Function(Widget) hides() { + switch (this) { + case AutoMasking.labels: + return isTextWidget; + case AutoMasking.textInputs: + return isTextInputWidget; + case AutoMasking.media: + return isMedia; + case AutoMasking.none: + return (_) => false; + } + } +} + +/// responsible for masking views +/// before they are sent to the native SDKs. +class PrivateViewsManager implements InstabugPrivateViewFlutterApi { + PrivateViewsManager._() { + _viewChecks = List.of([isPrivateWidget]); + } + + static PrivateViewsManager _instance = PrivateViewsManager._(); + + static PrivateViewsManager get instance => _instance; + static final _host = InstabugHostApi(); + + /// Shorthand for [instance] + static PrivateViewsManager get I => instance; + + @visibleForTesting + // ignore: use_setters_to_change_properties + static void setInstance(PrivateViewsManager instance) { + _instance = instance; + } + + static bool isPrivateWidget(Widget widget) { + final isPrivate = (widget.runtimeType == InstabugPrivateView) || + (widget.runtimeType == InstabugSliverPrivateView); + + return isPrivate; + } + + late List _viewChecks; + + void addAutoMasking(List masking) { + _viewChecks = List.of([isPrivateWidget]); + if (!(masking.contains(AutoMasking.none) && masking.length == 1)) { + _viewChecks.addAll(masking.map((e) => e.hides()).toList()); + } + _host.enableAutoMasking(masking.mapToString()); + } + + Rect? getLayoutRectInfoFromRenderObject(RenderObject? renderObject) { + if (renderObject == null || !renderObject.attached) { + return null; + } + + final globalOffset = _getRenderGlobalOffset(renderObject); + + // Case 1: RenderBox (e.g. Container, Text, etc.) + if (renderObject is RenderBox) { + return renderObject.paintBounds.shift(globalOffset); + } + + // Case 2: RenderSliver (e.g. SliverList, SliverToBoxAdapter, etc.) + if (renderObject is RenderSliver) { + final geometry = renderObject.geometry; + if (geometry == null) { + return null; + } + + final crossAxisExtent = renderObject.constraints.crossAxisExtent; + final paintExtent = geometry.paintExtent; + + return Rect.fromLTWH( + globalOffset.dx, + globalOffset.dy, + // assume vertical scroll by default + crossAxisExtent, + paintExtent, + ); + } + + return null; + } + + // The is the same implementation used in RenderBox.localToGlobal (a subclass of RenderObject) + Offset _getRenderGlobalOffset(RenderObject renderObject) { + // Find the nearest RenderBox ancestor to calculate global position + RenderObject? current = renderObject; + while (current != null && current is! RenderBox) { + final parentNode = current.parent; + if (parentNode is RenderObject) { + current = parentNode; + } else { + current = null; + } + } + + if (current is RenderBox) { + // Get transform from this object to screen root + final transform = renderObject.getTransformTo(null); + return MatrixUtils.transformPoint(transform, Offset.zero); + } + + // fallback: treat as zero offset (shouldn't happen if widget is mounted in tree) + return Offset.zero; + } + + List getRectsOfPrivateViews() { + final context = instabugWidgetKey.currentContext; + if (context == null) return []; + + final rootRenderObject = + context.findRenderObject() as RenderRepaintBoundary?; + if (rootRenderObject is! RenderBox) return []; + + final bounds = Offset.zero & rootRenderObject!.size; + + final rects = []; + + void findPrivateViews(Element element) { + final widget = element.widget; + final isPrivate = _viewChecks.any((e) => e.call(widget)); + if (isPrivate) { + final renderObject = element.findRenderObject(); + if ((renderObject is RenderBox || renderObject is RenderSliver) && + renderObject?.attached == true) { + final isElementInCurrentScreen = isElementInCurrentRoute(element); + final rect = getLayoutRectInfoFromRenderObject(renderObject); + if (rect != null && + rect.overlaps(bounds) && + isElementInCurrentScreen) { + rects.add(rect); + } + } + } else { + element.visitChildElements(findPrivateViews); + } + } + + rects.clear(); + context.visitChildElements(findPrivateViews); + + return rects; + } + + bool isElementInCurrentRoute(Element element) { + final modalRoute = ModalRoute.of(element); + return modalRoute?.isCurrent ?? false; + } + + @override + List getPrivateViews() { + final rects = getRectsOfPrivateViews(); + final result = []; + + for (final rect in rects) { + result.addAll([ + rect.left, + rect.top, + rect.right, + rect.bottom, + ]); + } + + return result; + } +} diff --git a/lib/src/utils/repro_steps_constants.dart b/packages/instabug_flutter/lib/src/utils/repro_steps_constants.dart similarity index 100% rename from lib/src/utils/repro_steps_constants.dart rename to packages/instabug_flutter/lib/src/utils/repro_steps_constants.dart diff --git a/lib/src/utils/screen_loading/flags_config.dart b/packages/instabug_flutter/lib/src/utils/screen_loading/flags_config.dart similarity index 100% rename from lib/src/utils/screen_loading/flags_config.dart rename to packages/instabug_flutter/lib/src/utils/screen_loading/flags_config.dart diff --git a/lib/src/utils/screen_loading/instabug_capture_screen_loading.dart b/packages/instabug_flutter/lib/src/utils/screen_loading/instabug_capture_screen_loading.dart similarity index 100% rename from lib/src/utils/screen_loading/instabug_capture_screen_loading.dart rename to packages/instabug_flutter/lib/src/utils/screen_loading/instabug_capture_screen_loading.dart diff --git a/lib/src/utils/screen_loading/route_matcher.dart b/packages/instabug_flutter/lib/src/utils/screen_loading/route_matcher.dart similarity index 100% rename from lib/src/utils/screen_loading/route_matcher.dart rename to packages/instabug_flutter/lib/src/utils/screen_loading/route_matcher.dart diff --git a/lib/src/utils/screen_loading/screen_loading_manager.dart b/packages/instabug_flutter/lib/src/utils/screen_loading/screen_loading_manager.dart similarity index 100% rename from lib/src/utils/screen_loading/screen_loading_manager.dart rename to packages/instabug_flutter/lib/src/utils/screen_loading/screen_loading_manager.dart diff --git a/lib/src/utils/screen_loading/screen_loading_trace.dart b/packages/instabug_flutter/lib/src/utils/screen_loading/screen_loading_trace.dart similarity index 100% rename from lib/src/utils/screen_loading/screen_loading_trace.dart rename to packages/instabug_flutter/lib/src/utils/screen_loading/screen_loading_trace.dart diff --git a/lib/src/utils/screen_loading/ui_trace.dart b/packages/instabug_flutter/lib/src/utils/screen_loading/ui_trace.dart similarity index 100% rename from lib/src/utils/screen_loading/ui_trace.dart rename to packages/instabug_flutter/lib/src/utils/screen_loading/ui_trace.dart diff --git a/lib/src/utils/screen_name_masker.dart b/packages/instabug_flutter/lib/src/utils/screen_name_masker.dart similarity index 100% rename from lib/src/utils/screen_name_masker.dart rename to packages/instabug_flutter/lib/src/utils/screen_name_masker.dart diff --git a/packages/instabug_flutter/lib/src/utils/user_steps/instabug_user_steps.dart b/packages/instabug_flutter/lib/src/utils/user_steps/instabug_user_steps.dart new file mode 100644 index 000000000..891cd78e2 --- /dev/null +++ b/packages/instabug_flutter/lib/src/utils/user_steps/instabug_user_steps.dart @@ -0,0 +1,261 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter/src/utils/user_steps/user_step_details.dart'; +import 'package:instabug_flutter/src/utils/user_steps/widget_utils.dart'; + +Element? _clickTrackerElement; + +class InstabugUserSteps extends StatefulWidget { + final Widget child; + + const InstabugUserSteps({Key? key, required this.child}) : super(key: key); + + @override + InstabugUserStepsState createState() => InstabugUserStepsState(); + + @override + StatefulElement createElement() { + final element = super.createElement(); + _clickTrackerElement = element; + return element; + } +} + +class InstabugUserStepsState extends State { + static const double _doubleTapThreshold = 300.0; // milliseconds + static const double _pinchSensitivity = 20.0; + static const double _swipeSensitivity = 50.0; + static const double _scrollSensitivity = 50.0; + static const double _tapSensitivity = 20 * 20; + + Timer? _longPressTimer; + Offset? _pointerDownLocation; + GestureType? _gestureType; + String? _gestureMetaData; + DateTime? _lastTapTime; + double _pinchDistance = 0.0; + int _pointerCount = 0; + double? _previousOffset; + + void _onPointerDown(PointerDownEvent event) { + _resetGestureTracking(); + _pointerDownLocation = event.localPosition; + _pointerCount += event.buttons; + _longPressTimer = Timer(const Duration(milliseconds: 500), () { + _gestureType = GestureType.longPress; + }); + } + + void _onPointerUp(PointerUpEvent event, BuildContext context) { + _longPressTimer?.cancel(); + + final gestureType = _detectGestureType(event.localPosition); + if (_gestureType != GestureType.longPress) { + _gestureType = gestureType; + } + + _pointerCount = 0; + + if (_gestureType == null) { + return; + } + final tappedWidget = + _getWidgetDetails(event.localPosition, context, _gestureType!); + if (tappedWidget != null) { + final userStepDetails = tappedWidget.copyWith( + gestureType: _gestureType, + gestureMetaData: _gestureMetaData, + ); + if (userStepDetails.gestureType == null || + userStepDetails.message == null) { + return; + } + + Instabug.logUserSteps( + userStepDetails.gestureType!, + userStepDetails.message!, + userStepDetails.widgetName, + ); + } + } + + GestureType? _detectGestureType(Offset upLocation) { + final delta = upLocation - (_pointerDownLocation ?? Offset.zero); + + if (_pointerCount == 1) { + if (_isTap(delta)) return _detectTapType(); + if (_isSwipe(delta)) return GestureType.swipe; + } else if (_pointerCount == 2 && _isPinch()) { + return GestureType.pinch; + } + + return null; + } + + bool _isTap(Offset delta) => delta.distanceSquared < _tapSensitivity; + + GestureType? _detectTapType() { + final now = DateTime.now(); + final isDoubleTap = _lastTapTime != null && + now.difference(_lastTapTime!).inMilliseconds <= _doubleTapThreshold; + + _lastTapTime = now; + return isDoubleTap ? GestureType.doubleTap : GestureType.tap; + } + + bool _isSwipe(Offset delta) { + final isHorizontal = delta.dx.abs() > delta.dy.abs(); + + if (isHorizontal && delta.dx.abs() > _swipeSensitivity) { + _gestureMetaData = delta.dx > 0 ? "Right" : "Left"; + return true; + } + + if (!isHorizontal && delta.dy.abs() > _swipeSensitivity) { + _gestureMetaData = delta.dy > 0 ? "Down" : "Up"; + return true; + } + + return false; + } + + bool _isPinch() => _pinchDistance.abs() > _pinchSensitivity; + + void _resetGestureTracking() { + _gestureType = null; + _gestureMetaData = null; + _longPressTimer?.cancel(); + } + + UserStepDetails? _getWidgetDetails( + Offset location, + BuildContext context, + GestureType gestureType, + ) { + Element? tappedElement; + var isPrivate = false; + + final rootElement = _clickTrackerElement; + if (rootElement == null || rootElement.widget != widget) return null; + + final hitTestResult = BoxHitTestResult(); + final renderBox = context.findRenderObject()! as RenderBox; + + renderBox.hitTest(hitTestResult, position: _pointerDownLocation!); + + final targets = hitTestResult.path + .where((e) => e.target is RenderBox) + .map((e) => e.target) + .toList(); + + void visitor(Element visitedElement) { + final renderObject = visitedElement.renderObject; + if (renderObject == null) return; + + if (targets.contains(renderObject)) { + final transform = renderObject.getTransformTo(rootElement.renderObject); + final paintBounds = + MatrixUtils.transformRect(transform, renderObject.paintBounds); + + if (paintBounds.contains(_pointerDownLocation!)) { + final widget = visitedElement.widget; + if (!isPrivate) { + isPrivate = widget.runtimeType.toString() == + 'InstabugPrivateView' || + widget.runtimeType.toString() == 'InstabugSliverPrivateView'; + } + if (_isTargetWidget(widget, gestureType)) { + tappedElement = visitedElement; + return; + } + } + } + if (tappedElement == null) { + visitedElement.visitChildElements(visitor); + } + } + + rootElement.visitChildElements(visitor); + if (tappedElement == null) return null; + return UserStepDetails(element: tappedElement, isPrivate: isPrivate); + } + + bool _isTargetWidget(Widget? widget, GestureType type) { + if (widget == null) return false; + switch (type) { + case GestureType.swipe: + return isSwipedWidget(widget); + case GestureType.tap: + case GestureType.longPress: + case GestureType.doubleTap: + return isTappedWidget(widget); + case GestureType.pinch: + return isPinchWidget(widget); + case GestureType.scroll: + return false; + } + } + + void _detectScrollDirection(double currentOffset, Axis direction) { + if (_previousOffset == null) return; + + final delta = (currentOffset - _previousOffset!).abs(); + if (delta < _scrollSensitivity) return; + final String swipeDirection; + if (direction == Axis.horizontal) { + swipeDirection = currentOffset > _previousOffset! ? "Left" : "Right"; + } else { + swipeDirection = currentOffset > _previousOffset! ? "Down" : "Up"; + } + + final userStepDetails = UserStepDetails( + element: null, + isPrivate: false, + gestureMetaData: swipeDirection, + gestureType: GestureType.scroll, + ); + + if (userStepDetails.gestureType == null || + userStepDetails.message == null) { + return; + } + Instabug.logUserSteps( + userStepDetails.gestureType!, + userStepDetails.message!, + "ListView", + ); + } + + @override + Widget build(BuildContext context) { + return Listener( + behavior: HitTestBehavior.translucent, + onPointerDown: _onPointerDown, + onPointerMove: (event) { + if (_pointerCount == 2) { + _pinchDistance = + (event.localPosition - (_pointerDownLocation ?? Offset.zero)) + .distance; + } + }, + onPointerUp: (event) => _onPointerUp(event, context), + child: NotificationListener( + onNotification: (notification) { + if (notification is ScrollStartNotification) { + _previousOffset = notification.metrics.pixels; + } else if (notification is ScrollEndNotification) { + _detectScrollDirection( + notification.metrics.pixels, // Vertical position + notification.metrics.axis, + ); + } + + return true; + }, + child: widget.child, + ), + ); + } +} diff --git a/packages/instabug_flutter/lib/src/utils/user_steps/user_step_details.dart b/packages/instabug_flutter/lib/src/utils/user_steps/user_step_details.dart new file mode 100644 index 000000000..590758eeb --- /dev/null +++ b/packages/instabug_flutter/lib/src/utils/user_steps/user_step_details.dart @@ -0,0 +1,122 @@ +import 'package:flutter/material.dart'; +import 'package:instabug_flutter/src/utils/user_steps/widget_utils.dart'; + +enum GestureType { swipe, scroll, tap, pinch, longPress, doubleTap } + +extension GestureTypeText on GestureType { + String get text { + switch (this) { + case GestureType.swipe: + return "Swiped"; + case GestureType.scroll: + return "Scrolled"; + case GestureType.tap: + return "Tapped"; + case GestureType.pinch: + return "Pinched"; + case GestureType.longPress: + return "Long Pressed"; + case GestureType.doubleTap: + return "Double Tapped"; + } + } +} + +class UserStepDetails { + final Element? element; + final bool isPrivate; + final GestureType? gestureType; + final String? gestureMetaData; + final Widget? widget; + + UserStepDetails({ + required this.element, + required this.isPrivate, + this.gestureType, + this.gestureMetaData, + }) : widget = element?.widget; + + String? get key => widget == null ? null : keyToStringValue(widget!.key); + + String? get widgetName { + if (widget == null) return null; + if (widget is InkWell) { + final inkWell = widget! as InkWell; + if (inkWell.child == null) { + return widget.runtimeType.toString(); + } + return "${inkWell.child.runtimeType} Wrapped with ${widget.runtimeType}"; + } else if (widget is GestureDetector) { + final gestureDetector = widget! as GestureDetector; + + if (gestureDetector.child == null) { + return widget.runtimeType.toString(); + } + return "${gestureDetector.child.runtimeType} Wrapped with ${widget.runtimeType}"; + } + return widget.runtimeType.toString(); + } + + String? get message { + if (gestureType == null) return null; + if (gestureType == GestureType.pinch) { + return gestureType?.text; + } + var baseMessage = ""; + + if (gestureType == GestureType.scroll || gestureType == GestureType.swipe) { + baseMessage += + gestureMetaData?.isNotEmpty == true ? '$gestureMetaData ' : ''; + } + + if (widgetName != null) baseMessage += " $widgetName "; + + if (!isPrivate && widget != null) { + final additionalInfo = _getWidgetSpecificDetails(); + if (additionalInfo != null) baseMessage += additionalInfo; + } + + if (key != null) baseMessage += " with key '$key' "; + + return baseMessage.trimRight(); + } + + String? _getWidgetSpecificDetails() { + if (isSliderWidget(widget!)) { + final value = getSliderValue(widget!); + if (value?.isNotEmpty == true) { + return " to '$value'"; + } + } else if (isTextWidget(widget!) || isButtonWidget(widget!)) { + final label = getLabelRecursively(element!); + if (label?.isNotEmpty == true) { + return "'$label'"; + } + } else if (isToggleableWidget(widget!)) { + final value = getToggleValue(widget!); + if (value?.isNotEmpty == true) { + return " ('$value')"; + } + } else if (isTextInputWidget(widget!)) { + final value = getTextInputValue(widget!); + final hint = getTextHintValue(widget!); + if (value?.isNotEmpty == true) return " '$value'"; + if (hint?.isNotEmpty == true) return "(placeholder:'$hint')"; + } + return null; + } + + UserStepDetails copyWith({ + Element? element, + bool? isPrivate, + GestureType? gestureType, + String? gestureMetaData, + }) { + return UserStepDetails( + element: element ?? this.element, + isPrivate: isPrivate ?? this.isPrivate, + gestureType: gestureType ?? this.gestureType, + gestureMetaData: gestureMetaData ?? this.gestureMetaData, + ); + } +} diff --git a/packages/instabug_flutter/lib/src/utils/user_steps/widget_utils.dart b/packages/instabug_flutter/lib/src/utils/user_steps/widget_utils.dart new file mode 100644 index 000000000..939aa4660 --- /dev/null +++ b/packages/instabug_flutter/lib/src/utils/user_steps/widget_utils.dart @@ -0,0 +1,223 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +/// Converts a [Key] into a string representation, supporting various key types. +String? keyToStringValue(Key? key) { + if (key == null) return null; + + if (key is ValueKey) { + return key.value?.toString(); + } else if (key is GlobalObjectKey) { + return key.value.toString(); + } else if (key is ObjectKey) { + return key.value?.toString(); + } + + return key.toString(); +} + +/// Checks if a widget is a button or button-like component. +bool isButtonWidget(Widget widget) { + if (widget is ButtonStyleButton) return widget.enabled; + if (widget is MaterialButton) return widget.enabled; + if (widget is CupertinoButton) return widget.enabled; + if (widget is IconButton) return widget.onPressed != null; + if (widget is FloatingActionButton) return widget.onPressed != null; + if (widget is BackButton) return widget.onPressed != null; + if (widget is PopupMenuButton) return widget.enabled; + if (widget is DropdownButton) return widget.onTap != null; + + if (widget is GestureDetector) { + return widget.onTap != null || + widget.onLongPress != null || + widget.onDoubleTap != null || + widget.onTapDown != null; + } + + if (widget is InkWell) { + return widget.onTap != null || + widget.onLongPress != null || + widget.onDoubleTap != null || + widget.onTapDown != null; + } + + return false; +} + +/// Checks if a widget can respond to tap-related gestures. +bool isTappedWidget(Widget? widget) { + if (widget == null) return false; + + return isButtonWidget(widget) || + isToggleableWidget(widget) || + isSliderWidget(widget) || + isTextInputWidget(widget); +} + +/// Checks if a widget supports swipe gestures. +bool isSwipedWidget(Widget? widget) { + return widget is Slider || + widget is CupertinoSlider || + widget is RangeSlider || + widget is Dismissible; +} + +/// Determines if a widget supports pinch gestures (defaulting to those not tappable or swipeable). +bool isPinchWidget(Widget? widget) { + return !isSwipedWidget(widget); +} + +/// Checks if a widget is primarily for displaying text. +bool isTextWidget(Widget widget) { + return widget is Text || + widget is RichText || + widget is SelectableText || + widget is TextSpan || + widget is Placeholder || + widget is TextStyle; +} + +/// Checks if a widget is a slider. +bool isSliderWidget(Widget widget) { + return widget is Slider || widget is CupertinoSlider || widget is RangeSlider; +} + +/// Checks if a widget is an image or image-like. +bool isImageWidget(Widget? widget) { + if (widget == null) { + return false; + } + final isDefaultImage = widget is Image || + widget is FadeInImage || + widget is NetworkImage || + widget is AssetImage || + widget is Icon || + widget is FileImage || + widget is MemoryImage || + widget is ImageProvider; + + if (isDefaultImage) { + return true; + } + final imageWidgetTypes = { + 'CachedNetworkImage', // From cached_network_image package + 'SvgPicture', // flutter_svg package + 'OctoImage', // octo_image package + }; + + return imageWidgetTypes.contains(widget.runtimeType.toString()); +} + +bool isVideoPlayerWidget(Widget widget) { + final videoPlayerTypes = { + 'VideoPlayer', // flutter_video_player + 'Chewie', // chewie video player + 'BetterPlayer', // better_player package + 'YoutubePlayer', // youtube_player_flutter + 'VlcPlayer', // flutter_vlc_player + 'FlickVideoPlayer', // flick_video_player + }; + + return videoPlayerTypes.contains(widget.runtimeType.toString()); +} + +bool isMedia(Widget widget) { + return isImageWidget(widget) || isVideoPlayerWidget(widget); +} + +/// Checks if a widget is toggleable (e.g., switch, checkbox, etc.). +bool isToggleableWidget(Widget widget) { + return widget is Checkbox || + widget is CheckboxListTile || + widget is Radio || + widget is RadioListTile || + widget is Switch || + widget is SwitchListTile || + widget is CupertinoSwitch || + widget is ToggleButtons; +} + +/// Checks if a widget is a text input field. +bool isTextInputWidget(Widget widget) { + return widget is TextField || + widget is CupertinoTextField || + widget is EditableText; +} + +/// Retrieves the label of a widget if available. +String? getLabel(Widget widget) { + if (widget is Text) return widget.data; + if (widget is Semantics) return widget.properties.label; + if (widget is Icon) return widget.semanticLabel; + if (widget is Tooltip) return widget.message; + + return null; +} + +/// Retrieves the value of a toggleable widget. +String? getToggleValue(Widget widget) { + bool? value; + if (widget is Checkbox) value = widget.value; + if (widget is Radio) return widget.groupValue.toString(); + if (widget is RadioListTile) return widget.groupValue.toString(); + if (widget is Switch) value = widget.value; + if (widget is SwitchListTile) value = widget.value; + if (widget is CupertinoSwitch) value = widget.value; + if (widget is ToggleButtons) return widget.isSelected.toString(); + + if (value == false || value == null) { + return "UnSelected"; + } else if (value) { + return "Selected"; + } + return null; +} + +/// Retrieves the value entered in a text input field. +String? getTextInputValue(Widget widget) { + if (widget is TextField && !widget.obscureText) { + return widget.controller?.text; + } else if (widget is CupertinoTextField && !widget.obscureText) { + return widget.controller?.text; + } else if (widget is EditableText && !widget.obscureText) { + return widget.controller.text; + } + + return null; +} + +/// Retrieves the hint value of a text input widget. +String? getTextHintValue(Widget widget) { + if (widget is TextField && !widget.obscureText) { + return widget.decoration?.hintText ?? widget.decoration?.labelText; + } else if (widget is CupertinoTextField && !widget.obscureText) { + return widget.placeholder; + } + + return null; +} + +/// Retrieves the current value of a slider widget. +String? getSliderValue(Widget widget) { + if (widget is Slider) return widget.value.toString(); + if (widget is CupertinoSlider) return widget.value.toString(); + if (widget is RangeSlider) { + return "(${widget.values.start},${widget.values.end})"; + } + + return null; +} + +/// Recursively searches for a label within a widget hierarchy. +String? getLabelRecursively(Element element) { + String? label; + + void visitor(Element e) { + label ??= getLabel(e.widget); + if (label == null) e.visitChildren(visitor); + } + + visitor(element); + + return label; +} diff --git a/lib/src/utils/w3c_header_utils.dart b/packages/instabug_flutter/lib/src/utils/w3c_header_utils.dart similarity index 100% rename from lib/src/utils/w3c_header_utils.dart rename to packages/instabug_flutter/lib/src/utils/w3c_header_utils.dart diff --git a/packages/instabug_flutter/package.json b/packages/instabug_flutter/package.json new file mode 100644 index 000000000..52b3a844e --- /dev/null +++ b/packages/instabug_flutter/package.json @@ -0,0 +1,9 @@ +{ + "name": "Instabug-Flutter", + "version": "0.0.0", + "devDependencies": { + "@instabug/danger-plugin-coverage": "Instabug/danger-plugin-coverage", + "danger": "^11.2.5", + "typescript": "^5.0.4" + } +} diff --git a/pigeons/apm.api.dart b/packages/instabug_flutter/pigeons/apm.api.dart similarity index 100% rename from pigeons/apm.api.dart rename to packages/instabug_flutter/pigeons/apm.api.dart diff --git a/pigeons/bug_reporting.api.dart b/packages/instabug_flutter/pigeons/bug_reporting.api.dart similarity index 100% rename from pigeons/bug_reporting.api.dart rename to packages/instabug_flutter/pigeons/bug_reporting.api.dart diff --git a/pigeons/crash_reporting.api.dart b/packages/instabug_flutter/pigeons/crash_reporting.api.dart similarity index 100% rename from pigeons/crash_reporting.api.dart rename to packages/instabug_flutter/pigeons/crash_reporting.api.dart diff --git a/pigeons/feature_requests.api.dart b/packages/instabug_flutter/pigeons/feature_requests.api.dart similarity index 100% rename from pigeons/feature_requests.api.dart rename to packages/instabug_flutter/pigeons/feature_requests.api.dart diff --git a/pigeons/instabug.api.dart b/packages/instabug_flutter/pigeons/instabug.api.dart similarity index 91% rename from pigeons/instabug.api.dart rename to packages/instabug_flutter/pigeons/instabug.api.dart index aa91aec11..575b40a2b 100644 --- a/pigeons/instabug.api.dart +++ b/packages/instabug_flutter/pigeons/instabug.api.dart @@ -24,6 +24,8 @@ abstract class InstabugHostApi { String? appVariant, ); + void enableAutoMasking(List autoMasking); + void show(); void showWelcomeMessageWithMode(String mode); @@ -38,14 +40,20 @@ abstract class InstabugHostApi { void logOut(); + void setEnableUserSteps(bool isEnabled); + + void logUserSteps( + String gestureType, + String message, + String? viewName, + ); + 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); diff --git a/pigeons/instabug_log.api.dart b/packages/instabug_flutter/pigeons/instabug_log.api.dart similarity index 100% rename from pigeons/instabug_log.api.dart rename to packages/instabug_flutter/pigeons/instabug_log.api.dart diff --git a/packages/instabug_flutter/pigeons/instabug_private_view.api.dart b/packages/instabug_flutter/pigeons/instabug_private_view.api.dart new file mode 100644 index 000000000..9a84a63f3 --- /dev/null +++ b/packages/instabug_flutter/pigeons/instabug_private_view.api.dart @@ -0,0 +1,11 @@ +import 'package:pigeon/pigeon.dart'; + +@FlutterApi() +abstract class InstabugPrivateViewFlutterApi { + List getPrivateViews(); +} + +@HostApi() +abstract class InstabugPrivateViewHostApi { + void init(); +} diff --git a/pigeons/replies.api.dart b/packages/instabug_flutter/pigeons/replies.api.dart similarity index 100% rename from pigeons/replies.api.dart rename to packages/instabug_flutter/pigeons/replies.api.dart diff --git a/pigeons/session_replay.api.dart b/packages/instabug_flutter/pigeons/session_replay.api.dart similarity index 100% rename from pigeons/session_replay.api.dart rename to packages/instabug_flutter/pigeons/session_replay.api.dart diff --git a/pigeons/surveys.api.dart b/packages/instabug_flutter/pigeons/surveys.api.dart similarity index 100% rename from pigeons/surveys.api.dart rename to packages/instabug_flutter/pigeons/surveys.api.dart diff --git a/packages/instabug_flutter/pubspec.lock b/packages/instabug_flutter/pubspec.lock new file mode 100644 index 000000000..5adceef62 --- /dev/null +++ b/packages/instabug_flutter/pubspec.lock @@ -0,0 +1,717 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + url: "https://pub.dev" + source: hosted + version: "61.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 + url: "https://pub.dev" + source: hosted + version: "5.13.0" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + 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" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa" + url: "https://pub.dev" + source: hosted + version: "4.0.4" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" + url: "https://pub.dev" + source: hosted + version: "2.4.13" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 + url: "https://pub.dev" + source: hosted + version: "7.3.2" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: ba95c961bafcd8686d1cf63be864eb59447e795e124d98d6a27d91fcd13602fb + url: "https://pub.dev" + source: hosted + version: "8.11.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" + url: "https://pub.dev" + source: hosted + version: "4.10.1" + collection: + dependency: transitive + description: + name: collection + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + url: "https://pub.dev" + source: hosted + version: "1.19.0" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" + url: "https://pub.dev" + source: hosted + version: "1.15.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + fake_async: + dependency: "direct dev" + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + html: + dependency: transitive + description: + name: html + sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" + url: "https://pub.dev" + source: hosted + version: "0.15.6" + http: + dependency: transitive + description: + name: http + sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + url: "https://pub.dev" + source: hosted + version: "10.0.7" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + url: "https://pub.dev" + source: hosted + version: "3.0.8" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lint: + dependency: "direct dev" + description: + name: lint + sha256: "4a539aa34ec5721a2c7574ae2ca0336738ea4adc2a34887d54b7596310b33c85" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + lints: + dependency: transitive + description: + name: lints + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 + url: "https://pub.dev" + source: hosted + version: "3.0.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + markdown: + dependency: transitive + description: + name: markdown + sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" + url: "https://pub.dev" + source: hosted + version: "7.3.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: "direct main" + description: + name: meta + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + url: "https://pub.dev" + source: hosted + version: "1.15.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mockito: + dependency: "direct dev" + description: + name: mockito + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" + url: "https://pub.dev" + source: hosted + version: "5.4.4" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" + pana: + dependency: "direct dev" + description: + name: pana + sha256: "3fc3fe8e7a9fd4827fa4d625a423eec95d305b2bc3538a3adf7fd6c49217af97" + url: "https://pub.dev" + source: hosted + version: "0.21.45" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + pigeon: + dependency: "direct dev" + description: + name: pigeon + sha256: "6eb9702acc25d5ec340bd1b751e511e2982189dfc40c12e2d69db6e05bab03be" + url: "https://pub.dev" + source: hosted + version: "10.1.5" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + retry: + dependency: transitive + description: + name: retry + sha256: "822e118d5b3aafed083109c72d5f484c6dc66707885e07c0fbcb8b986bba7efc" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + safe_url_check: + dependency: transitive + description: + name: safe_url_check + sha256: "49a3e060a7869cbafc8f4845ca1ecbbaaa53179980a32f4fdfeab1607e90f41d" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: "direct main" + description: + name: stack_trace + sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + tar: + dependency: transitive + description: + name: tar + sha256: "22f67e2d77b51050436620b2a5de521c58ca6f0b75af1d9ab3c8cae2eae58fcd" + url: "https://pub.dev" + source: hosted + version: "1.0.5" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test: + dependency: transitive + description: + name: test + sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f" + url: "https://pub.dev" + source: hosted + version: "1.25.8" + test_api: + dependency: transitive + description: + name: test_api + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + url: "https://pub.dev" + source: hosted + version: "0.7.3" + test_core: + dependency: transitive + description: + name: test_core + sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d" + url: "https://pub.dev" + source: hosted + version: "0.6.5" + timing: + dependency: transitive + description: + name: timing + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + url: "https://pub.dev" + source: hosted + version: "14.3.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" +sdks: + dart: ">=3.6.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/packages/instabug_flutter/pubspec.yaml b/packages/instabug_flutter/pubspec.yaml new file mode 100644 index 000000000..27801e5bc --- /dev/null +++ b/packages/instabug_flutter/pubspec.yaml @@ -0,0 +1,39 @@ +name: instabug_flutter +version: 16.0.0 +description: >- + Instabug empowers mobile teams to monitor, prioritize, and debug + performance and stability issues throughout the app development lifecycle. +homepage: https://www.instabug.com/platforms/flutter +repository: https://github.com/Instabug/Instabug-Flutter +documentation: https://docs.instabug.com/docs/flutter-overview + +dependencies: + flutter: + sdk: flutter + meta: ^1.3.0 + stack_trace: ^1.10.0 + +dev_dependencies: + build_runner: ^2.0.3 + fake_async: ">=1.2.0 <1.4.0" + flutter_test: + sdk: flutter + lint: ^1.0.0 + # mockito v5.2.0 is needed for running Flutter 2 tests on CI + mockito: ">=5.2.0 <5.5.0" + 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.flutter + pluginClass: InstabugFlutterPlugin + ios: + pluginClass: InstabugFlutterPlugin + +environment: + sdk: ">=2.14.0 <4.0.0" + flutter: ">=1.17.0" diff --git a/scripts/pigeon.sh b/packages/instabug_flutter/scripts/pigeon.sh similarity index 100% rename from scripts/pigeon.sh rename to packages/instabug_flutter/scripts/pigeon.sh diff --git a/test/apm_test.dart b/packages/instabug_flutter/test/apm_test.dart similarity index 100% rename from test/apm_test.dart rename to packages/instabug_flutter/test/apm_test.dart diff --git a/test/bug_reporting_test.dart b/packages/instabug_flutter/test/bug_reporting_test.dart similarity index 100% rename from test/bug_reporting_test.dart rename to packages/instabug_flutter/test/bug_reporting_test.dart diff --git a/test/crash_reporting_test.dart b/packages/instabug_flutter/test/crash_reporting_test.dart similarity index 100% rename from test/crash_reporting_test.dart rename to packages/instabug_flutter/test/crash_reporting_test.dart diff --git a/test/feature_flags_manager_test.dart b/packages/instabug_flutter/test/feature_flags_manager_test.dart similarity index 100% rename from test/feature_flags_manager_test.dart rename to packages/instabug_flutter/test/feature_flags_manager_test.dart diff --git a/test/feature_requests_test.dart b/packages/instabug_flutter/test/feature_requests_test.dart similarity index 100% rename from test/feature_requests_test.dart rename to packages/instabug_flutter/test/feature_requests_test.dart diff --git a/test/instabug_log_test.dart b/packages/instabug_flutter/test/instabug_log_test.dart similarity index 100% rename from test/instabug_log_test.dart rename to packages/instabug_flutter/test/instabug_log_test.dart diff --git a/test/instabug_test.dart b/packages/instabug_flutter/test/instabug_test.dart similarity index 100% rename from test/instabug_test.dart rename to packages/instabug_flutter/test/instabug_test.dart diff --git a/test/network_data_test.dart b/packages/instabug_flutter/test/network_data_test.dart similarity index 100% rename from test/network_data_test.dart rename to packages/instabug_flutter/test/network_data_test.dart diff --git a/test/network_logger_test.dart b/packages/instabug_flutter/test/network_logger_test.dart similarity index 100% rename from test/network_logger_test.dart rename to packages/instabug_flutter/test/network_logger_test.dart diff --git a/test/network_manager_test.dart b/packages/instabug_flutter/test/network_manager_test.dart similarity index 100% rename from test/network_manager_test.dart rename to packages/instabug_flutter/test/network_manager_test.dart diff --git a/test/replies_test.dart b/packages/instabug_flutter/test/replies_test.dart similarity index 100% rename from test/replies_test.dart rename to packages/instabug_flutter/test/replies_test.dart diff --git a/test/route_matcher_test.dart b/packages/instabug_flutter/test/route_matcher_test.dart similarity index 100% rename from test/route_matcher_test.dart rename to packages/instabug_flutter/test/route_matcher_test.dart diff --git a/test/session_replay_test.dart b/packages/instabug_flutter/test/session_replay_test.dart similarity index 100% rename from test/session_replay_test.dart rename to packages/instabug_flutter/test/session_replay_test.dart diff --git a/test/surveys_test.dart b/packages/instabug_flutter/test/surveys_test.dart similarity index 100% rename from test/surveys_test.dart rename to packages/instabug_flutter/test/surveys_test.dart diff --git a/test/utils/instabug_navigator_observer_test.dart b/packages/instabug_flutter/test/utils/instabug_navigator_observer_test.dart similarity index 82% rename from test/utils/instabug_navigator_observer_test.dart rename to packages/instabug_flutter/test/utils/instabug_navigator_observer_test.dart index ebf541137..5f138ac8f 100644 --- a/test/utils/instabug_navigator_observer_test.dart +++ b/packages/instabug_flutter/test/utils/instabug_navigator_observer_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: invalid_null_aware_operator + import 'package:fake_async/fake_async.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -43,8 +45,9 @@ void main() { test('should report screen change when a route is pushed', () { fakeAsync((async) { observer.didPush(route, previousRoute); - - async.elapse(const Duration(milliseconds: 1000)); + WidgetsBinding.instance?.handleBeginFrame(Duration.zero); + WidgetsBinding.instance?.handleDrawFrame(); + async.elapse(const Duration(milliseconds: 2000)); verify( mScreenLoadingManager.startUiTrace(screen, screen), @@ -61,7 +64,8 @@ void main() { () { fakeAsync((async) { observer.didPop(route, previousRoute); - + WidgetsBinding.instance?.handleBeginFrame(Duration.zero); + WidgetsBinding.instance?.handleDrawFrame(); async.elapse(const Duration(milliseconds: 1000)); verify( @@ -79,7 +83,8 @@ void main() { () { fakeAsync((async) { observer.didPop(route, null); - + WidgetsBinding.instance?.handleBeginFrame(Duration.zero); + WidgetsBinding.instance?.handleDrawFrame(); async.elapse(const Duration(milliseconds: 1000)); verifyNever( @@ -98,7 +103,8 @@ void main() { const fallback = 'N/A'; observer.didPush(route, previousRoute); - + WidgetsBinding.instance?.handleBeginFrame(Duration.zero); + WidgetsBinding.instance?.handleDrawFrame(); async.elapse(const Duration(milliseconds: 1000)); verify( @@ -118,8 +124,9 @@ void main() { fakeAsync((async) { observer.didPush(route, previousRoute); - - async.elapse(const Duration(milliseconds: 1000)); + WidgetsBinding.instance?.handleBeginFrame(Duration.zero); + WidgetsBinding.instance?.handleDrawFrame(); + async.elapse(const Duration(milliseconds: 2000)); verify( mScreenLoadingManager.startUiTrace(maskedScreen, screen), diff --git a/packages/instabug_flutter/test/utils/private_views/private_views_manager_test.dart b/packages/instabug_flutter/test/utils/private_views/private_views_manager_test.dart new file mode 100644 index 000000000..ba9b1d5d7 --- /dev/null +++ b/packages/instabug_flutter/test/utils/private_views/private_views_manager_test.dart @@ -0,0 +1,161 @@ +import 'dart:typed_data'; +import 'dart:ui' as ui; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter/src/utils/private_views/private_views_manager.dart'; + +Future createTestImage() async { + // Create an empty 1x1 image + final recorder = ui.PictureRecorder(); + final canvas = Canvas(recorder); + final paint = Paint()..color = const Color(0xFFFF0000); // Red pixel + canvas.drawRect(const Rect.fromLTWH(0, 0, 1, 1), paint); + + final img = await recorder.endRecording().toImage(1, 1); + final byteData = await img.toByteData(format: ui.ImageByteFormat.png); + return byteData!.buffer.asUint8List(); +} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + WidgetsFlutterBinding.ensureInitialized(); + + group('PrivateViewsManager Tests', () { + late PrivateViewsManager manager; + + setUp(() { + manager = PrivateViewsManager.instance; + }); + + test('isPrivateWidget detects InstabugPrivateView', () { + final widget = InstabugPrivateView(child: Container()); + expect(PrivateViewsManager.isPrivateWidget(widget), isTrue); + }); + + test('isPrivateWidget detects InstabugSliverPrivateView', () { + final widget = InstabugSliverPrivateView(sliver: Container()); + expect(PrivateViewsManager.isPrivateWidget(widget), isTrue); + }); + + test('isPrivateWidget returns false for other widgets', () { + expect(PrivateViewsManager.isPrivateWidget(Container()), isFalse); + expect(PrivateViewsManager.isPrivateWidget(const Text('Hello')), isFalse); + }); + + testWidgets('getRectsOfPrivateViews detects masked views', (tester) async { + await tester.pumpWidget( + InstabugWidget( + child: MaterialApp( + home: Scaffold( + body: ListView( + children: const [ + SizedBox(width: 100, height: 100), + InstabugPrivateView(child: TextField()), + ], + ), + ), + ), + ), + ); + + final rects = manager.getRectsOfPrivateViews(); + expect(rects.length, 1); + }); + + testWidgets('getRectsOfPrivateViews detects masked labels', (tester) async { + await tester.pumpWidget( + InstabugWidget( + automasking: const [AutoMasking.labels], + child: MaterialApp( + home: Scaffold( + body: ListView( + children: const [ + SizedBox(width: 100, height: 100), + Text("Test 1"), + Text("Test 2"), + ], + ), + ), + ), + ), + ); + + final rects = manager.getRectsOfPrivateViews(); + expect(rects.length, 2); + }); + + testWidgets( + 'getPrivateViews returns correct list of masked view coordinates', + (tester) async { + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: ListView( + children: const [ + InstabugPrivateView( + child: SizedBox(width: 50, height: 50), + ), + ], + ), + ), + ), + ); + + final privateViews = manager.getPrivateViews(); + expect( + privateViews.length % 4, + 0, + ); // Ensure coordinates come in sets of four + }); + + testWidgets('getRectsOfPrivateViews detects masked Media', (tester) async { + final validImage = await tester.runAsync(() => createTestImage()); + + await tester.pumpWidget( + InstabugWidget( + automasking: const [AutoMasking.media], + child: MaterialApp( + home: Scaffold( + body: Column( + children: [ + const SizedBox(width: 100, height: 100), + Image.memory( + validImage!, + ), + ], + ), + ), + ), + ), + ); + + final rects = manager.getRectsOfPrivateViews(); + expect(rects.length, 1); + }); + + testWidgets('getRectsOfPrivateViews detects masked textInputs', + (tester) async { + await tester.pumpWidget( + InstabugWidget( + automasking: const [AutoMasking.textInputs], + child: MaterialApp( + home: Scaffold( + body: ListView( + children: const [ + SizedBox(width: 100, height: 100), + TextField(), + ], + ), + ), + ), + ), + ); + + final rects = manager.getRectsOfPrivateViews(); + expect(rects.length, 1); + }); + }); +} diff --git a/test/utils/screen_loading/instabug_capture_screen_loading_test.dart b/packages/instabug_flutter/test/utils/screen_loading/instabug_capture_screen_loading_test.dart similarity index 100% rename from test/utils/screen_loading/instabug_capture_screen_loading_test.dart rename to packages/instabug_flutter/test/utils/screen_loading/instabug_capture_screen_loading_test.dart diff --git a/test/utils/screen_loading/screen_loading_manager_test.dart b/packages/instabug_flutter/test/utils/screen_loading/screen_loading_manager_test.dart similarity index 100% rename from test/utils/screen_loading/screen_loading_manager_test.dart rename to packages/instabug_flutter/test/utils/screen_loading/screen_loading_manager_test.dart diff --git a/test/utils/screen_loading/screen_loading_trace_test.dart b/packages/instabug_flutter/test/utils/screen_loading/screen_loading_trace_test.dart similarity index 100% rename from test/utils/screen_loading/screen_loading_trace_test.dart rename to packages/instabug_flutter/test/utils/screen_loading/screen_loading_trace_test.dart diff --git a/test/utils/screen_loading/ui_trace_test.dart b/packages/instabug_flutter/test/utils/screen_loading/ui_trace_test.dart similarity index 100% rename from test/utils/screen_loading/ui_trace_test.dart rename to packages/instabug_flutter/test/utils/screen_loading/ui_trace_test.dart diff --git a/test/utils/screen_name_masker_test.dart b/packages/instabug_flutter/test/utils/screen_name_masker_test.dart similarity index 100% rename from test/utils/screen_name_masker_test.dart rename to packages/instabug_flutter/test/utils/screen_name_masker_test.dart diff --git a/packages/instabug_flutter/test/utils/user_steps/instabug_user_steps_test.dart b/packages/instabug_flutter/test/utils/user_steps/instabug_user_steps_test.dart new file mode 100644 index 000000000..9ac05e4cb --- /dev/null +++ b/packages/instabug_flutter/test/utils/user_steps/instabug_user_steps_test.dart @@ -0,0 +1,298 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter/src/utils/user_steps/user_step_details.dart'; +import 'package:mockito/mockito.dart'; + +import '../../instabug_test.mocks.dart'; + +void main() { + late MockInstabugHostApi mockInstabugHostApi; + + setUp(() { + mockInstabugHostApi = MockInstabugHostApi(); + Instabug.$setHostApi(mockInstabugHostApi); + }); + + Widget buildTestWidget(Widget child) { + return MaterialApp(home: InstabugUserSteps(child: child)); + } + + group('InstabugUserSteps Widget', () { + testWidgets('builds child widget correctly', (tester) async { + await tester.pumpWidget(buildTestWidget(const Text('Test Widget'))); + expect(find.text('Test Widget'), findsOneWidget); + }); + + testWidgets('detects tap gestures', (tester) async { + await tester.pumpWidget( + buildTestWidget( + GestureDetector(onTap: () {}, child: const Text('Tap Me')), + ), + ); + + await tester.tap(find.text('Tap Me')); + await tester.pumpAndSettle(); + + verify( + mockInstabugHostApi.logUserSteps( + GestureType.tap.toString(), + any, + any, + ), + ).called(1); + }); + + testWidgets('detects long press gestures', (tester) async { + await tester.pumpWidget( + buildTestWidget( + GestureDetector( + onLongPress: () {}, + child: const Text('Long Press Me'), + ), + ), + ); + + final gesture = await tester + .startGesture(tester.getCenter(find.text('Long Press Me'))); + await tester + .pump(const Duration(seconds: 2)); // Simulate long press duration + await gesture.up(); + + await tester.pump(); + + verify( + mockInstabugHostApi.logUserSteps( + GestureType.longPress.toString(), + any, + any, + ), + ).called(1); + }); + + group('Swipe Gestures', () { + const scrollOffset = Offset(0, -200); + const smallScrollOffset = Offset(0, -20); + + testWidgets('detects scroll gestures', (tester) async { + await tester.pumpWidget( + buildTestWidget( + ListView(children: List.generate(50, (i) => Text('Item $i'))), + ), + ); + + await tester.fling(find.byType(ListView), scrollOffset, 1000); + await tester.pumpAndSettle(); + + verify( + mockInstabugHostApi.logUserSteps( + GestureType.scroll.toString(), + any, + any, + ), + ).called(1); + }); + + testWidgets('ignores small swipe gestures', (tester) async { + await tester.pumpWidget( + buildTestWidget( + ListView(children: List.generate(50, (i) => Text('Item $i'))), + ), + ); + + await tester.fling(find.byType(ListView), smallScrollOffset, 1000); + await tester.pumpAndSettle(); + + verifyNever( + mockInstabugHostApi.logUserSteps( + GestureType.scroll.toString(), + any, + any, + ), + ); + }); + + testWidgets('detects horizontal scroll', (tester) async { + await tester.pumpWidget( + buildTestWidget( + ListView( + scrollDirection: Axis.horizontal, + children: List.generate(20, (i) => Text('Item $i')), + ), + ), + ); + + await tester.drag(find.byType(ListView), const Offset(-300, 0)); + await tester.pumpAndSettle(); + + verify( + mockInstabugHostApi.logUserSteps( + GestureType.scroll.toString(), + argThat(contains('Left')), + "ListView", + ), + ).called(1); + }); + + testWidgets('detects vertical scroll direction', (tester) async { + await tester.pumpWidget( + buildTestWidget( + ListView(children: List.generate(20, (i) => Text('Item $i'))), + ), + ); + + await tester.drag(find.byType(ListView), const Offset(0, -300)); + await tester.pumpAndSettle(); + + verify( + mockInstabugHostApi.logUserSteps( + GestureType.scroll.toString(), + argThat(contains('Down')), + "ListView", + ), + ).called(1); + }); + + testWidgets('does not log small scroll gestures', (tester) async { + await tester.pumpWidget( + buildTestWidget( + ListView(children: List.generate(20, (i) => Text('Item $i'))), + ), + ); + + await tester.drag(find.byType(ListView), const Offset(0, -10)); + await tester.pumpAndSettle(); + + verifyNever( + mockInstabugHostApi.logUserSteps( + GestureType.scroll.toString(), + argThat(contains('Down')), + "ListView", + ), + ); + }); + }); + + group('Pinch Gestures', () { + testWidgets('handles pinch gestures', (tester) async { + await tester.pumpWidget( + buildTestWidget( + Transform.scale( + scale: 1.0, + child: const Icon(Icons.add, size: 300), + ), + ), + ); + + final iconFinder = find.byIcon(Icons.add); + final pinchStart = tester.getCenter(iconFinder); + + final gesture1 = await tester.startGesture(pinchStart); + final gesture2 = + await tester.startGesture(pinchStart + const Offset(100.0, 0.0)); + + await tester.pump(); + await gesture1.moveTo(pinchStart + const Offset(150.0, 0.0)); + await gesture2.moveTo(pinchStart + const Offset(70.0, 0.0)); + + await gesture1.up(); + await gesture2.up(); + + await tester.pump(const Duration(seconds: 1)); + + verify( + mockInstabugHostApi.logUserSteps( + GestureType.pinch.toString(), + any, + any, + ), + ).called(1); + }); + + testWidgets('ignores small pinch gestures', (tester) async { + await tester.pumpWidget( + buildTestWidget( + Transform.scale( + scale: 1.0, + child: const Icon(Icons.add, size: 300), + ), + ), + ); + + final iconFinder = find.byIcon(Icons.add); + final pinchStart = tester.getCenter(iconFinder); + + final gesture1 = await tester.startGesture(pinchStart); + final gesture2 = + await tester.startGesture(pinchStart + const Offset(100.0, 0.0)); + + await tester.pump(); + await gesture1.moveTo(pinchStart + const Offset(10.0, 0.0)); + await gesture2.moveTo(pinchStart + const Offset(110.0, 0.0)); + + await gesture1.up(); + await gesture2.up(); + + await tester.pump(const Duration(seconds: 1)); + + verifyNever( + mockInstabugHostApi.logUserSteps( + GestureType.pinch.toString(), + any, + any, + ), + ); + }); + }); + + group('Double Tap Gestures', () { + testWidgets('logs double tap gestures', (tester) async { + await tester.pumpWidget( + buildTestWidget( + GestureDetector( + onDoubleTap: () {}, + child: const Text('Double Tap Me'), + ), + ), + ); + + final doubleTapFinder = find.text('Double Tap Me'); + await tester.tap(doubleTapFinder); + await tester.pump(const Duration(milliseconds: 50)); + await tester.tap(doubleTapFinder); + await tester.pumpAndSettle(); + + verify( + mockInstabugHostApi.logUserSteps( + GestureType.doubleTap.toString(), + any, + any, + ), + ).called(1); + }); + + testWidgets('does not log single taps as double taps', (tester) async { + await tester.pumpWidget( + buildTestWidget( + GestureDetector( + onDoubleTap: () {}, + child: const Text('Double Tap Me'), + ), + ), + ); + + final doubleTapFinder = find.text('Double Tap Me'); + await tester.tap(doubleTapFinder); + await tester.pump(const Duration(milliseconds: 50)); + + verifyNever( + mockInstabugHostApi.logUserSteps( + GestureType.doubleTap.toString(), + any, + any, + ), + ); + }); + }); + }); +} diff --git a/packages/instabug_flutter/test/utils/user_steps/user_step_details_test.dart b/packages/instabug_flutter/test/utils/user_steps/user_step_details_test.dart new file mode 100644 index 000000000..0d992755f --- /dev/null +++ b/packages/instabug_flutter/test/utils/user_steps/user_step_details_test.dart @@ -0,0 +1,130 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:instabug_flutter/src/utils/user_steps/user_step_details.dart'; + +void main() { + group('GestureTypeText Extension', () { + test('GestureType.text returns correct text', () { + expect(GestureType.swipe.text, 'Swiped'); + expect(GestureType.scroll.text, 'Scrolled'); + expect(GestureType.tap.text, 'Tapped'); + expect(GestureType.pinch.text, 'Pinched'); + expect(GestureType.longPress.text, 'Long Pressed'); + expect(GestureType.doubleTap.text, 'Double Tapped'); + }); + }); + + group('UserStepDetails', () { + test('key returns correct value', () { + final widget = Container(key: const ValueKey('testKey')); + final element = widget.createElement(); + final details = UserStepDetails( + element: element, + isPrivate: false, + ); + + expect(details.key, 'testKey'); + }); + + test('widgetName identifies widget types correctly', () { + const inkWell = InkWell( + child: Text('Child'), + ); + final detailsInkWell = UserStepDetails( + element: inkWell.createElement(), + isPrivate: false, + ); + expect(detailsInkWell.widgetName, "Text Wrapped with InkWell"); + + final gestureDetector = GestureDetector( + child: const Icon(Icons.add), + ); + final detailsGestureDetector = UserStepDetails( + element: gestureDetector.createElement(), + isPrivate: false, + ); + expect( + detailsGestureDetector.widgetName, + "Icon Wrapped with GestureDetector", + ); + }); + + test('message constructs correctly with gestureType', () { + final widget = Container(key: const ValueKey('testKey')); + final element = widget.createElement(); + + final details = UserStepDetails( + element: element, + isPrivate: false, + gestureType: GestureType.tap, + ); + + expect( + details.message, + " Container with key 'testKey'", + ); + }); + + test('_getWidgetSpecificDetails handles slider widgets', () { + final slider = Slider(value: 0.5, onChanged: (_) {}); + final element = slider.createElement(); + + final details = UserStepDetails( + element: element, + isPrivate: false, + gestureType: GestureType.tap, + ); + + expect( + details.message, + contains(" Slider to '0.5'"), + ); + }); + + test('_getWidgetSpecificDetails handles null widget gracefully', () { + final details = UserStepDetails( + element: null, + isPrivate: false, + ); + + expect(details.message, isNull); + }); + + test('widgetName handles null child gracefully in InkWell', () { + const inkWell = InkWell(); + final details = UserStepDetails( + element: inkWell.createElement(), + isPrivate: false, + ); + expect(details.widgetName, "InkWell"); + }); + + test('message includes additional metadata when gestureMetaData is empty', + () { + final widget = Container(key: const ValueKey('testKey')); + final element = widget.createElement(); + + final details = UserStepDetails( + element: element, + isPrivate: false, + gestureType: GestureType.tap, + gestureMetaData: '', + ); + + expect( + details.message, + " Container with key 'testKey'", + ); + }); + + test('widgetName handles GestureDetector without child', () { + final gestureDetector = GestureDetector(); + final details = UserStepDetails( + element: gestureDetector.createElement(), + isPrivate: false, + ); + expect(details.widgetName, "GestureDetector"); + }); + }); +// }); +} diff --git a/packages/instabug_flutter/test/utils/user_steps/widget_utils_test.dart b/packages/instabug_flutter/test/utils/user_steps/widget_utils_test.dart new file mode 100644 index 000000000..631d49c61 --- /dev/null +++ b/packages/instabug_flutter/test/utils/user_steps/widget_utils_test.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:instabug_flutter/src/utils/user_steps/widget_utils.dart'; + +void main() { + group('keyToStringValue', () { + test('returns null for null key', () { + expect(keyToStringValue(null), isNull); + }); + + test('returns value for ValueKey', () { + expect(keyToStringValue(const ValueKey('test')), 'test'); + }); + + test('returns value for GlobalObjectKey', () { + const globalKey = GlobalObjectKey('globalKey'); + expect(keyToStringValue(globalKey), 'globalKey'); + }); + + test('returns value for ObjectKey', () { + expect(keyToStringValue(const ObjectKey('objectKey')), 'objectKey'); + }); + + test('returns toString for unknown key type', () { + const customKey = Key('customKey'); + expect(keyToStringValue(customKey), 'customKey'); + }); + }); + + group('isButtonWidget', () { + test('detects ButtonStyleButton', () { + final button = + ElevatedButton(onPressed: () {}, child: const Text('Button')); + expect(isButtonWidget(button), true); + }); + + test('detects disabled MaterialButton', () { + const button = MaterialButton(onPressed: null); + expect(isButtonWidget(button), false); + }); + + test('detects IconButton with onPressed', () { + final button = IconButton(onPressed: () {}, icon: const Icon(Icons.add)); + expect(isButtonWidget(button), true); + }); + + test('returns false for non-button widget', () { + const widget = Text('Not a button'); + expect(isButtonWidget(widget), false); + }); + }); + + group('isTappedWidget', () { + test('detects button widget', () { + final button = + ElevatedButton(onPressed: () {}, child: const Text('Button')); + expect(isTappedWidget(button), true); + }); + + test('returns false for null widget', () { + expect(isTappedWidget(null), false); + }); + }); + + group('isTextWidget', () { + test('detects Text widget', () { + const widget = Text('Hello'); + expect(isTextWidget(widget), true); + }); + + test('returns false for non-text widget', () { + const widget = Icon(Icons.add); + expect(isTextWidget(widget), false); + }); + }); + + group('getLabel', () { + test('returns label from Text widget', () { + const widget = Text('Label'); + expect(getLabel(widget), 'Label'); + }); + + test('returns label from Tooltip', () { + const widget = Tooltip(message: 'Tooltip message', child: Text('Child')); + expect(getLabel(widget), 'Tooltip message'); + }); + + test('returns null for unlabeled widget', () { + const widget = Icon(Icons.add); + expect(getLabel(widget), isNull); + }); + }); + + group('getSliderValue', () { + test('returns value from Slider', () { + final widget = Slider(value: 0.5, onChanged: (_) {}); + expect(getSliderValue(widget), '0.5'); + }); + + test('returns value from RangeSlider', () { + final widget = + RangeSlider(values: const RangeValues(0.2, 0.8), onChanged: (_) {}); + expect(getSliderValue(widget), '(0.2,0.8)'); + }); + + test('returns null for non-slider widget', () { + const widget = Text('Not a slider'); + expect(getSliderValue(widget), isNull); + }); + }); +} diff --git a/test/w3_header_utils_test.dart b/packages/instabug_flutter/test/w3_header_utils_test.dart similarity index 100% rename from test/w3_header_utils_test.dart rename to packages/instabug_flutter/test/w3_header_utils_test.dart diff --git a/packages/instabug_flutter/yarn.lock b/packages/instabug_flutter/yarn.lock new file mode 100644 index 000000000..d86ee57b3 --- /dev/null +++ b/packages/instabug_flutter/yarn.lock @@ -0,0 +1,960 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@gitbeaker/core@^21.7.0": + version "21.7.0" + resolved "https://registry.yarnpkg.com/@gitbeaker/core/-/core-21.7.0.tgz#fcf7a12915d39f416e3f316d0a447a814179b8e5" + integrity sha512-cw72rE7tA27wc6JJe1WqeAj9v/6w0S7XJcEji+bRNjTlUfE1zgfW0Gf1mbGUi7F37SOABGCosQLfg9Qe63aIqA== + dependencies: + "@gitbeaker/requester-utils" "^21.7.0" + form-data "^3.0.0" + li "^1.3.0" + xcase "^2.0.1" + +"@gitbeaker/node@^21.3.0": + version "21.7.0" + resolved "https://registry.yarnpkg.com/@gitbeaker/node/-/node-21.7.0.tgz#2c19613f44ee497a8808c555abec614ebd2dfcad" + integrity sha512-OdM3VcTKYYqboOsnbiPcO0XimXXpYK4gTjARBZ6BWc+1LQXKmqo+OH6oUbyxOoaFu9hHECafIt3WZU3NM4sZTg== + dependencies: + "@gitbeaker/core" "^21.7.0" + "@gitbeaker/requester-utils" "^21.7.0" + form-data "^3.0.0" + got "^11.1.4" + xcase "^2.0.1" + +"@gitbeaker/requester-utils@^21.7.0": + version "21.7.0" + resolved "https://registry.yarnpkg.com/@gitbeaker/requester-utils/-/requester-utils-21.7.0.tgz#e9a9cfaf268d2a99eb7bbdc930943240a5f88878" + integrity sha512-eLTaVXlBnh8Qimj6QuMMA06mu/mLcJm3dy8nqhhn/Vm/D25sPrvpGwmbfFyvzj6QujPqtHvFfsCHtyZddL01qA== + dependencies: + form-data "^3.0.0" + query-string "^6.12.1" + xcase "^2.0.1" + +"@instabug/danger-plugin-coverage@Instabug/danger-plugin-coverage": + version "0.0.0-development" + resolved "git+ssh://git@github.com/Instabug/danger-plugin-coverage.git#a3941bd25421b0978ec636648a557b2280d0c9e6" + dependencies: + fast-xml-parser "^4.2.0" + +"@octokit/auth-token@^2.4.4": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36" + integrity sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g== + dependencies: + "@octokit/types" "^6.0.3" + +"@octokit/core@^3.5.1": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.6.0.tgz#3376cb9f3008d9b3d110370d90e0a1fcd5fe6085" + integrity sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q== + dependencies: + "@octokit/auth-token" "^2.4.4" + "@octokit/graphql" "^4.5.8" + "@octokit/request" "^5.6.3" + "@octokit/request-error" "^2.0.5" + "@octokit/types" "^6.0.3" + before-after-hook "^2.2.0" + universal-user-agent "^6.0.0" + +"@octokit/endpoint@^6.0.1": + version "6.0.12" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.12.tgz#3b4d47a4b0e79b1027fb8d75d4221928b2d05658" + integrity sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA== + dependencies: + "@octokit/types" "^6.0.3" + is-plain-object "^5.0.0" + universal-user-agent "^6.0.0" + +"@octokit/graphql@^4.5.8": + version "4.8.0" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.8.0.tgz#664d9b11c0e12112cbf78e10f49a05959aa22cc3" + integrity sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg== + dependencies: + "@octokit/request" "^5.6.0" + "@octokit/types" "^6.0.3" + universal-user-agent "^6.0.0" + +"@octokit/openapi-types@^12.11.0": + version "12.11.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-12.11.0.tgz#da5638d64f2b919bca89ce6602d059f1b52d3ef0" + integrity sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ== + +"@octokit/plugin-paginate-rest@^2.16.8": + version "2.21.3" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz#7f12532797775640dbb8224da577da7dc210c87e" + integrity sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw== + dependencies: + "@octokit/types" "^6.40.0" + +"@octokit/plugin-request-log@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85" + integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== + +"@octokit/plugin-rest-endpoint-methods@^5.12.0": + version "5.16.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz#7ee8bf586df97dd6868cf68f641354e908c25342" + integrity sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw== + dependencies: + "@octokit/types" "^6.39.0" + deprecation "^2.3.1" + +"@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677" + integrity sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg== + dependencies: + "@octokit/types" "^6.0.3" + deprecation "^2.0.0" + once "^1.4.0" + +"@octokit/request@^5.6.0", "@octokit/request@^5.6.3": + version "5.6.3" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0" + integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A== + dependencies: + "@octokit/endpoint" "^6.0.1" + "@octokit/request-error" "^2.1.0" + "@octokit/types" "^6.16.1" + is-plain-object "^5.0.0" + node-fetch "^2.6.7" + universal-user-agent "^6.0.0" + +"@octokit/rest@^16.43.0 || ^17.11.0 || ^18.12.0", "@octokit/rest@^18.12.0": + version "18.12.0" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.12.0.tgz#f06bc4952fc87130308d810ca9d00e79f6988881" + integrity sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q== + dependencies: + "@octokit/core" "^3.5.1" + "@octokit/plugin-paginate-rest" "^2.16.8" + "@octokit/plugin-request-log" "^1.0.4" + "@octokit/plugin-rest-endpoint-methods" "^5.12.0" + +"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.39.0", "@octokit/types@^6.40.0": + version "6.41.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04" + integrity sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg== + dependencies: + "@octokit/openapi-types" "^12.11.0" + +"@sindresorhus/is@^4.0.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== + +"@szmarczak/http-timer@^4.0.5": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" + integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== + dependencies: + defer-to-connect "^2.0.0" + +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + +"@types/cacheable-request@^6.0.1": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" + integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "^3.1.4" + "@types/node" "*" + "@types/responselike" "^1.0.0" + +"@types/http-cache-semantics@*": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" + integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== + +"@types/keyv@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" + integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== + dependencies: + "@types/node" "*" + +"@types/node@*": + version "18.15.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" + integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== + +"@types/responselike@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + dependencies: + "@types/node" "*" + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +async-retry@1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.2.3.tgz#a6521f338358d322b1a0012b79030c6f411d1ce0" + integrity sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q== + dependencies: + retry "0.12.0" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +before-after-hook@^2.2.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" + integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== + +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + +cacheable-lookup@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" + integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== + +cacheable-request@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" + integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^6.0.1" + responselike "^2.0.0" + +chalk@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +clone-response@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== + dependencies: + mimic-response "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +colors@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^2.18.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +core-js@^3.8.2: + version "3.30.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.30.0.tgz#64ac6f83bc7a49fd42807327051701d4b1478dea" + integrity sha512-hQotSSARoNh1mYPi9O2YaWeiq/cEB95kOrFb4NCrO4RIFt1qqNpKsaE+vy/L3oiqvND5cThqXzUU3r9F7Efztg== + +danger@^11.2.5: + version "11.2.5" + resolved "https://registry.yarnpkg.com/danger/-/danger-11.2.5.tgz#e0f20fbbc35dedff83a67595a684425c5711606a" + integrity sha512-t3M20P0TsslkEkakha1PJHLyD+KxbHHdlhsauC/a53GQgQFO3aKz3Zg5YCHJ+javp0gVkPcUgFrgc7voW1Qp6g== + dependencies: + "@gitbeaker/node" "^21.3.0" + "@octokit/rest" "^18.12.0" + async-retry "1.2.3" + chalk "^2.3.0" + commander "^2.18.0" + core-js "^3.8.2" + debug "^4.1.1" + fast-json-patch "^3.0.0-1" + get-stdin "^6.0.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.1" + hyperlinker "^1.0.0" + json5 "^2.1.0" + jsonpointer "^5.0.0" + jsonwebtoken "^9.0.0" + lodash.find "^4.6.0" + lodash.includes "^4.3.0" + lodash.isobject "^3.0.2" + lodash.keys "^4.0.8" + lodash.mapvalues "^4.6.0" + lodash.memoize "^4.1.2" + memfs-or-file-map-to-github-branch "^1.2.1" + micromatch "^4.0.4" + node-cleanup "^2.1.2" + node-fetch "^2.6.7" + override-require "^1.1.1" + p-limit "^2.1.0" + parse-diff "^0.7.0" + parse-git-config "^2.0.3" + parse-github-url "^1.0.2" + parse-link-header "^2.0.0" + pinpoint "^1.1.0" + prettyjson "^1.2.1" + readline-sync "^1.4.9" + regenerator-runtime "^0.13.9" + require-from-string "^2.0.2" + supports-hyperlinks "^1.0.1" + +debug@4, debug@^4.1.1: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decode-uri-component@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +defer-to-connect@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +deprecation@^2.0.0, deprecation@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" + integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== + +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw== + dependencies: + homedir-polyfill "^1.0.1" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +fast-json-patch@^3.0.0-1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-3.1.1.tgz#85064ea1b1ebf97a3f7ad01e23f9337e72c66947" + integrity sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ== + +fast-xml-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.0.tgz#6db2ba33b95b8b4af93f94fe024d4b4d02a50855" + integrity sha512-+zVQv4aVTO+o8oRUyRL7PjgeVo1J6oP8Cw2+a8UTZQcj5V0yUK5T63gTN0ldgiHDPghUjKc4OpT6SwMTwnOQug== + dependencies: + strnum "^1.0.5" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +filter-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" + integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs-exists-sync@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" + integrity sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg== + +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +git-config-path@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/git-config-path/-/git-config-path-1.0.1.tgz#6d33f7ed63db0d0e118131503bab3aca47d54664" + integrity sha512-KcJ2dlrrP5DbBnYIZ2nlikALfRhKzNSX0stvv3ImJ+fvC4hXKoV+U+74SV0upg+jlQZbrtQzc0bu6/Zh+7aQbg== + dependencies: + extend-shallow "^2.0.1" + fs-exists-sync "^0.1.0" + homedir-polyfill "^1.0.0" + +got@^11.1.4: + version "11.8.6" + resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" + integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== + dependencies: + "@sindresorhus/is" "^4.0.0" + "@szmarczak/http-timer" "^4.0.5" + "@types/cacheable-request" "^6.0.1" + "@types/responselike" "^1.0.0" + cacheable-lookup "^5.0.3" + cacheable-request "^7.0.2" + decompress-response "^6.0.0" + http2-wrapper "^1.0.0-beta.5.2" + lowercase-keys "^2.0.0" + p-cancelable "^2.0.0" + responselike "^2.0.0" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + +http-cache-semantics@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + +http2-wrapper@^1.0.0-beta.5.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" + integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.0.0" + +https-proxy-agent@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +hyperlinker@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" + integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ== + +ini@^1.3.5: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +is-extendable@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json5@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonpointer@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" + integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== + +jsonwebtoken@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz#d0faf9ba1cc3a56255fe49c0961a67e520c1926d" + integrity sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw== + dependencies: + jws "^3.2.2" + lodash "^4.17.21" + ms "^2.1.1" + semver "^7.3.8" + +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + +keyv@^4.0.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" + integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g== + dependencies: + json-buffer "3.0.1" + +li@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/li/-/li-1.3.0.tgz#22c59bcaefaa9a8ef359cf759784e4bf106aea1b" + integrity sha512-z34TU6GlMram52Tss5mt1m//ifRIpKH5Dqm7yUVOdHI+BQCs9qGPHFaCUTIzsWX7edN30aa2WrPwR7IO10FHaw== + +lodash.find@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1" + integrity sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg== + +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== + +lodash.isobject@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-3.0.2.tgz#3c8fb8d5b5bf4bf90ae06e14f2a530a4ed935e1d" + integrity sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA== + +lodash.keys@^4.0.8: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205" + integrity sha512-J79MkJcp7Df5mizHiVNpjoHXLi4HLjh9VLS/M7lQSGoQ+0oQ+lWEigREkqKyizPB1IawvQLLKY8mzEcm1tkyxQ== + +lodash.mapvalues@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" + integrity sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ== + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +memfs-or-file-map-to-github-branch@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/memfs-or-file-map-to-github-branch/-/memfs-or-file-map-to-github-branch-1.2.1.tgz#fdb9a85408262316a9bd5567409bf89be7d72f96" + integrity sha512-I/hQzJ2a/pCGR8fkSQ9l5Yx+FQ4e7X6blNHyWBm2ojeFLT3GVzGkTj7xnyWpdclrr7Nq4dmx3xrvu70m3ypzAQ== + dependencies: + "@octokit/rest" "^16.43.0 || ^17.11.0 || ^18.12.0" + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mimic-response@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +minimist@^1.2.0: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +node-cleanup@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/node-cleanup/-/node-cleanup-2.1.2.tgz#7ac19abd297e09a7f72a71545d951b517e4dde2c" + integrity sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw== + +node-fetch@^2.6.7: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" + integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== + +once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +override-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/override-require/-/override-require-1.1.1.tgz#6ae22fadeb1f850ffb0cf4c20ff7b87e5eb650df" + integrity sha512-eoJ9YWxFcXbrn2U8FKT6RV+/Kj7fiGAB1VvHzbYKt8xM5ZuKZgCGvnHzDxmreEjcBH28ejg5MiOH4iyY1mQnkg== + +p-cancelable@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" + integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== + +p-limit@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parse-diff@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/parse-diff/-/parse-diff-0.7.1.tgz#9b7a2451c3725baf2c87c831ba192d40ee2237d4" + integrity sha512-1j3l8IKcy4yRK2W4o9EYvJLSzpAVwz4DXqCewYyx2vEwk2gcf3DBPqc8Fj4XV3K33OYJ08A8fWwyu/ykD/HUSg== + +parse-git-config@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/parse-git-config/-/parse-git-config-2.0.3.tgz#6fb840d4a956e28b971c97b33a5deb73a6d5b6bb" + integrity sha512-Js7ueMZOVSZ3tP8C7E3KZiHv6QQl7lnJ+OkbxoaFazzSa2KyEHqApfGbU3XboUgUnq4ZuUmskUpYKTNx01fm5A== + dependencies: + expand-tilde "^2.0.2" + git-config-path "^1.0.1" + ini "^1.3.5" + +parse-github-url@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-github-url/-/parse-github-url-1.0.2.tgz#242d3b65cbcdda14bb50439e3242acf6971db395" + integrity sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw== + +parse-link-header@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-link-header/-/parse-link-header-2.0.0.tgz#949353e284f8aa01f2ac857a98f692b57733f6b7" + integrity sha512-xjU87V0VyHZybn2RrCX5TIFGxTVZE6zqqZWMPlIKiSKuWh/X5WZdt+w1Ki1nXB+8L/KtL+nZ4iq+sfI6MrhhMw== + dependencies: + xtend "~4.0.1" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pinpoint@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pinpoint/-/pinpoint-1.1.0.tgz#0cf7757a6977f1bf7f6a32207b709e377388e874" + integrity sha512-+04FTD9x7Cls2rihLlo57QDCcHoLBGn5Dk51SwtFBWkUWLxZaBXyNVpCw1S+atvE7GmnFjeaRZ0WLq3UYuqAdg== + +prettyjson@^1.2.1: + version "1.2.5" + resolved "https://registry.yarnpkg.com/prettyjson/-/prettyjson-1.2.5.tgz#ef3cfffcc70505c032abc59785884b4027031835" + integrity sha512-rksPWtoZb2ZpT5OVgtmy0KHVM+Dca3iVwWY9ifwhcexfjebtgjg3wmrUt9PvJ59XIYBcknQeYHD8IAnVlh9lAw== + dependencies: + colors "1.4.0" + minimist "^1.2.0" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +query-string@^6.12.1: + version "6.14.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.14.1.tgz#7ac2dca46da7f309449ba0f86b1fd28255b0c86a" + integrity sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw== + dependencies: + decode-uri-component "^0.2.0" + filter-obj "^1.1.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +readline-sync@^1.4.9: + version "1.4.10" + resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b" + integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw== + +regenerator-runtime@^0.13.9: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-alpn@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== + +responselike@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" + integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== + dependencies: + lowercase-keys "^2.0.0" + +retry@0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + +safe-buffer@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +semver@^7.3.8: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== + +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + +supports-color@^5.0.0, supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-hyperlinks@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz#71daedf36cc1060ac5100c351bb3da48c29c0ef7" + integrity sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw== + dependencies: + has-flag "^2.0.0" + supports-color "^5.0.0" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +typescript@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" + integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== + +universal-user-agent@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" + integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +xcase@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/xcase/-/xcase-2.0.1.tgz#c7fa72caa0f440db78fd5673432038ac984450b9" + integrity sha512-UmFXIPU+9Eg3E9m/728Bii0lAIuoc+6nbrNUKaRPJOFp91ih44qqGlWtxMB6kXFrRD6po+86ksHM5XHCfk6iPw== + +xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/packages/instabug_flutter_modular/.metadata b/packages/instabug_flutter_modular/.metadata new file mode 100644 index 000000000..e5c802c48 --- /dev/null +++ b/packages/instabug_flutter_modular/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "367f9ea16bfae1ca451b9cc27c1366870b187ae2" + channel: "stable" + +project_type: package diff --git a/packages/instabug_flutter_modular/CHANGELOG.md b/packages/instabug_flutter_modular/CHANGELOG.md new file mode 100644 index 000000000..b968a85f9 --- /dev/null +++ b/packages/instabug_flutter_modular/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +## [v1.0.0](https://github.com/Instabug/instabug_flutter_modular/commits/v1.0.0/) (July 7, 2024) + +### Added + +- Add support for capturing screen loading time in Flutter Modular v5 ([#477](https://github.com/Instabug/Instabug-Flutter/pull/477)). diff --git a/packages/instabug_flutter_modular/LICENSE b/packages/instabug_flutter_modular/LICENSE new file mode 100644 index 000000000..80d729766 --- /dev/null +++ b/packages/instabug_flutter_modular/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Instabug + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/packages/instabug_flutter_modular/README.md b/packages/instabug_flutter_modular/README.md new file mode 100644 index 000000000..6e907fc90 --- /dev/null +++ b/packages/instabug_flutter_modular/README.md @@ -0,0 +1,55 @@ +# Instabug Flutter Modular + +[![Pub](https://img.shields.io/pub/v/instabug_flutter_modular.svg)](https://pub.dev/packages/instabug_flutter_modular) +[![Twitter](https://img.shields.io/badge/twitter-@Instabug-blue.svg)](https://twitter.com/Instabug) + +An add-on for the [Instabug Flutter SDK](https://github.com/Instabug/Instabug-Flutter) that provides screen loading support for [Flutter Modular](https://pub.dev/packages/flutter_modular) v5. + +## Installation + +1. Add `instabug_flutter_modular` to your `pubspec.yaml` file. + +```yaml +dependencies: + instabug_flutter_modular: +``` + +2. Install the package by running the following command. + +```sh +flutter pub get +``` + +## Usage + +1. Wrap your `AppParentModule` inside `InstabugModule`: + + +```dart + +void main() { + //... + + runApp( + ModularApp( + module: InstabugModule(AppModule()), + child: const MyApp(), + ), + ); +} +``` + +2. Add `InstabugNavigatorObserver` to your navigation observers list: + +```dart +@override +Widget build(BuildContext context) { + return MaterialApp.router( + routeInformationParser: Modular.routeInformationParser, + routerDelegate: Modular.routerDelegate + ..setObservers([InstabugNavigatorObserver()]), + + // ... + ); +} +``` \ No newline at end of file diff --git a/packages/instabug_flutter_modular/example/.gitignore b/packages/instabug_flutter_modular/example/.gitignore new file mode 100644 index 000000000..c2b055ffd --- /dev/null +++ b/packages/instabug_flutter_modular/example/.gitignore @@ -0,0 +1,44 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.metadata +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/packages/instabug_flutter_modular/example/android/.gitignore b/packages/instabug_flutter_modular/example/android/.gitignore new file mode 100644 index 000000000..6f568019d --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/packages/instabug_flutter_modular/example/android/app/build.gradle b/packages/instabug_flutter_modular/example/android/app/build.gradle new file mode 100644 index 000000000..b64cbfae0 --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/app/build.gradle @@ -0,0 +1,67 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + namespace "com.example.flutter_modular_demo_app" + compileSdk flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.flutter_modular_demo_app" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies {} diff --git a/packages/instabug_flutter_modular/example/android/app/src/debug/AndroidManifest.xml b/packages/instabug_flutter_modular/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..399f6981d --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/packages/instabug_flutter_modular/example/android/app/src/main/AndroidManifest.xml b/packages/instabug_flutter_modular/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..82cb28a05 --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/instabug_flutter_modular/example/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java b/packages/instabug_flutter_modular/example/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java new file mode 100644 index 000000000..752fc185d --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java @@ -0,0 +1,25 @@ +// Generated file. +// +// If you wish to remove Flutter's multidex support, delete this entire file. +// +// Modifications to this file should be done in a copy under a different name +// as this file may be regenerated. + +package io.flutter.app; + +import android.app.Application; +import android.content.Context; +import androidx.annotation.CallSuper; +import androidx.multidex.MultiDex; + +/** + * Extension of {@link android.app.Application}, adding multidex support. + */ +public class FlutterMultiDexApplication extends Application { + @Override + @CallSuper + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + MultiDex.install(this); + } +} diff --git a/packages/instabug_flutter_modular/example/android/app/src/main/kotlin/com/example/flutter_modular_demo_app/MainActivity.kt b/packages/instabug_flutter_modular/example/android/app/src/main/kotlin/com/example/flutter_modular_demo_app/MainActivity.kt new file mode 100644 index 000000000..79f585c2c --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/app/src/main/kotlin/com/example/flutter_modular_demo_app/MainActivity.kt @@ -0,0 +1,5 @@ +package com.example.flutter_modular_demo_app + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() diff --git a/packages/instabug_flutter_modular/example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/instabug_flutter_modular/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 000000000..f74085f3f --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/instabug_flutter_modular/example/android/app/src/main/res/drawable/launch_background.xml b/packages/instabug_flutter_modular/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000..304732f88 --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/instabug_flutter_modular/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/android/app/src/main/res/values-night/styles.xml b/packages/instabug_flutter_modular/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 000000000..06952be74 --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/instabug_flutter_modular/example/android/app/src/main/res/values/styles.xml b/packages/instabug_flutter_modular/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..cb1ef8805 --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/instabug_flutter_modular/example/android/app/src/main/res/xml/network_security_config.xml b/packages/instabug_flutter_modular/example/android/app/src/main/res/xml/network_security_config.xml new file mode 100644 index 000000000..9db612408 --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/app/src/main/res/xml/network_security_config.xml @@ -0,0 +1,12 @@ + + + + localhost + + + + + + + + diff --git a/packages/instabug_flutter_modular/example/android/app/src/profile/AndroidManifest.xml b/packages/instabug_flutter_modular/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000..399f6981d --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/packages/instabug_flutter_modular/example/android/build.gradle b/packages/instabug_flutter_modular/example/android/build.gradle new file mode 100644 index 000000000..bc157bd1a --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/build.gradle @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/packages/instabug_flutter_modular/example/android/gradle.properties b/packages/instabug_flutter_modular/example/android/gradle.properties new file mode 100644 index 000000000..73c3168eb --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/gradle.properties @@ -0,0 +1,6 @@ +org.gradle.jvmargs=-Xmx4G +android.useAndroidX=true +android.enableJetifier=true +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false diff --git a/packages/instabug_flutter_modular/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/instabug_flutter_modular/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..e1ca574ef --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip diff --git a/packages/instabug_flutter_modular/example/android/settings.gradle b/packages/instabug_flutter_modular/example/android/settings.gradle new file mode 100644 index 000000000..1d6d19b7f --- /dev/null +++ b/packages/instabug_flutter_modular/example/android/settings.gradle @@ -0,0 +1,26 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + } + settings.ext.flutterSdkPath = flutterSdkPath() + + includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.3.0" apply false + id "org.jetbrains.kotlin.android" version "1.7.10" apply false +} + +include ":app" diff --git a/packages/instabug_flutter_modular/example/ios/.gitignore b/packages/instabug_flutter_modular/example/ios/.gitignore new file mode 100644 index 000000000..7a7f9873a --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/packages/instabug_flutter_modular/example/ios/Flutter/AppFrameworkInfo.plist b/packages/instabug_flutter_modular/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000..7c5696400 --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/packages/instabug_flutter_modular/example/ios/Flutter/Debug.xcconfig b/packages/instabug_flutter_modular/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000..ec97fc6f3 --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/instabug_flutter_modular/example/ios/Flutter/Release.xcconfig b/packages/instabug_flutter_modular/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000..c4855bfe2 --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/instabug_flutter_modular/example/ios/Podfile b/packages/instabug_flutter_modular/example/ios/Podfile new file mode 100644 index 000000000..d97f17e22 --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Podfile @@ -0,0 +1,44 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '12.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/example/ios/Podfile.lock b/packages/instabug_flutter_modular/example/ios/Podfile.lock similarity index 100% rename from example/ios/Podfile.lock rename to packages/instabug_flutter_modular/example/ios/Podfile.lock diff --git a/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.pbxproj b/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..99206dfba --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,728 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 327E711B528735FED991BFC4 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2943C6CA26DB2D8358EBC2D7 /* Pods_Runner.framework */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 6D2169967115A81725A63418 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C96F9B3DD34FEEAF2EB522D /* Pods_RunnerTests.framework */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 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 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 22D0234AF76181345ADA0C95 /* 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 = ""; }; + 2943C6CA26DB2D8358EBC2D7 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 42617FCCD3CC7E9232CA19EF /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 4B1FAE53C830CB656B3306A8 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 7046D924EA334C9701656E63 /* 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 = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 849846FA37D5C84AC76BC5B8 /* 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 = ""; }; + 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 /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.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 = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9C96F9B3DD34FEEAF2EB522D /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9D23D5A15863072900ABD324 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8B88E0EF1C0B1FCD941F5841 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2169967115A81725A63418 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 327E711B528735FED991BFC4 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 25EC9C0EE1DF0FD1150948F4 /* Pods */ = { + isa = PBXGroup; + children = ( + 22D0234AF76181345ADA0C95 /* Pods-Runner.debug.xcconfig */, + 9D23D5A15863072900ABD324 /* Pods-Runner.release.xcconfig */, + 7046D924EA334C9701656E63 /* Pods-Runner.profile.xcconfig */, + 4B1FAE53C830CB656B3306A8 /* Pods-RunnerTests.debug.xcconfig */, + 849846FA37D5C84AC76BC5B8 /* Pods-RunnerTests.release.xcconfig */, + 42617FCCD3CC7E9232CA19EF /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 94671C5E18FAC8DD353CE05B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2943C6CA26DB2D8358EBC2D7 /* Pods_Runner.framework */, + 9C96F9B3DD34FEEAF2EB522D /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + 25EC9C0EE1DF0FD1150948F4 /* Pods */, + 94671C5E18FAC8DD353CE05B /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 354470C9D30A896FFCE8DEA0 /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + 8B88E0EF1C0B1FCD941F5841 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 48A7DA0DEA99D4A15D3FE66A /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + FB8A21F1FDFF0427C21277F5 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 354470C9D30A896FFCE8DEA0 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 48A7DA0DEA99D4A15D3FE66A /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + FB8A21F1FDFF0427C21277F5 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterModularDemoApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4B1FAE53C830CB656B3306A8 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterModularDemoApp.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 849846FA37D5C84AC76BC5B8 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterModularDemoApp.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 42617FCCD3CC7E9232CA19EF /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterModularDemoApp.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterModularDemoApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterModularDemoApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..8e3ca5dfe --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/instabug_flutter_modular/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/instabug_flutter_modular/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..21a3cc14c --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/packages/instabug_flutter_modular/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/instabug_flutter_modular/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/instabug_flutter_modular/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/instabug_flutter_modular/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/instabug_flutter_modular/example/ios/Runner/AppDelegate.swift b/packages/instabug_flutter_modular/example/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000..70693e4a8 --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..d36b1fab2 --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..797d452e458972bab9d994556c8305db4c827017 GIT binary patch literal 406 zcmV;H0crk;P))>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2d933e1120817fe9182483a228007b18ab6ae GIT binary patch literal 450 zcmV;z0X_bSP)iGWQ_5NJQ_~rNh*z)}eT%KUb z`7gNk0#AwF^#0T0?hIa^`~Ck;!}#m+_uT050aTR(J!bU#|IzRL%^UsMS#KsYnTF*!YeDOytlP4VhV?b} z%rz_<=#CPc)tU1MZTq~*2=8~iZ!lSa<{9b@2Jl;?IEV8)=fG217*|@)CCYgFze-x? zIFODUIA>nWKpE+bn~n7;-89sa>#DR>TSlqWk*!2hSN6D~Qb#VqbP~4Fk&m`@1$JGr zXPIdeRE&b2Thd#{MtDK$px*d3-Wx``>!oimf%|A-&-q*6KAH)e$3|6JV%HX{Hig)k suLT-RhftRq8b9;(V=235Wa|I=027H2wCDra;{X5v07*qoM6N<$f;9x^2LJ#7 literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..4cd7b0099ca80c806f8fe495613e8d6c69460d76 GIT binary patch literal 282 zcmV+#0p(^bcu7P-R4C8Q z&e;xxFbF_Vrezo%_kH*OKhshZ6BFpG-Y1e10`QXJKbND7AMQ&cMj60B5TNObaZxYybcN07*qoM6N<$g3m;S%K!iX literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe730945a01f64a61e2235dbe3f45b08f7729182 GIT binary patch literal 462 zcmV;<0WtoGP)-}iV`2<;=$?g5M=KQbZ{F&YRNy7Nn@%_*5{gvDM0aKI4?ESmw z{NnZg)A0R`+4?NF_RZexyVB&^^ZvN!{I28tr{Vje;QNTz`dG&Jz0~Ek&f2;*Z7>B|cg}xYpxEFY+0YrKLF;^Q+-HreN0P{&i zK~zY`?b7ECf-n?@;d<&orQ*Q7KoR%4|C>{W^h6@&01>0SKS`dn{Q}GT%Qj_{PLZ_& zs`MFI#j-(>?bvdZ!8^xTwlY{qA)T4QLbY@j(!YJ7aXJervHy6HaG_2SB`6CC{He}f zHVw(fJWApwPq!6VY7r1w-Fs)@ox~N+q|w~e;JI~C4Vf^@d>Wvj=fl`^u9x9wd9 zR%3*Q+)t%S!MU_`id^@&Y{y7-r98lZX0?YrHlfmwb?#}^1b{8g&KzmkE(L>Z&)179 zp<)v6Y}pRl100G2FL_t(o!|l{-Q-VMg#&MKg7c{O0 z2wJImOS3Gy*Z2Qifdv~JYOp;v+U)a|nLoc7hNH;I$;lzDt$}rkaFw1mYK5_0Q(Sut zvbEloxON7$+HSOgC9Z8ltuC&0OSF!-mXv5caV>#bc3@hBPX@I$58-z}(ZZE!t-aOG zpjNkbau@>yEzH(5Yj4kZiMH32XI!4~gVXNnjAvRx;Sdg^`>2DpUEwoMhTs_st8pKG z(%SHyHdU&v%f36~uERh!bd`!T2dw;z6PrOTQ7Vt*#9F2uHlUVnb#ev_o^fh}Dzmq} zWtlk35}k=?xj28uO|5>>$yXadTUE@@IPpgH`gJ~Ro4>jd1IF|(+IX>8M4Ps{PNvmI zNj4D+XgN83gPt_Gm}`Ybv{;+&yu-C(Grdiahmo~BjG-l&mWM+{e5M1sm&=xduwgM9 z`8OEh`=F3r`^E{n_;%9weN{cf2%7=VzC@cYj+lg>+3|D|_1C@{hcU(DyQG_BvBWe? zvTv``=%b1zrol#=R`JB)>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..502f463a9bc882b461c96aadf492d1729e49e725 GIT binary patch literal 586 zcmV-Q0=4~#P)+}#`wDE{8-2Mebf5<{{PqV{TgVcv*r8?UZ3{-|G?_}T*&y;@cqf{ z{Q*~+qr%%p!1pS*_Uicl#q9lc(D`!D`LN62sNwq{oYw(Wmhk)k<@f$!$@ng~_5)Ru z0Z)trIA5^j{DIW^c+vT2%lW+2<(RtE2wR;4O@)Tm`Xr*?A(qYoM}7i5Yxw>D(&6ou zxz!_Xr~yNF+waPe00049Nkl*;a!v6h%{rlvIH#gW3s8p;bFr=l}mRqpW2h zw=OA%hdyL~z+UHOzl0eKhEr$YYOL-c-%Y<)=j?(bzDweB7{b+%_ypvm_cG{SvM=DK zhv{K@m>#Bw>2W$eUI#iU)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G! zhkE!s;%oku3;IwG3U^2kw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn`0X*2 zy3(k600_CSZj?O$Qu%&$;|TGUJrptR(HzyIx>5E(2r{eA(<6t3e3I0B)7d6s7?Z5J zZ!rtKvA{MiEBm&KFtoifx>5P^Z=vl)95XJn()aS5%ad(s?4-=Tkis9IGu{`Fy8r+H07*qoM6N<$f20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec303439225b78712f49115768196d8d76f6790 GIT binary patch literal 862 zcmV-k1EKthP)20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f5fea27c705180eb716271f41b582e76dcbd90 GIT binary patch literal 1674 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 literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0467bf12aa4d28f374bb26596605a46dcbb3e7c8 GIT binary patch literal 1418 zcmV;51$Fv~P)q zKfU)WzW*n(@|xWGCA9ScMt*e9`2kdxPQ&&>|-UCa7_51w+ zLUsW@ZzZSW0y$)Hp~e9%PvP|a03ks1`~K?q{u;6NC8*{AOqIUq{CL&;p56Lf$oQGq z^={4hPQv)y=I|4n+?>7Fim=dxt1 z2H+Dm+1+fh+IF>G0SjJMkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJT zkdTm&kdTm&kdTm&kdP`esgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>Tmf` zm1{eLgw!b{bXkjWbF%dTkTZEJWyWOb##Lfw4EK2}<0d6%>AGS{po>WCOy&f$Tay_> z?NBlkpo@s-O;0V%Y_Xa-G#_O08q5LR*~F%&)}{}r&L%Sbs8AS4t7Y0NEx*{soY=0MZExqA5XHQkqi#4gW3 zqODM^iyZl;dvf)-bOXtOru(s)Uc7~BFx{w-FK;2{`VA?(g&@3z&bfLFyctOH!cVsF z7IL=fo-qBndRUm;kAdXR4e6>k-z|21AaN%ubeVrHl*<|s&Ax@W-t?LR(P-24A5=>a z*R9#QvjzF8n%@1Nw@?CG@6(%>+-0ASK~jEmCV|&a*7-GKT72W<(TbSjf)&Eme6nGE z>Gkj4Sq&2e+-G%|+NM8OOm5zVl9{Z8Dd8A5z3y8mZ=4Bv4%>as_{9cN#bm~;h>62( zdqY93Zy}v&c4n($Vv!UybR8ocs7#zbfX1IY-*w~)p}XyZ-SFC~4w>BvMVr`dFbelV{lLL0bx7@*ZZdebr3`sP;? zVImji)kG)(6Juv0lz@q`F!k1FE;CQ(D0iG$wchPbKZQELlsZ#~rt8#90Y_Xh&3U-< z{s<&cCV_1`^TD^ia9!*mQDq& zn2{r`j};V|uV%_wsP!zB?m%;FeaRe+X47K0e+KE!8C{gAWF8)lCd1u1%~|M!XNRvw zvtqy3iz0WSpWdhn6$hP8PaRBmp)q`#PCA`Vd#Tc$@f1tAcM>f_I@bC)hkI9|o(Iqv zo}Piadq!j76}004RBio<`)70k^`K1NK)q>w?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF z34$0Z;QO!JOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUC YUoZo%k(ykuW&i*H07*qoM6N<$f+CH{y8r+H literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 000000000..0bedcf2fd --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000..89c2725b7 --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/instabug_flutter_modular/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..f2e259c7c --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Base.lproj/Main.storyboard b/packages/instabug_flutter_modular/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000..f3c28516f --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Info.plist b/packages/instabug_flutter_modular/example/ios/Runner/Info.plist new file mode 100644 index 000000000..929983c33 --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Flutter Modular Demo App + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + flutter_modular_demo_app + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/packages/instabug_flutter_modular/example/ios/Runner/Runner-Bridging-Header.h b/packages/instabug_flutter_modular/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000..308a2a560 --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/packages/instabug_flutter_modular/example/ios/RunnerTests/RunnerTests.swift b/packages/instabug_flutter_modular/example/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 000000000..86a7c3b1b --- /dev/null +++ b/packages/instabug_flutter_modular/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/packages/instabug_flutter_modular/example/lib/main.dart b/packages/instabug_flutter_modular/example/lib/main.dart new file mode 100644 index 000000000..d2c1c6100 --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/main.dart @@ -0,0 +1,54 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_modular/flutter_modular.dart'; +import 'package:flutter_modular_demo_app/modules.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter_modular/instabug_flutter_modular.dart'; + +void main() { + runZonedGuarded( + () { + WidgetsFlutterBinding.ensureInitialized(); + + Instabug.init( + token: '6b41bc30dd42aac50794ef3ec8f74a74', + invocationEvents: [InvocationEvent.floatingButton], + debugLogsLevel: LogLevel.verbose, + ); + + FlutterError.onError = (FlutterErrorDetails details) { + Zone.current.handleUncaughtError(details.exception, details.stack!); + }; + runApp( + ModularApp( + module: InstabugModule(AppModule()), + child: const MyApp(), + ), + ); + }, + CrashReporting.reportCrash, + ); +} + +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + @override + Widget build(BuildContext context) { + return MaterialApp.router( + routeInformationParser: Modular.routeInformationParser, + routerDelegate: Modular.routerDelegate + ..setObservers([InstabugNavigatorObserver()]), + title: 'Flutter Modular Demo', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + ); + } +} diff --git a/packages/instabug_flutter_modular/example/lib/modules.dart b/packages/instabug_flutter_modular/example/lib/modules.dart new file mode 100644 index 000000000..f01d3d5f3 --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/modules.dart @@ -0,0 +1,9 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_modular/flutter_modular.dart'; +import 'package:flutter_modular_demo_app/screens.dart'; + +part 'modules/app_module.dart'; + +part 'modules/second_module.dart'; + +part 'modules/third_module.dart'; diff --git a/packages/instabug_flutter_modular/example/lib/modules/app_module.dart b/packages/instabug_flutter_modular/example/lib/modules/app_module.dart new file mode 100644 index 000000000..f68cf08b5 --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/modules/app_module.dart @@ -0,0 +1,20 @@ +part of '../modules.dart'; + +class AppModule extends Module { + @override + final List binds = [Bind.singleton((i) => Counter())]; + + @override + final List routes = [ + ChildRoute('/', child: (_, args) => const HomePage()), + ChildRoute('/simplePage', child: (_, args) => const SimplePage()), + ChildRoute('/complexPage', child: (_, args) => const ComplexPage()), + ChildRoute('/bindsPage', child: (_, args) => const ThirdModuleHomePage()), + WildcardRoute( + child: (p0, p1) => const NotFoundPage(), + ), + RedirectRoute('/redirect', to: '/simplePage?name=redirected'), + ModuleRoute('/secondModule', module: SecondModule()), + ModuleRoute('/thirdModule', module: ThirdModule()), + ]; +} diff --git a/packages/instabug_flutter_modular/example/lib/modules/second_module.dart b/packages/instabug_flutter_modular/example/lib/modules/second_module.dart new file mode 100644 index 000000000..b178f36be --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/modules/second_module.dart @@ -0,0 +1,31 @@ +part of '../modules.dart'; + +class SecondModule extends Module { + @override + final List binds = []; + + @override + List get routes => [ + ChildRoute( + '/', + child: (context, args) => const SecondModuleHomePage(), + children: [ + ChildRoute( + '/page1', + child: (context, args) => + const InternalPage(title: 'page 1', color: Colors.red), + ), + ChildRoute( + '/page2', + child: (context, args) => + const InternalPage(title: 'page 2', color: Colors.amber), + ), + ChildRoute( + '/page3', + child: (context, args) => + const InternalPage(title: 'page 3', color: Colors.green), + ), + ], + ), + ]; +} diff --git a/packages/instabug_flutter_modular/example/lib/modules/third_module.dart b/packages/instabug_flutter_modular/example/lib/modules/third_module.dart new file mode 100644 index 000000000..e14d83be0 --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/modules/third_module.dart @@ -0,0 +1,21 @@ +part of '../modules.dart'; + +class ThirdModule extends Module { + @override + final List binds = []; + + @override + final List routes = [ + ChildRoute('/', child: (_, args) => const ThirdModuleHomePage()), + ]; +} + +class Counter { + int _number = 0; + + int get number => _number; + + void increment() => _number++; + + void decrement() => _number--; +} diff --git a/packages/instabug_flutter_modular/example/lib/screens.dart b/packages/instabug_flutter_modular/example/lib/screens.dart new file mode 100644 index 000000000..a067eb93b --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/screens.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_modular/flutter_modular.dart'; +import 'package:flutter_modular_demo_app/modules.dart'; +import 'package:flutter_modular_demo_app/widgets.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; + +part 'screens/home_page.dart'; + +part 'screens/second_module_home_page.dart'; + +part 'screens/simple_page.dart'; + +part 'screens/third_module_home_page.dart'; + +part 'screens/not_found_page.dart'; + +part 'screens/complex_page.dart'; diff --git a/packages/instabug_flutter_modular/example/lib/screens/complex_page.dart b/packages/instabug_flutter_modular/example/lib/screens/complex_page.dart new file mode 100644 index 000000000..cac14c0d9 --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/screens/complex_page.dart @@ -0,0 +1,95 @@ +part of '../screens.dart'; + +class ComplexPage extends StatelessWidget { + const ComplexPage({super.key}); + + @override + Widget build(BuildContext context) { + int numberOfWidgets = 100; + return Scaffold( + floatingActionButton: FloatingActionButton( + onPressed: () {}, + child: const Icon(Icons.add), + ), + appBar: AppBar( + title: const Text("Complex Page"), + ), + body: SafeArea( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Padding( + padding: EdgeInsets.all(16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + CustomCard( + width: 40, + height: 40, + ), + SizedBox(width: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomCard( + height: 10, + width: 150, + ), + SizedBox(height: 8), + CustomCard( + height: 10, + width: 200, + ), + ], + ), + ], + ), + ), + SizedBox( + height: 80, + child: ListView.separated( + itemBuilder: (_, __) => const CustomCard( + width: 80, + ), + separatorBuilder: (_, __) => const SizedBox(width: 8), + itemCount: numberOfWidgets, + scrollDirection: Axis.horizontal, + ), + ), + const SizedBox(height: 16), + Expanded( + child: ListView.separated( + padding: const EdgeInsets.all(16), + itemBuilder: (_, __) => const CustomCard( + height: 100, + ), + separatorBuilder: (_, __) => const SizedBox(height: 8), + itemCount: numberOfWidgets, + ), + ), + ], + ), + ), + ); + } +} + +class CustomCard extends StatelessWidget { + const CustomCard({super.key, this.width, this.height}); + + final double? width, height; + + @override + Widget build(BuildContext context) { + return Container( + width: width, + height: height, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: Colors.black12, + ), + ); + } +} diff --git a/packages/instabug_flutter_modular/example/lib/screens/home_page.dart b/packages/instabug_flutter_modular/example/lib/screens/home_page.dart new file mode 100644 index 000000000..d6a29c195 --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/screens/home_page.dart @@ -0,0 +1,109 @@ +part of '../screens.dart'; +//ignore_for_file:invalid_use_of_internal_member + +class HomePage extends StatefulWidget { + const HomePage({super.key}); + + @override + State createState() => _HomePageState(); +} + +class _HomePageState extends State { + bool _instabug = true, _apm = true, _screenLoading = true, _uiTrace = true; + + @override + void didChangeDependencies() async { + super.didChangeDependencies(); + _instabug = await Instabug.isEnabled(); + _apm = await APM.isEnabled(); + _screenLoading = await APM.isScreenLoadingEnabled(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Home Page')), + body: SingleChildScrollView( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + CustomSwitchListTile( + value: _instabug, + onChanged: (value) { + Instabug.setEnabled(value); + setState(() => _instabug = value); + }, + title: "Instabug", + ), + CustomSwitchListTile( + value: _apm, + onChanged: (value) { + APM.setEnabled(value); + setState(() => _apm = value); + }, + title: "APM", + ), + CustomSwitchListTile( + value: _screenLoading, + onChanged: (value) { + APM.setScreenLoadingEnabled(value); + setState(() => _screenLoading = value); + }, + title: "Screen Loading", + ), + CustomSwitchListTile( + value: _uiTrace, + onChanged: (value) { + APM.setAutoUITraceEnabled(value); + setState(() => _uiTrace = value); + }, + title: "UI Trace", + ), + CustomButton( + onPressed: () => Modular.to.navigate('/simplePage'), + title: 'Navigate To Simple Page', + ), + CustomButton( + onPressed: () => Modular.to.pushNamed('/complexPage'), + title: 'Navigate To Complex Page', + ), + CustomButton( + onPressed: () => Modular.to.pushNamed('/simplePage'), + title: 'Navigate To Second Page (using push)', + ), + CustomButton( + onPressed: () => + Modular.to.navigate('/simplePage?name=Inastabug'), + title: 'Navigate To Second Page (with params)', + ), + CustomButton( + onPressed: () => Modular.to.navigate('/redirect'), + title: 'Navigate Using RedirectRoute', + ), + CustomButton( + onPressed: () => Modular.to.navigate('/bindsPage'), + title: 'Navigate To Binds Page', + ), + const SizedBox( + height: 32, + ), + CustomButton( + onPressed: () => Modular.to.navigate('/secondModule/'), + title: 'Navigate To Second Module (Nested Routes)', + ), + CustomButton( + onPressed: () => Modular.to.navigate('/thirdModule/'), + title: 'Navigate To Third Module (Binds)', + ), + CustomButton( + onPressed: () => Modular.to.navigate('/asde'), + title: 'Navigation History', + ), + ], + ), + ), + ); + } +} diff --git a/packages/instabug_flutter_modular/example/lib/screens/not_found_page.dart b/packages/instabug_flutter_modular/example/lib/screens/not_found_page.dart new file mode 100644 index 000000000..a17ee9176 --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/screens/not_found_page.dart @@ -0,0 +1,18 @@ +part of '../screens.dart'; + +class NotFoundPage extends StatelessWidget { + const NotFoundPage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Not Found Page')), + body: Center( + child: CustomButton( + onPressed: () => Modular.to.navigate('/'), + title: 'Back To Home', + ), + ), + ); + } +} diff --git a/packages/instabug_flutter_modular/example/lib/screens/second_module_home_page.dart b/packages/instabug_flutter_modular/example/lib/screens/second_module_home_page.dart new file mode 100644 index 000000000..7fe3c9454 --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/screens/second_module_home_page.dart @@ -0,0 +1,66 @@ +part of '../screens.dart'; + +class SecondModuleHomePage extends StatelessWidget { + const SecondModuleHomePage({super.key}); + + @override + Widget build(BuildContext context) { + final leading = SizedBox( + width: MediaQuery.of(context).size.width * 0.3, + child: NavigationListener( + builder: (context, child) => Column( + children: [ + ListTile( + title: const Text('Page 1'), + onTap: () => Modular.to.navigate('/secondModule/page1'), + selected: Modular.to.path.endsWith('/secondModule/page1'), + ), + ListTile( + title: const Text('Page 2'), + onTap: () => Modular.to.navigate('/secondModule/page2'), + selected: Modular.to.path.endsWith('/secondModule/page2'), + ), + ListTile( + title: const Text('Page 3'), + onTap: () => Modular.to.navigate('/secondModule/page3'), + selected: Modular.to.path.endsWith('/secondModule/page3'), + ), + const Spacer(), + ListTile( + title: const Text('Back To Home'), + onTap: () => Modular.to.navigate('/'), + ), + ], + ), + ), + ); + + return Scaffold( + appBar: AppBar(title: const Text('Second Module (Nested Routes)')), + body: SafeArea( + child: Row( + children: [ + leading, + Container(width: 1, color: Colors.black26), + const Expanded(child: RouterOutlet()), + ], + ), + ), + ); + } +} + +class InternalPage extends StatelessWidget { + final String title; + final Color color; + + const InternalPage({super.key, required this.title, required this.color}); + + @override + Widget build(BuildContext context) { + return Material( + color: color, + child: Center(child: Text(title)), + ); + } +} diff --git a/packages/instabug_flutter_modular/example/lib/screens/simple_page.dart b/packages/instabug_flutter_modular/example/lib/screens/simple_page.dart new file mode 100644 index 000000000..5d57e5510 --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/screens/simple_page.dart @@ -0,0 +1,58 @@ +part of '../screens.dart'; + +class SimplePage extends StatelessWidget { + const SimplePage({super.key}); + + @override + Widget build(BuildContext context) { + final canPop = Modular.to.canPop(); + const int extendedMicroseconds = 50000; + + return Scaffold( + appBar: AppBar(title: const Text('Second Page')), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (Modular.args.queryParams.containsKey("name")) ...[ + Text( + "Parameters: ${Modular.args.queryParams["name"]}", + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + ], + CustomButton( + onPressed: () => + _extendScreenLoading(context, extendedMicroseconds), + title: 'Extend SCL for $extendedMicroseconds μs', + ), + CustomButton( + onPressed: () { + if (canPop) { + Modular.to.pop(); + } else { + Modular.to.navigate('/'); + } + }, + title: 'Back to Home ${canPop ? "(pop)" : ""}', + ), + ], + ), + ), + ); + } + + void _extendScreenLoading(BuildContext context, int microseconds) { + ScaffoldMessenger.of(context) + .showSnackBar( + SnackBar( + content: Text("extend Screen for $microseconds microseconds"), + duration: Duration(microseconds: microseconds), + ), + ) + .closed + .then((value) => APM.endScreenLoading()); + } +} diff --git a/packages/instabug_flutter_modular/example/lib/screens/third_module_home_page.dart b/packages/instabug_flutter_modular/example/lib/screens/third_module_home_page.dart new file mode 100644 index 000000000..1f060b1a0 --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/screens/third_module_home_page.dart @@ -0,0 +1,50 @@ +part of '../screens.dart'; + +class ThirdModuleHomePage extends StatefulWidget { + const ThirdModuleHomePage({super.key}); + + @override + State createState() => _ThirdModuleHomePageState(); +} + +class _ThirdModuleHomePageState extends State { + final counter = Modular.get(); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Third Module (Binds)')), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + IconButton( + onPressed: () => setState(() => counter.increment()), + icon: const Icon(Icons.add_circle_outline_rounded)), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Text( + "Counter: ${counter.number}", + textAlign: TextAlign.center, + ), + ), + IconButton( + onPressed: () => setState(() => counter.decrement()), + icon: const Icon(Icons.remove_circle_outline_rounded)), + ], + ), + CustomButton( + onPressed: () => Modular.to.navigate('/'), + title: 'Back To Home', + ), + ], + ), + ), + ); + } +} diff --git a/packages/instabug_flutter_modular/example/lib/widgets.dart b/packages/instabug_flutter_modular/example/lib/widgets.dart new file mode 100644 index 000000000..37b85cc1f --- /dev/null +++ b/packages/instabug_flutter_modular/example/lib/widgets.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +class CustomSwitchListTile extends StatelessWidget { + const CustomSwitchListTile( + {super.key, required this.value, this.onChanged, required this.title}); + + final bool value; + final void Function(bool)? onChanged; + + final String title; + + @override + Widget build(BuildContext context) { + return SwitchListTile( + value: value, + onChanged: onChanged, + title: Text(title), + ); + } +} + +class CustomButton extends StatelessWidget { + const CustomButton({super.key, required this.onPressed, required this.title}); + + final VoidCallback onPressed; + final String title; + + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: onPressed, + child: Text( + title, + textAlign: TextAlign.center, + ), + ); + } +} diff --git a/packages/instabug_flutter_modular/example/pubspec.lock b/packages/instabug_flutter_modular/example/pubspec.lock new file mode 100644 index 000000000..d7b40e81b --- /dev/null +++ b/packages/instabug_flutter_modular/example/pubspec.lock @@ -0,0 +1,259 @@ +# 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: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + url: "https://pub.dev" + source: hosted + version: "1.19.0" + 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: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + flutter_modular: + dependency: transitive + description: + name: flutter_modular + sha256: "061f0bcc8f8c438d4c82f4ff70a9e61f109961c92b4e1eaf1bbfab75f577fe0e" + url: "https://pub.dev" + source: hosted + version: "5.0.3" + flutter_modular_annotations: + dependency: transitive + description: + name: flutter_modular_annotations + sha256: "65971655bdd30816a6a66651c801f4ceba6c8ba265f0866cc51ad038332c9a71" + url: "https://pub.dev" + source: hosted + version: "0.0.2" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + instabug_flutter: + dependency: "direct main" + description: + path: "../../instabug_flutter" + relative: true + source: path + version: "16.0.0" + instabug_flutter_modular: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "1.0.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + url: "https://pub.dev" + source: hosted + version: "10.0.7" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + url: "https://pub.dev" + source: hosted + version: "3.0.8" + 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: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 + url: "https://pub.dev" + source: hosted + version: "3.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" + modular_core: + dependency: transitive + description: + name: modular_core + sha256: "84cfe65d2ab15b0265a5bdb07a7a0408b06f8d92fee6fb94a3c85e97cbc2d6af" + url: "https://pub.dev" + source: hosted + version: "2.0.3+1" + modular_interfaces: + dependency: transitive + description: + name: modular_interfaces + sha256: "89db18038048d63de80871189ddc52363814e8181615459e5d88ed0a921acc1f" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + 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: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + 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: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + url: "https://pub.dev" + source: hosted + version: "1.3.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: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + url: "https://pub.dev" + source: hosted + version: "0.7.3" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + url: "https://pub.dev" + source: hosted + version: "14.3.0" +sdks: + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/packages/instabug_flutter_modular/example/pubspec.yaml b/packages/instabug_flutter_modular/example/pubspec.yaml new file mode 100644 index 000000000..90d6065c0 --- /dev/null +++ b/packages/instabug_flutter_modular/example/pubspec.yaml @@ -0,0 +1,93 @@ +name: flutter_modular_demo_app +description: "Flutter Modular Demo App" +# 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 + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: '>=3.3.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 + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.6 + instabug_flutter: ^13.2.0 + instabug_flutter_modular: + path: ../ + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^3.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/packages/instabug_flutter_modular/example/pubspec_overrides.yaml b/packages/instabug_flutter_modular/example/pubspec_overrides.yaml new file mode 100644 index 000000000..82c9b8e03 --- /dev/null +++ b/packages/instabug_flutter_modular/example/pubspec_overrides.yaml @@ -0,0 +1,6 @@ +# melos_managed_dependency_overrides: instabug_flutter,instabug_flutter_modular +dependency_overrides: + instabug_flutter: + path: ../../instabug_flutter + instabug_flutter_modular: + path: .. diff --git a/packages/instabug_flutter_modular/lib/instabug_flutter_modular.dart b/packages/instabug_flutter_modular/lib/instabug_flutter_modular.dart new file mode 100644 index 000000000..807259b68 --- /dev/null +++ b/packages/instabug_flutter_modular/lib/instabug_flutter_modular.dart @@ -0,0 +1 @@ +export 'src/instabug_module.dart'; diff --git a/packages/instabug_flutter_modular/lib/src/instabug_modular_manager.dart b/packages/instabug_flutter_modular/lib/src/instabug_modular_manager.dart new file mode 100644 index 000000000..d1f8c8ea7 --- /dev/null +++ b/packages/instabug_flutter_modular/lib/src/instabug_modular_manager.dart @@ -0,0 +1,76 @@ +import 'package:flutter_modular/flutter_modular.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter_modular/src/instabug_module.dart'; +import 'package:meta/meta.dart'; + +class InstabugModularManager { + InstabugModularManager._(); + + static InstabugModularManager _instance = InstabugModularManager._(); + static InstabugModularManager get instance => _instance; + + /// Shorthand for [instance] + static InstabugModularManager get I => instance; + + @visibleForTesting + // ignore: use_setters_to_change_properties + static void setInstance(InstabugModularManager instance) { + _instance = instance; + } + + List wrapRoutes( + List routes, { + String parent = '/', + bool wrapModules = true, + }) { + return routes + .map( + (route) => wrapRoute( + route, + parent: parent, + wrapModules: wrapModules, + ), + ) + .toList(); + } + + ModularRoute wrapRoute( + ModularRoute route, { + String parent = '/', + bool wrapModules = true, + }) { + final fullPath = (parent + route.name).replaceFirst('//', '/'); + + if (route is ModuleRoute && route.context is Module && wrapModules) { + final module = InstabugModule( + route.context! as Module, + path: fullPath, + ); + + return route.addModule( + route.name, + module: module, + ); + } else if (route is ParallelRoute && route is! ModuleRoute) { + ModularChild? child; + + if (route.child != null) { + child = (context, args) => InstabugCaptureScreenLoading( + screenName: fullPath, + child: route.child!(context, args), + ); + } + + return route.copyWith( + child: child, + children: wrapRoutes( + route.children, + parent: fullPath, + wrapModules: wrapModules, + ), + ); + } + + return route; + } +} diff --git a/packages/instabug_flutter_modular/lib/src/instabug_module.dart b/packages/instabug_flutter_modular/lib/src/instabug_module.dart new file mode 100644 index 000000000..dc56fb171 --- /dev/null +++ b/packages/instabug_flutter_modular/lib/src/instabug_module.dart @@ -0,0 +1,28 @@ +import 'package:flutter_modular/flutter_modular.dart'; +import 'package:instabug_flutter_modular/src/instabug_modular_manager.dart'; + +class InstabugModule extends Module { + final Module module; + final String path; + final List _routes; + + InstabugModule(this.module, {this.path = '/'}) + : _routes = InstabugModularManager.I.wrapRoutes( + module.routes, + parent: path, + ); + + @override + List get imports => module.imports; + + @override + List get binds => module.binds; + + @override + List get routes => _routes; + + // Override the runtime type to return the module's runtime type as Flutter + // Modular maps context bindings by their runtime type. + @override + Type get runtimeType => module.runtimeType; +} diff --git a/packages/instabug_flutter_modular/pubspec.lock b/packages/instabug_flutter_modular/pubspec.lock new file mode 100644 index 000000000..093917226 --- /dev/null +++ b/packages/instabug_flutter_modular/pubspec.lock @@ -0,0 +1,753 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" + url: "https://pub.dev" + source: hosted + version: "76.0.0" + _macros: + dependency: transitive + description: dart + source: sdk + version: "0.3.3" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" + url: "https://pub.dev" + source: hosted + version: "6.11.0" + args: + dependency: transitive + description: + name: args + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + url: "https://pub.dev" + source: hosted + version: "2.6.0" + 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" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" + url: "https://pub.dev" + source: hosted + version: "2.4.13" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 + url: "https://pub.dev" + source: hosted + version: "7.3.2" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + url: "https://pub.dev" + source: hosted + version: "8.9.2" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" + url: "https://pub.dev" + source: hosted + version: "4.10.1" + collection: + dependency: transitive + description: + name: collection + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + url: "https://pub.dev" + source: hosted + version: "1.19.0" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "4b03e11f6d5b8f6e5bb5e9f7889a56fe6c5cbe942da5378ea4d4d7f73ef9dfe5" + url: "https://pub.dev" + source: hosted + version: "1.11.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" + url: "https://pub.dev" + source: hosted + version: "2.3.7" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + url: "https://pub.dev" + source: hosted + version: "2.0.3" + flutter_modular: + dependency: "direct main" + description: + name: flutter_modular + sha256: "061f0bcc8f8c438d4c82f4ff70a9e61f109961c92b4e1eaf1bbfab75f577fe0e" + url: "https://pub.dev" + source: hosted + version: "5.0.3" + flutter_modular_annotations: + dependency: transitive + description: + name: flutter_modular_annotations + sha256: "65971655bdd30816a6a66651c801f4ceba6c8ba265f0866cc51ad038332c9a71" + url: "https://pub.dev" + source: hosted + version: "0.0.2" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + html: + dependency: transitive + description: + name: html + sha256: "1fc58edeaec4307368c60d59b7e15b9d658b57d7f3125098b6294153c75337ec" + url: "https://pub.dev" + source: hosted + version: "0.15.5" + http: + dependency: transitive + description: + name: http + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + url: "https://pub.dev" + source: hosted + version: "1.2.2" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + instabug_flutter: + dependency: "direct main" + description: + path: "../instabug_flutter" + relative: true + source: path + version: "16.0.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + url: "https://pub.dev" + source: hosted + version: "10.0.7" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + url: "https://pub.dev" + source: hosted + version: "3.0.8" + 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: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + macros: + dependency: transitive + description: + name: macros + sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656" + url: "https://pub.dev" + source: hosted + version: "0.1.3-main.0" + markdown: + dependency: transitive + description: + name: markdown + sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051 + url: "https://pub.dev" + source: hosted + version: "7.2.2" + 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: "direct main" + description: + name: meta + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + url: "https://pub.dev" + source: hosted + version: "1.15.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mockito: + dependency: "direct dev" + description: + name: mockito + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" + url: "https://pub.dev" + source: hosted + version: "5.4.4" + modular_core: + dependency: "direct dev" + description: + name: modular_core + sha256: "84cfe65d2ab15b0265a5bdb07a7a0408b06f8d92fee6fb94a3c85e97cbc2d6af" + url: "https://pub.dev" + source: hosted + version: "2.0.3+1" + modular_interfaces: + dependency: transitive + description: + name: modular_interfaces + sha256: "89db18038048d63de80871189ddc52363814e8181615459e5d88ed0a921acc1f" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + pana: + dependency: "direct dev" + description: + name: pana + sha256: "6f4372d5d2af5fe3fc6491c18f575601743bceb8433c7f179a6fffd162ee55f1" + url: "https://pub.dev" + source: hosted + version: "0.21.39" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + retry: + dependency: transitive + description: + name: retry + sha256: "822e118d5b3aafed083109c72d5f484c6dc66707885e07c0fbcb8b986bba7efc" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + safe_url_check: + dependency: transitive + description: + name: safe_url_check + sha256: "49a3e060a7869cbafc8f4845ca1ecbbaaa53179980a32f4fdfeab1607e90f41d" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" + source: hosted + version: "0.10.12" + 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: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + tar: + dependency: transitive + description: + name: tar + sha256: "22f67e2d77b51050436620b2a5de521c58ca6f0b75af1d9ab3c8cae2eae58fcd" + url: "https://pub.dev" + source: hosted + version: "1.0.5" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test: + dependency: transitive + description: + name: test + sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f" + url: "https://pub.dev" + source: hosted + version: "1.25.8" + test_api: + dependency: transitive + description: + name: test_api + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + url: "https://pub.dev" + source: hosted + version: "0.7.3" + test_core: + dependency: transitive + description: + name: test_core + sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d" + url: "https://pub.dev" + source: hosted + version: "0.6.5" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + url: "https://pub.dev" + source: hosted + version: "14.3.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" + url: "https://pub.dev" + source: hosted + version: "0.1.6" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/packages/instabug_flutter_modular/pubspec.yaml b/packages/instabug_flutter_modular/pubspec.yaml new file mode 100644 index 000000000..4015404b9 --- /dev/null +++ b/packages/instabug_flutter_modular/pubspec.yaml @@ -0,0 +1,27 @@ +name: instabug_flutter_modular +description: An add-on for the Instabug Flutter SDK that provides screen loading support for Flutter Modular v5. +version: 1.0.0 +homepage: https://www.instabug.com +repository: https://github.com/Instabug/Instabug-Flutter/tree/refactor/monorepo/packages/instabug_flutter_modular + +environment: + sdk: '>=3.1.2 <4.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + flutter_modular: '>=5.0.0 <6.0.0' + instabug_flutter: '>=13.2.0 <14.0.0' + meta: ^1.3.0 + +dev_dependencies: + build_runner: ^2.0.3 + flutter_lints: ^2.0.0 + flutter_test: + sdk: flutter + # mockito v5.2.0 is needed for running Flutter 2 tests on CI + mockito: '>=5.2.0 <=5.4.4' + # A specific version isn't specified as we want to use the version used in flutter_modular + modular_core: + pana: ^0.21.0 diff --git a/packages/instabug_flutter_modular/pubspec_overrides.yaml b/packages/instabug_flutter_modular/pubspec_overrides.yaml new file mode 100644 index 000000000..1f0beaf62 --- /dev/null +++ b/packages/instabug_flutter_modular/pubspec_overrides.yaml @@ -0,0 +1,4 @@ +# melos_managed_dependency_overrides: instabug_flutter +dependency_overrides: + instabug_flutter: + path: ../instabug_flutter diff --git a/packages/instabug_flutter_modular/release.sh b/packages/instabug_flutter_modular/release.sh new file mode 100755 index 000000000..b30831736 --- /dev/null +++ b/packages/instabug_flutter_modular/release.sh @@ -0,0 +1,13 @@ +#!/bin/sh +VERSION=$(egrep -o "version: ([0-9]-*.*)+[0-9]" pubspec.yaml | cut -d ":" -f 2) +if [ ! "${VERSION}" ] || [ -z "${VERSION}" ];then + echo "Instabug: err: Version Number not found." + exit 1 +else + mkdir -p $HOME/.config/dart + cat < $HOME/.config/dart/pub-credentials.json + ${PUB_CREDENTIALS} + +EOF + flutter packages pub publish -f +fi \ No newline at end of file diff --git a/packages/instabug_flutter_modular/test/src/instabug_modular_manager_test.dart b/packages/instabug_flutter_modular/test/src/instabug_modular_manager_test.dart new file mode 100644 index 000000000..85b4aa011 --- /dev/null +++ b/packages/instabug_flutter_modular/test/src/instabug_modular_manager_test.dart @@ -0,0 +1,201 @@ +// ignore_for_file: avoid_dynamic_calls + +import 'package:flutter/widgets.dart'; +import 'package:flutter_modular/flutter_modular.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter_modular/instabug_flutter_modular.dart'; +import 'package:instabug_flutter_modular/src/instabug_modular_manager.dart'; +import 'package:mockito/annotations.dart'; +import 'package:modular_core/modular_core.dart'; + +import 'instabug_modular_manager_test.mocks.dart'; + +@GenerateNiceMocks([ + MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), +]) +void main() { + late MockInstabugModule mockInstabugModule; + late MockModule mockModule; + late MockWidget mockWidget; + late MockBuildContext mockContext; + late MockModularArguments mockArgs; + + setUp(() { + mockInstabugModule = MockInstabugModule(); + mockModule = MockModule(); + mockWidget = MockWidget(); + mockContext = MockBuildContext(); + mockArgs = MockModularArguments(); + }); + + test('[wrapRoutes] with simple list', () { + // Arrange + final routes = [ + ChildRoute('/home', child: (_, __) => mockWidget), + ModuleRoute('/profile', module: mockModule), + ]; + + // Act + final wrappedRoutes = InstabugModularManager.instance.wrapRoutes(routes); + + // Assert + expect(wrappedRoutes.length, 2); + expect(wrappedRoutes[0].name, '/home'); + expect(wrappedRoutes[1].name, '/profile'); + }); + + test('[wrapRoutes] with nested route', () { + // Arrange + final routes = [ + ChildRoute( + '/users', + child: (_, __) => mockWidget, + children: [ + ModuleRoute('/list', module: mockModule), + ModuleRoute('/details', module: mockModule), + ], + ), + ]; + + // Act + final wrappedRoutes = InstabugModularManager.instance.wrapRoutes(routes); + + // Assert + expect(wrappedRoutes.length, 1); + expect(wrappedRoutes[0].name, '/users'); + expect(wrappedRoutes[0].children.length, 2); + expect(wrappedRoutes[0].children[0].name, '/list'); + expect(wrappedRoutes[0].children[1].name, '/details'); + }); + + test('[wrapRoute] with [ModuleRoute] should wrap with [InstabugModule]', () { + // Arrange + final route = ModuleRoute('/home', module: mockInstabugModule); + + // Act + final wrappedRoute = + InstabugModularManager.instance.wrapRoute(route) as dynamic; + + // Assert + expect(wrappedRoute.name, '/home'); + expect(wrappedRoute.context.module, isA()); + }); + + test( + '[wrapRoute] with [ParallelRoute] should wrap child with [InstabugCaptureScreenLoading]', + () { + // Arrange + final route = ChildRoute( + '/profile', + child: (context, args) => mockWidget, + ); + + // Act + final wrappedRoute = + InstabugModularManager.instance.wrapRoute(route) as dynamic; + + final widget = wrappedRoute.child(mockContext, mockArgs); + + // Assert + expect(wrappedRoute.name, '/profile'); + expect(widget, isA()); + }); + + test( + '[wrapRoutes] should wrap child property with [InstabugCaptureScreenLoading] and preserve the rest of its properties', + () { + // Arrange + final customTransition = MockCustomTransition(); + const duration = Duration.zero; + final guards = []; + const transition = TransitionType.downToUp; + + final homeRoute = ChildRoute( + '/home', + child: (context, args) => mockWidget, + customTransition: customTransition, + duration: duration, + guards: guards, + transition: transition, + ); + + final profileRoute = ChildRoute( + '/profile', + child: (context, args) => mockWidget, + customTransition: customTransition, + duration: duration, + guards: guards, + transition: transition, + ); + final routes = [homeRoute, profileRoute]; + + // Act + final wrappedRoutes = + InstabugModularManager.instance.wrapRoutes(routes) as List; + + for (final element in wrappedRoutes) { + final widget = element.child(mockContext, mockArgs); + + // Assert + expect(widget, isA()); + expect(element.customTransition, customTransition); + expect(element.duration, duration); + expect(element.transition, transition); + } + }); + + test('[wrapRoutes] with nested route', () { + // Arrange + final routes = [ + ChildRoute( + '/users', + child: (_, __) => mockWidget, + children: [ + ModuleRoute('/list', module: mockModule), + ModuleRoute('/details', module: mockModule), + ], + ), + ]; + + // Act + final wrappedRoutes = InstabugModularManager.instance.wrapRoutes(routes); + + // Assert + expect(wrappedRoutes.length, 1); + expect(wrappedRoutes[0].name, '/users'); + expect(wrappedRoutes[0].children.length, 2); + expect(wrappedRoutes[0].children[0].name, '/list'); + expect(wrappedRoutes[0].children[1].name, '/details'); + }); + + test('[wrapRoute] with custom parent path should add it to the path', () { + // Arrange + final route = ModuleRoute('/home', module: mockModule); + + // Act + final wrappedRoute = InstabugModularManager.instance + .wrapRoute(route, parent: '/users') as dynamic; + + // Assert + expect(wrappedRoute.context.path, '/users/home'); + }); + + test('[wrapRoute] with wrapModules set to false', () { + // Arrange + final route = ModuleRoute('/home', module: mockModule); + + // Act + final wrappedRoute = InstabugModularManager.instance + .wrapRoute(route, wrapModules: false) as dynamic; + + // Assert + expect(wrappedRoute.name, '/home'); + expect(wrappedRoute.context.module, isA()); + }); +} diff --git a/packages/instabug_http_client/CHANGELOG.md b/packages/instabug_http_client/CHANGELOG.md new file mode 100644 index 000000000..8abeafe73 --- /dev/null +++ b/packages/instabug_http_client/CHANGELOG.md @@ -0,0 +1,49 @@ +# Changelog + +## [2.6.0] (2025-07-17) + +### Added +- supports Instabug SDK above 3.0.0 ([#24](https://github.com/Instabug/Instabug-Dart-http-Adapter/pull/24)). + +## [2.5.1] - 22/04/2025 + +### Added + +- supports Dart versions above 3.0.0 ([#23](https://github.com/Instabug/Instabug-Dart-http-Adapter/pull/23)). + +## [2.5.0] - 18/11/2024 + +### Added + +- Add support for tracing network requests from Instabug to services like Datadog and New Relic ([#21](https://github.com/Instabug/Instabug-Dart-http-Adapter/pull/21)). + +## [2.4.0] - 7/05/2024 + +### Added + +- Add support for Instabug Flutter SDK v12 and v13 ([#17](https://github.com/Instabug/Instabug-Dart-http-Adapter/pull/17)). + +## [2.3.0] - 3/11/2022 + +- Adds support for MultipartRequest. + +## [2.2.1] - 2/8/2022 + +- Bumps [instabug_flutter](https://pub.dev/packages/instabug_flutter) to v11 + +## [2.2.0] - 11/4/2022 + +- Adds support for logging network requests using `send` method. + +## [2.1.0] - 5/1/2022 + +- Fixes network log compilation error. +- Adds payload size for network log. + +## [2.0.0] - 30/11/2021 + +- Upgrades to null safety. + +## [1.0.0] - 29/7/2019 + +- Adds implementation for the instabug_http_client library which supports Instabug network logging for the dart library: http. diff --git a/packages/instabug_http_client/LICENSE b/packages/instabug_http_client/LICENSE new file mode 100644 index 000000000..80d729766 --- /dev/null +++ b/packages/instabug_http_client/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Instabug + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/packages/instabug_http_client/README.md b/packages/instabug_http_client/README.md new file mode 100644 index 000000000..c367d4e8b --- /dev/null +++ b/packages/instabug_http_client/README.md @@ -0,0 +1,36 @@ +# instabug_http_client + +A dart package to support Instabug network logging for the external dart [http](https://pub.dev/packages/http) package. + +## Getting Started + +You can choose to attach all your network requests data to the Instabug reports being sent to the dashboard. See the details below on how to enable the feature for the `http` package. + +### Installation + +1. Add the dependency to your project `pubspec.yml`: + +```yaml +dependencies: + instabug_http_client: +``` + +2. Install the package by running the following command. + +```bash +flutter packages get +``` + +### Usage + +To enable logging, use the custom http client provided by Instabug: + +```dart +final client = InstabugHttpClient(); +``` + +Then proceed to use the package normally: + +```dart +final response = await client.get(Uri.parse(URL)); +``` diff --git a/packages/instabug_http_client/example/.metadata b/packages/instabug_http_client/example/.metadata new file mode 100644 index 000000000..5a023280a --- /dev/null +++ b/packages/instabug_http_client/example/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 7e9793dee1b85a243edd0e06cb1658e98b077561 + channel: stable + +project_type: app diff --git a/packages/instabug_http_client/example/README.md b/packages/instabug_http_client/example/README.md new file mode 100644 index 000000000..a13562602 --- /dev/null +++ b/packages/instabug_http_client/example/README.md @@ -0,0 +1,16 @@ +# example + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/example/analysis_options.yaml b/packages/instabug_http_client/example/analysis_options.yaml similarity index 93% rename from example/analysis_options.yaml rename to packages/instabug_http_client/example/analysis_options.yaml index 0d2902135..61b6c4de1 100644 --- a/example/analysis_options.yaml +++ b/packages/instabug_http_client/example/analysis_options.yaml @@ -13,7 +13,8 @@ linter: # The lint rules applied to this project can be customized in the # section below to disable rules from the `package:flutter_lints/flutter.yaml` # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. # # Instead of disabling a lint rule for the entire project in the # section below, it can also be suppressed for a single line of code diff --git a/packages/instabug_http_client/example/android/.gitignore b/packages/instabug_http_client/example/android/.gitignore new file mode 100644 index 000000000..6f568019d --- /dev/null +++ b/packages/instabug_http_client/example/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/packages/instabug_http_client/example/android/app/build.gradle b/packages/instabug_http_client/example/android/app/build.gradle new file mode 100644 index 000000000..86b077f53 --- /dev/null +++ b/packages/instabug_http_client/example/android/app/build.gradle @@ -0,0 +1,56 @@ +plugins { + id "com.android.application" + id "kotlin-android" + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id "dev.flutter.flutter-gradle-plugin" +} + +android { + namespace = "com.example.example" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8 + } + + defaultConfig { + applicationId "com.example.example" + minSdkVersion 21 + targetSdkVersion 34 + versionCode flutter.versionCode + versionName flutter.versionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + multiDexEnabled true + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.debug + } + } + namespace = "com.example.example" + + configurations.all { + resolutionStrategy.force 'org.hamcrest:hamcrest-core:1.3' + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.20" + implementation 'com.android.support:multidex:1.0.3' + implementation 'org.mockito:mockito-core:1.10.19' + testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:1.10.19' +} diff --git a/packages/instabug_http_client/example/android/app/src/debug/AndroidManifest.xml b/packages/instabug_http_client/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..f880684a6 --- /dev/null +++ b/packages/instabug_http_client/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/packages/instabug_http_client/example/android/app/src/main/AndroidManifest.xml b/packages/instabug_http_client/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..da82b5dba --- /dev/null +++ b/packages/instabug_http_client/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + diff --git a/packages/instabug_http_client/example/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java b/packages/instabug_http_client/example/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java new file mode 100644 index 000000000..9213f130f --- /dev/null +++ b/packages/instabug_http_client/example/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java @@ -0,0 +1,20 @@ +// Generated file. +// If you wish to remove Flutter's multidex support, delete this entire file. + +package io.flutter.app; + +import android.content.Context; +import androidx.annotation.CallSuper; +import androidx.multidex.MultiDex; + +/** + * Extension of {@link io.flutter.app.FlutterApplication}, adding multidex support. + */ +public class FlutterMultiDexApplication extends FlutterApplication { + @Override + @CallSuper + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + MultiDex.install(this); + } +} diff --git a/packages/instabug_http_client/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/packages/instabug_http_client/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt new file mode 100644 index 000000000..e793a000d --- /dev/null +++ b/packages/instabug_http_client/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/packages/instabug_http_client/example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/instabug_http_client/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 000000000..f74085f3f --- /dev/null +++ b/packages/instabug_http_client/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/instabug_http_client/example/android/app/src/main/res/drawable/launch_background.xml b/packages/instabug_http_client/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000..304732f88 --- /dev/null +++ b/packages/instabug_http_client/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/instabug_http_client/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/instabug_http_client/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/instabug_http_client/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/instabug_http_client/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/instabug_http_client/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/android/app/src/main/res/values-night/styles.xml b/packages/instabug_http_client/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 000000000..3db14bb53 --- /dev/null +++ b/packages/instabug_http_client/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/instabug_http_client/example/android/app/src/main/res/values/styles.xml b/packages/instabug_http_client/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..d460d1e92 --- /dev/null +++ b/packages/instabug_http_client/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/instabug_http_client/example/android/app/src/main/res/xml/network_security_config.xml b/packages/instabug_http_client/example/android/app/src/main/res/xml/network_security_config.xml new file mode 100644 index 000000000..be9989192 --- /dev/null +++ b/packages/instabug_http_client/example/android/app/src/main/res/xml/network_security_config.xml @@ -0,0 +1,13 @@ + + + + localhost + api.instabug.com + + + + + + + + diff --git a/packages/instabug_http_client/example/android/app/src/profile/AndroidManifest.xml b/packages/instabug_http_client/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000..f880684a6 --- /dev/null +++ b/packages/instabug_http_client/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/packages/instabug_http_client/example/android/build.gradle b/packages/instabug_http_client/example/android/build.gradle new file mode 100644 index 000000000..ed40a47e2 --- /dev/null +++ b/packages/instabug_http_client/example/android/build.gradle @@ -0,0 +1,15 @@ +rootProject.buildDir = '../build' + +//android { +// namespace 'com.instabug.flutter.example' +//} +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/packages/instabug_http_client/example/android/gradle.properties b/packages/instabug_http_client/example/android/gradle.properties new file mode 100644 index 000000000..b9a9a2464 --- /dev/null +++ b/packages/instabug_http_client/example/android/gradle.properties @@ -0,0 +1,6 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false diff --git a/packages/instabug_http_client/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/instabug_http_client/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..4cf0c849a --- /dev/null +++ b/packages/instabug_http_client/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip diff --git a/packages/instabug_http_client/example/android/settings.gradle b/packages/instabug_http_client/example/android/settings.gradle new file mode 100644 index 000000000..32cfc43dc --- /dev/null +++ b/packages/instabug_http_client/example/android/settings.gradle @@ -0,0 +1,27 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + maven { url 'https://storage.googleapis.com/flutter-plugins' } + + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.1.0" apply false + id "org.jetbrains.kotlin.android" version "1.8.22" apply false +} + +include ":app" diff --git a/packages/instabug_http_client/example/ios/.gitignore b/packages/instabug_http_client/example/ios/.gitignore new file mode 100644 index 000000000..7a7f9873a --- /dev/null +++ b/packages/instabug_http_client/example/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/packages/instabug_http_client/example/ios/Flutter/AppFrameworkInfo.plist b/packages/instabug_http_client/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000..7c5696400 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/packages/instabug_http_client/example/ios/Flutter/Debug.xcconfig b/packages/instabug_http_client/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000..ec97fc6f3 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/instabug_http_client/example/ios/Flutter/Release.xcconfig b/packages/instabug_http_client/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000..c4855bfe2 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/instabug_http_client/example/ios/Podfile b/packages/instabug_http_client/example/ios/Podfile new file mode 100644 index 000000000..ba26ef371 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '14.4' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/instabug_http_client/example/ios/Runner.xcodeproj/project.pbxproj b/packages/instabug_http_client/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..43b09ccb5 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,555 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 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 */; }; + AD44C4DB39F7C3968B8C56EB /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18B300F826F2074CB5E450C4 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 18B300F826F2074CB5E450C4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3E0436312822B722E186D653 /* 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 = ""; }; + 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 = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 90FF03378459C589A4D9DA6E /* 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 = ""; }; + 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 /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.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 = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DE25EB3DE5B281AB8980A728 /* 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 = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AD44C4DB39F7C3968B8C56EB /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3456E8E25F114A239880D241 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 18B300F826F2074CB5E450C4 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 4955E253C000584F8EA1A042 /* Pods */ = { + isa = PBXGroup; + children = ( + 90FF03378459C589A4D9DA6E /* Pods-Runner.debug.xcconfig */, + 3E0436312822B722E186D653 /* Pods-Runner.release.xcconfig */, + DE25EB3DE5B281AB8980A728 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 4955E253C000584F8EA1A042 /* Pods */, + 3456E8E25F114A239880D241 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + F412A5213E8CA6290AF8A003 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 9BDEDB79123E51897883C720 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + 9BDEDB79123E51897883C720 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F412A5213E8CA6290AF8A003 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = XNK224R4SF; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = XNK224R4SF; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = XNK224R4SF; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/packages/instabug_http_client/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/instabug_http_client/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/instabug_http_client/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/instabug_http_client/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/instabug_http_client/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/instabug_http_client/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/instabug_http_client/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/instabug_http_client/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..5e31d3d34 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/instabug_http_client/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/instabug_http_client/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..21a3cc14c --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/packages/instabug_http_client/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/instabug_http_client/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/instabug_http_client/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/instabug_http_client/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/instabug_http_client/example/ios/Runner/AppDelegate.swift b/packages/instabug_http_client/example/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000..b63630348 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@main +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..d36b1fab2 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 zcmds$`#;kQ7{|XelZftyR5~xW7?MLxS4^|Hw3&P7^y)@A9Fj{Xm1~_CIV^XZ%SLBn zA;!r`GqGHg=7>xrB{?psZQs88ZaedDoagm^KF{a*>G|dJWRSe^I$DNW008I^+;Kjt z>9p3GNR^I;v>5_`+91i(*G;u5|L+Bu6M=(afLjtkya#yZ175|z$pU~>2#^Z_pCZ7o z1c6UNcv2B3?; zX%qdxCXQpdKRz=#b*q0P%b&o)5ZrNZt7$fiETSK_VaY=mb4GK`#~0K#~9^ zcY!`#Af+4h?UMR-gMKOmpuYeN5P*RKF!(tb`)oe0j2BH1l?=>y#S5pMqkx6i{*=V9JF%>N8`ewGhRE(|WohnD59R^$_36{4>S zDFlPC5|k?;SPsDo87!B{6*7eqmMdU|QZ84>6)Kd9wNfh90=y=TFQay-0__>=<4pk& zYDjgIhL-jQ9o>z32K)BgAH+HxamL{ZL~ozu)Qqe@a`FpH=oQRA8=L-m-1dam(Ix2V z?du;LdMO+ooBelr^_y4{|44tmgH^2hSzPFd;U^!1p>6d|o)(-01z{i&Kj@)z-yfWQ)V#3Uo!_U}q3u`(fOs`_f^ueFii1xBNUB z6MecwJN$CqV&vhc+)b(p4NzGGEgwWNs z@*lUV6LaduZH)4_g!cE<2G6#+hJrWd5(|p1Z;YJ7ifVHv+n49btR}dq?HHDjl{m$T z!jLZcGkb&XS2OG~u%&R$(X+Z`CWec%QKt>NGYvd5g20)PU(dOn^7%@6kQb}C(%=vr z{?RP(z~C9DPnL{q^@pVw@|Vx~@3v!9dCaBtbh2EdtoNHm4kGxp>i#ct)7p|$QJs+U z-a3qtcPvhihub?wnJqEt>zC@)2suY?%-96cYCm$Q8R%-8$PZYsx3~QOLMDf(piXMm zB=<63yQk1AdOz#-qsEDX>>c)EES%$owHKue;?B3)8aRd}m~_)>SL3h2(9X;|+2#7X z+#2)NpD%qJvCQ0a-uzZLmz*ms+l*N}w)3LRQ*6>|Ub-fyptY(keUxw+)jfwF5K{L9 z|Cl_w=`!l_o><384d&?)$6Nh(GAm=4p_;{qVn#hI8lqewW7~wUlyBM-4Z|)cZr?Rh z=xZ&Ol>4(CU85ea(CZ^aO@2N18K>ftl8>2MqetAR53_JA>Fal`^)1Y--Am~UDa4th zKfCYpcXky$XSFDWBMIl(q=Mxj$iMBX=|j9P)^fDmF(5(5$|?Cx}DKEJa&XZP%OyE`*GvvYQ4PV&!g2|L^Q z?YG}tx;sY@GzMmsY`7r$P+F_YLz)(e}% zyakqFB<6|x9R#TdoP{R$>o7y(-`$$p0NxJ6?2B8tH)4^yF(WhqGZlM3=9Ibs$%U1w zWzcss*_c0=v_+^bfb`kBFsI`d;ElwiU%frgRB%qBjn@!0U2zZehBn|{%uNIKBA7n= zzE`nnwTP85{g;8AkYxA68>#muXa!G>xH22D1I*SiD~7C?7Za+9y7j1SHiuSkKK*^O zsZ==KO(Ua#?YUpXl{ViynyT#Hzk=}5X$e04O@fsMQjb}EMuPWFO0e&8(2N(29$@Vd zn1h8Yd>6z(*p^E{c(L0Lg=wVdupg!z@WG;E0k|4a%s7Up5C0c)55XVK*|x9RQeZ1J@1v9MX;>n34(i>=YE@Iur`0Vah(inE3VUFZNqf~tSz{1fz3Fsn_x4F>o(Yo;kpqvBe-sbwH(*Y zu$JOl0b83zu$JMvy<#oH^Wl>aWL*?aDwnS0iEAwC?DK@aT)GHRLhnz2WCvf3Ba;o=aY7 z2{Asu5MEjGOY4O#Ggz@@J;q*0`kd2n8I3BeNuMmYZf{}pg=jTdTCrIIYuW~luKecn z+E-pHY%ohj@uS0%^ z&(OxwPFPD$+#~`H?fMvi9geVLci(`K?Kj|w{rZ9JgthFHV+=6vMbK~0)Ea<&WY-NC zy-PnZft_k2tfeQ*SuC=nUj4H%SQ&Y$gbH4#2sT0cU0SdFs=*W*4hKGpuR1{)mV;Qf5pw4? zfiQgy0w3fC*w&Bj#{&=7033qFR*<*61B4f9K%CQvxEn&bsWJ{&winp;FP!KBj=(P6 z4Z_n4L7cS;ao2)ax?Tm|I1pH|uLpDSRVghkA_UtFFuZ0b2#>!8;>-_0ELjQSD-DRd z4im;599VHDZYtnWZGAB25W-e(2VrzEh|etsv2YoP#VbIZ{aFkwPrzJ#JvCvA*mXS& z`}Q^v9(W4GiSs}#s7BaN!WA2bniM$0J(#;MR>uIJ^uvgD3GS^%*ikdW6-!VFUU?JV zZc2)4cMsX@j z5HQ^e3BUzOdm}yC-xA%SY``k$rbfk z;CHqifhU*jfGM@DkYCecD9vl*qr58l6x<8URB=&%{!Cu3RO*MrKZ4VO}V6R0a zZw3Eg^0iKWM1dcTYZ0>N899=r6?+adUiBKPciJw}L$=1f4cs^bio&cr9baLF>6#BM z(F}EXe-`F=f_@`A7+Q&|QaZ??Txp_dB#lg!NH=t3$G8&06MFhwR=Iu*Im0s_b2B@| znW>X}sy~m#EW)&6E&!*0%}8UAS)wjt+A(io#wGI@Z2S+Ms1Cxl%YVE800007ip7{`C_J2TxPmfw%h$|%acrYHt)Re^PB%O&&=~a zhS(%I#+V>J-vjIib^<+s%ludY7y^C(P8nmqn9fp!i+?vr`bziDE=bx`%2W#Xyrj|i z!XQ4v1%L`m{7KT7q+LZNB^h8Ha2e=`Wp65^0;J00)_^G=au=8Yo;1b`CV&@#=jIBo zjN^JNVfYSs)+kDdGe7`1&8!?MQYKS?DuHZf3iogk_%#9E|5S zWeHrmAo>P;ejX7mwq#*}W25m^ZI+{(Z8fI?4jM_fffY0nok=+88^|*_DwcW>mR#e+ zX$F_KMdb6sRz!~7KkyN0G(3XQ+;z3X%PZ4gh;n-%62U<*VUKNv(D&Q->Na@Xb&u5Q3`3DGf+a8O5x7c#7+R+EAYl@R5us)CIw z7sT@_y~Ao@uL#&^LIh&QceqiT^+lb0YbFZt_SHOtWA%mgPEKVNvVgCsXy{5+zl*X8 zCJe)Q@y>wH^>l4;h1l^Y*9%-23TSmE>q5nI@?mt%n;Sj4Qq`Z+ib)a*a^cJc%E9^J zB;4s+K@rARbcBLT5P=@r;IVnBMKvT*)ew*R;&8vu%?Z&S>s?8?)3*YawM0P4!q$Kv zMmKh3lgE~&w&v%wVzH3Oe=jeNT=n@Y6J6TdHWTjXfX~-=1A1Bw`EW8rn}MqeI34nh zexFeA?&C3B2(E?0{drE@DA2pu(A#ElY&6el60Rn|Qpn-FkfQ8M93AfWIr)drgDFEU zghdWK)^71EWCP(@(=c4kfH1Y(4iugD4fve6;nSUpLT%!)MUHs1!zJYy4y||C+SwQ! z)KM&$7_tyM`sljP2fz6&Z;jxRn{Wup8IOUx8D4uh&(=O zx-7$a;U><*5L^!%xRlw)vAbh;sdlR||& ze}8_8%)c2Fwy=F&H|LM+p{pZB5DKTx>Y?F1N%BlZkXf!}JeGuMZk~LPi7{cidvUGB zAJ4LVeNV%XO>LTrklB#^-;8nb;}6l;1oW&WS=Mz*Az!4cqqQzbOSFq`$Q%PfD7srM zpKgP-D_0XPTRX*hAqeq0TDkJ;5HB1%$3Np)99#16c{ zJImlNL(npL!W|Gr_kxl1GVmF5&^$^YherS7+~q$p zt}{a=*RiD2Ikv6o=IM1kgc7zqpaZ;OB)P!1zz*i3{U()Dq#jG)egvK}@uFLa`oyWZ zf~=MV)|yJn`M^$N%ul5);JuQvaU1r2wt(}J_Qgyy`qWQI`hEeRX0uC@c1(dQ2}=U$ tNIIaX+dr)NRWXcxoR{>fqI{SF_dm1Ylv~=3YHI)h002ovPDHLkV1g(pWS;;4 literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 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 literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 zcmV-m2cP(fP)x~L`~4d)Rspd&<9kFh{hn*KP1LP0~$;u(LfAu zp%fx&qLBcRHx$G|3q(bv@+b;o0*D|jwD-Q9uQR(l*ST}s+uPgQ-MeFwZ#GS?b332? z&Tk$&_miXn3IGq)AmQ)3sisq{raD4(k*bHvpCe-TdWq^NRTEVM)i9xbgQ&ccnUVx* zEY%vS%gDcSg=!tuIK8$Th2_((_h^+7;R|G{n06&O2#6%LK`a}n?h_fL18btz<@lFG za}xS}u?#DBMB> zw^b($1Z)`9G?eP95EKi&$eOy@K%h;ryrR3la%;>|o*>CgB(s>dDcNOXg}CK9SPmD? zmr-s{0wRmxUnbDrYfRvnZ@d z6johZ2sMX{YkGSKWd}m|@V7`Degt-43=2M?+jR%8{(H$&MLLmS;-|JxnX2pnz;el1jsvqQz}pGSF<`mqEXRQ5sC4#BbwnB_4` zc5bFE-Gb#JV3tox9fp-vVEN{(tOCpRse`S+@)?%pz+zVJXSooTrNCUg`R6`hxwb{) zC@{O6MKY8tfZ5@!yy=p5Y|#+myRL=^{tc(6YgAnkg3I(Cd!r5l;|;l-MQ8B`;*SCE z{u)uP^C$lOPM z5d~UhKhRRmvv{LIa^|oavk1$QiEApSrP@~Jjbg`<*dW4TO?4qG%a%sTPUFz(QtW5( zM)lA+5)0TvH~aBaOAs|}?u2FO;yc-CZ1gNM1dAxJ?%m?YsGR`}-xk2*dxC}r5j$d* zE!#Vtbo69h>V4V`BL%_&$} z+oJAo@jQ^Tk`;%xw-4G>hhb&)B?##U+(6Fi7nno`C<|#PVA%$Y{}N-?(Gc$1%tr4Pc}}hm~yY#fTOe!@v9s-ik$dX~|ygArPhByaXn8 zpI^FUjNWMsTFKTP3X7m?UK)3m zp6rI^_zxRYrx6_QmhoWoDR`fp4R7gu6;gdO)!KexaoO2D88F9x#TM1(9Bn7g;|?|o z)~$n&Lh#hCP6_LOPD>a)NmhW})LADx2kq=X7}7wYRj-0?dXr&bHaRWCfSqvzFa=sn z-8^gSyn-RmH=BZ{AJZ~!8n5621GbUJV7Qvs%JNv&$%Q17s_X%s-41vAPfIR>;x0Wlqr5?09S>x#%Qkt>?(&XjFRY}*L6BeQ3 z<6XEBh^S7>AbwGm@XP{RkeEKj6@_o%oV?hDuUpUJ+r#JZO?!IUc;r0R?>mi)*ZpQ) z#((dn=A#i_&EQn|hd)N$#A*fjBFuiHcYvo?@y1 z5|fV=a^a~d!c-%ZbMNqkMKiSzM{Yq=7_c&1H!mXk60Uv32dV;vMg&-kQ)Q{+PFtwc zj|-uQ;b^gts??J*9VxxOro}W~Q9j4Em|zSRv)(WSO9$F$s=Ydu%Q+5DOid~lwk&we zY%W(Z@ofdwPHncEZzZgmqS|!gTj3wQq9rxQy+^eNYKr1mj&?tm@wkO*9@UtnRMG>c aR{jt9+;fr}hV%pg00001^@s67{VYS000c7NklQEG_j zup^)eW&WUIApqy$=APz8jE@awGp)!bsTjDbrJO`$x^ZR^dr;>)LW>{ zs70vpsD38v)19rI=GNk1b(0?Js9~rjsQsu*K;@SD40RB-3^gKU-MYC7G!Bw{fZsqp zih4iIi;Hr_xZ033Iu{sQxLS=}yBXgLMn40d++>aQ0#%8D1EbGZp7+ z5=mK?t31BkVYbGOxE9`i748x`YgCMwL$qMsChbSGSE1`p{nSmadR zcQ#R)(?!~dmtD0+D2!K zR9%!Xp1oOJzm(vbLvT^$IKp@+W2=-}qTzTgVtQ!#Y7Gxz}stUIm<1;oBQ^Sh2X{F4ibaOOx;5ZGSNK z0maF^@(UtV$=p6DXLgRURwF95C=|U8?osGhgOED*b z7woJ_PWXBD>V-NjQAm{~T%sjyJ{5tn2f{G%?J!KRSrrGvQ1(^`YLA5B!~eycY(e5_ z*%aa{at13SxC(=7JT7$IQF~R3sy`Nn%EMv!$-8ZEAryB*yB1k&stni)=)8-ODo41g zkJu~roIgAih94tb=YsL%iH5@^b~kU9M-=aqgXIrbtxMpFy5mekFm#edF9z7RQ6V}R zBIhbXs~pMzt0VWy1Fi$^fh+1xxLDoK09&5&MJl(q#THjPm(0=z2H2Yfm^a&E)V+a5 zbi>08u;bJsDRUKR9(INSc7XyuWv(JsD+BB*0hS)FO&l&7MdViuur@-<-EHw>kHRGY zqoT}3fDv2-m{NhBG8X}+rgOEZ;amh*DqN?jEfQdqxdj08`Sr=C-KmT)qU1 z+9Cl)a1mgXxhQiHVB}l`m;-RpmKy?0*|yl?FXvJkFxuu!fKlcmz$kN(a}i*saM3nr z0!;a~_%Xqy24IxA2rz<+08=B-Q|2PT)O4;EaxP^6qixOv7-cRh?*T?zZU`{nIM-at zTKYWr9rJ=tppQ9I#Z#mLgINVB!pO-^FOcvFw6NhV0gztuO?g ztoA*C-52Q-Z-P#xB4HAY3KQVd%dz1S4PA3vHp0aa=zAO?FCt zC_GaTyVBg2F!bBr3U@Zy2iJgIAt>1sf$JWA9kh{;L+P*HfUBX1Zy{4MgNbDfBV_ly z!y#+753arsZUt@366jIC0klaC@ckuk!qu=pAyf7&QmiBUT^L1&tOHzsK)4n|pmrVT zs2($4=?s~VejTFHbFdDOwG;_58LkIj1Fh@{glkO#F1>a==ymJS$z;gdedT1zPx4Kj ztjS`y_C}%af-RtpehdQDt3a<=W5C4$)9W@QAse;WUry$WYmr51ml9lkeunUrE`-3e zmq1SgSOPNEE-Mf+AGJ$g0M;3@w!$Ej;hMh=v=I+Lpz^n%Pg^MgwyqOkNyu2c^of)C z1~ALor3}}+RiF*K4+4{(1%1j3pif1>sv0r^mTZ?5Jd-It!tfPfiG_p$AY*Vfak%FG z4z#;wLtw&E&?}w+eKG^=#jF7HQzr8rV0mY<1YAJ_uGz~$E13p?F^fPSzXSn$8UcI$ z8er9{5w5iv0qf8%70zV71T1IBB1N}R5Kp%NO0=5wJalZt8;xYp;b{1K) zHY>2wW-`Sl{=NpR%iu3(u6l&)rc%%cSA#aV7WCowfbFR4wcc{LQZv~o1u_`}EJA3>ki`?9CKYTA!rhO)if*zRdd}Kn zEPfYbhoVE~!FI_2YbC5qAj1kq;xP6%J8+?2PAs?`V3}nyFVD#sV3+uP`pi}{$l9U^ zSz}_M9f7RgnnRhaoIJgT8us!1aB&4!*vYF07Hp&}L zCRlop0oK4DL@ISz{2_BPlezc;xj2|I z23RlDNpi9LgTG_#(w%cMaS)%N`e>~1&a3<{Xy}>?WbF>OOLuO+j&hc^YohQ$4F&ze z+hwnro1puQjnKm;vFG~o>`kCeUIlkA-2tI?WBKCFLMBY=J{hpSsQ=PDtU$=duS_hq zHpymHt^uuV1q@uc4bFb{MdG*|VoW@15Osrqt2@8ll0qO=j*uOXn{M0UJX#SUztui9FN4)K3{9!y8PC-AHHvpVTU;x|-7P+taAtyglk#rjlH2 z5Gq8ik}BPaGiM{#Woyg;*&N9R2{J0V+WGB69cEtH7F?U~Kbi6ksi*`CFXsi931q7Y zGO82?whBhN%w1iDetv%~wM*Y;E^)@Vl?VDj-f*RX>{;o_=$fU!&KAXbuadYZ46Zbg z&6jMF=49$uL^73y;;N5jaHYv)BTyfh&`qVLYn?`o6BCA_z-0niZz=qPG!vonK3MW_ zo$V96zM!+kJRs{P-5-rQVse0VBH*n6A58)4uc&gfHMa{gIhV2fGf{st>E8sKyP-$8zp~wJX^A*@DI&-;8>gANXZj zU)R+Y)PB?=)a|Kj>8NXEu^S_h^7R`~Q&7*Kn!xyvzVv&^>?^iu;S~R2e-2fJx-oUb cX)(b1KSk$MOV07*qoM6N<$f&6$jw%VRuvdN2+38CZWny1cRtlsl+0_KtW)EU14Ei(F!UtWuj4IK+3{sK@>rh zs1Z;=(DD&U6+tlyL?UnHVN^&g6QhFi2#HS+*qz;(>63G(`|jRtW|nz$Pv7qTovP!^ zP_jES{mr@O-02w%!^a?^1ZP!_KmQiz0L~jZ=W@Qt`8wzOoclQsAS<5YdH;a(4bGLE zk8s}1If(PSIgVi!XE!5kA?~z*sobvNyohr;=Q_@h2@$6Flyej3J)D-6YfheRGl`HEcPk|~huT_2-U?PfL=4BPV)f1o!%rQ!NMt_MYw-5bUSwQ9Z&zC>u zOrl~UJglJNa%f50Ok}?WB{on`Ci`p^Y!xBA?m@rcJXLxtrE0FhRF3d*ir>yzO|BD$ z3V}HpFcCh6bTzY}Nt_(W%QYd3NG)jJ4<`F<1Od) zfQblTdC&h2lCz`>y?>|9o2CdvC8qZeIZt%jN;B7Hdn2l*k4M4MFEtq`q_#5?}c$b$pf_3y{Y!cRDafZBEj-*OD|gz#PBDeu3QoueOesLzB+O zxjf2wvf6Wwz>@AiOo2mO4=TkAV+g~%_n&R;)l#!cBxjuoD$aS-`IIJv7cdX%2{WT7 zOm%5rs(wqyPE^k5SIpUZ!&Lq4<~%{*>_Hu$2|~Xa;iX*tz8~G6O3uFOS?+)tWtdi| zV2b#;zRN!m@H&jd=!$7YY6_}|=!IU@=SjvGDFtL;aCtw06U;-v^0%k0FOyESt z1Wv$={b_H&8FiRV?MrzoHWd>%v6KTRU;-v^Miiz+@q`(BoT!+<37CKhoKb)|8!+RG z6BQFU^@fRW;s8!mOf2QViKQGk0TVER6EG1`#;Nm39Do^PoT!+<37AD!%oJe86(=et zZ~|sLzU>V-qYiU6V8$0GmU7_K8|Fd0B?+9Un1BhKAz#V~Fk^`mJtlCX#{^8^M8!me z8Yg;8-~>!e<-iG;h*0B1kBKm}hItVGY6WnjVpgnTTAC$rqQ^v)4KvOtpY|sIj@WYg zyw##ZZ5AC2IKNC;^hwg9BPk0wLStlmBr;E|$5GoAo$&Ui_;S9WY62n3)i49|T%C#i017z3J=$RF|KyZWnci*@lW4 z=AKhNN6+m`Q!V3Ye68|8y@%=am>YD0nG99M)NWc20%)gwO!96j7muR}Fr&54SxKP2 zP30S~lt=a*qDlbu3+Av57=9v&vr<6g0&`!8E2fq>I|EJGKs}t|{h7+KT@)LfIV-3K zK)r_fr2?}FFyn*MYoLC>oV-J~eavL2ho4a4^r{E-8m2hi>~hA?_vIG4a*KT;2eyl1 zh_hUvUJpNCFwBvRq5BI*srSle>c6%n`#VNsyC|MGa{(P&08p=C9+WUw9Hl<1o9T4M zdD=_C0F7#o8A_bRR?sFNmU0R6tW`ElnF8p53IdHo#S9(JoZCz}fHwJ6F<&?qrpVqE zte|m%89JQD+XwaPU#%#lVs-@-OL);|MdfINd6!XwP2h(eyafTUsoRkA%&@fe?9m@jw-v(yTTiV2(*fthQH9}SqmsRPVnwwbV$1E(_lkmo&S zF-truCU914_$jpqjr(>Ha4HkM4YMT>m~NosUu&UZ>zirfHo%N6PPs9^_o$WqPA0#5 z%tG>qFCL+b*0s?sZ;Sht0nE7Kl>OVXy=gjWxxK;OJ3yGd7-pZf7JYNcZo2*1SF`u6 zHJyRRxGw9mDlOiXqVMsNe#WX`fC`vrtjSQ%KmLcl(lC>ZOQzG^%iql2w-f_K@r?OE zwCICifM#L-HJyc7Gm>Ern?+Sk3&|Khmu4(~3qa$(m6Ub^U0E5RHq49za|XklN#?kP zl;EstdW?(_4D>kwjWy2f!LM)y?F94kyU3`W!6+AyId-89v}sXJpuic^NLL7GJItl~ zsiuB98AI-(#Mnm|=A-R6&2fwJ0JVSY#Q>&3$zFh|@;#%0qeF=j5Ajq@4i0tIIW z&}sk$&fGwoJpe&u-JeGLi^r?dO`m=y(QO{@h zQqAC7$rvz&5+mo3IqE?h=a~6m>%r5Quapvzq;{y~p zJpyXOBgD9VrW7@#p6l7O?o3feml(DtSL>D^R) zZUY%T2b0-vBAFN7VB;M88!~HuOXi4KcI6aRQ&h|XQ0A?m%j2=l1f0cGP}h(oVfJ`N zz#PpmFC*ieab)zJK<4?^k=g%OjPnkANzbAbmGZHoVRk*mTfm75s_cWVa`l*f$B@xu z5E*?&@seIo#*Y~1rBm!7sF9~~u6Wrj5oICUOuz}CS)jdNIznfzCA(stJ(7$c^e5wN z?lt>eYgbA!kvAR7zYSD&*r1$b|(@;9dcZ^67R0 zXAXJKa|5Sdmj!g578Nwt6d$sXuc&MWezA0Whd`94$h{{?1IwXP4)Tx4obDK%xoFZ_Z zjjHJ_P@R_e5blG@yEjnaJb`l;s%Lb2&=8$&Ct-fV`E^4CUs)=jTk!I}2d&n!f@)bm z@ z_4Dc86+3l2*p|~;o-Sb~oXb_RuLmoifDU^&Te$*FevycC0*nE3Xws8gsWp|Rj2>SM zns)qcYj?^2sd8?N!_w~4v+f-HCF|a$TNZDoNl$I1Uq87euoNgKb6&r26TNrfkUa@o zfdiFA@p{K&mH3b8i!lcoz)V{n8Q@g(vR4ns4r6w;K z>1~ecQR0-<^J|Ndg5fvVUM9g;lbu-){#ghGw(fg>L zh)T5Ljb%lWE;V9L!;Cqk>AV1(rULYF07ZBJbGb9qbSoLAd;in9{)95YqX$J43-dY7YU*k~vrM25 zxh5_IqO0LYZW%oxQ5HOzmk4x{atE*vipUk}sh88$b2tn?!ujEHn`tQLe&vo}nMb&{ zio`xzZ&GG6&ZyN3jnaQy#iVqXE9VT(3tWY$n-)uWDQ|tc{`?fq2F`oQ{;d3aWPg4Hp-(iE{ry>MIPWL> iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000..89c2725b7 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/instabug_http_client/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/instabug_http_client/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..f2e259c7c --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/instabug_http_client/example/ios/Runner/Base.lproj/Main.storyboard b/packages/instabug_http_client/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000..f3c28516f --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/instabug_http_client/example/ios/Runner/Info.plist b/packages/instabug_http_client/example/ios/Runner/Info.plist new file mode 100644 index 000000000..7f553465b --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/packages/instabug_http_client/example/ios/Runner/Runner-Bridging-Header.h b/packages/instabug_http_client/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000..308a2a560 --- /dev/null +++ b/packages/instabug_http_client/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/packages/instabug_http_client/example/lib/main.dart b/packages/instabug_http_client/example/lib/main.dart new file mode 100644 index 000000000..da0018df8 --- /dev/null +++ b/packages/instabug_http_client/example/lib/main.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:instabug_http_client/instabug_http_client.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; + +Future main() async { + runApp(const MyApp()); + Instabug.init( + token: 'ed6f659591566da19b67857e1b9d40ab', + invocationEvents: [InvocationEvent.floatingButton]); + final client = InstabugHttpClient(); + await client.get(Uri.parse('https://google.com')); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({Key? key, required this.title}) : super(key: key); + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + int _counter = 0; + + void _incrementCounter() { + setState(() { + _counter++; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'You have pushed the button this many times:', + ), + Text( + '$_counter', + style: Theme.of(context).textTheme.headlineMedium, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: _incrementCounter, + tooltip: 'Increment', + child: const Icon(Icons.add), + ), + ); + } +} diff --git a/packages/instabug_http_client/example/pubspec.lock b/packages/instabug_http_client/example/pubspec.lock new file mode 100644 index 000000000..9939c4e7b --- /dev/null +++ b/packages/instabug_http_client/example/pubspec.lock @@ -0,0 +1,251 @@ +# 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: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + url: "https://pub.dev" + source: hosted + version: "1.19.0" + 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: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 + url: "https://pub.dev" + source: hosted + version: "1.0.4" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + http: + dependency: transitive + description: + name: http + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + url: "https://pub.dev" + source: hosted + version: "0.13.6" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + instabug_flutter: + dependency: "direct overridden" + description: + path: "../../instabug_flutter" + relative: true + source: path + version: "16.0.0" + instabug_http_client: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "2.6.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + url: "https://pub.dev" + source: hosted + version: "10.0.7" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + url: "https://pub.dev" + source: hosted + version: "3.0.8" + 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: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c + url: "https://pub.dev" + source: hosted + version: "1.0.1" + 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" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + 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: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + 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: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + url: "https://pub.dev" + source: hosted + version: "1.3.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: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + url: "https://pub.dev" + source: hosted + version: "0.7.3" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + url: "https://pub.dev" + source: hosted + version: "14.3.0" +sdks: + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/packages/instabug_http_client/example/pubspec.yaml b/packages/instabug_http_client/example/pubspec.yaml new file mode 100644 index 000000000..9add5fe45 --- /dev/null +++ b/packages/instabug_http_client/example/pubspec.yaml @@ -0,0 +1,24 @@ +name: http_client_example +description: Demonstrates how to use the instabug_http_client package. + +publish_to: "none" + +version: 1.0.0+1 + +environment: + sdk: ">=2.12.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + cupertino_icons: ^1.0.2 + instabug_http_client: + path: ../ + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^1.0.0 + +flutter: + uses-material-design: true diff --git a/packages/instabug_http_client/example/pubspec_overrides.yaml b/packages/instabug_http_client/example/pubspec_overrides.yaml new file mode 100644 index 000000000..3daf4fd14 --- /dev/null +++ b/packages/instabug_http_client/example/pubspec_overrides.yaml @@ -0,0 +1,6 @@ +# melos_managed_dependency_overrides: instabug_flutter,instabug_http_client +dependency_overrides: + instabug_flutter: + path: ../../instabug_flutter + instabug_http_client: + path: .. diff --git a/packages/instabug_http_client/lib/instabug_http_client.dart b/packages/instabug_http_client/lib/instabug_http_client.dart new file mode 100644 index 000000000..40529ae82 --- /dev/null +++ b/packages/instabug_http_client/lib/instabug_http_client.dart @@ -0,0 +1,177 @@ +// ignore_for_file: invalid_use_of_internal_member + +library instabug_http_client; + +import 'dart:convert'; + +// to maintain supported versions prior to Flutter 3.3 +// ignore: unnecessary_import +import 'dart:typed_data'; + +import 'package:http/http.dart' as http; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_http_client/instabug_http_logger.dart'; +import 'package:meta/meta.dart'; + +class InstabugHttpClient extends InstabugHttpLogger implements http.Client { + InstabugHttpClient() : client = http.Client() { + logger = this; + } + + final NetworkLogger _networklogger = NetworkLogger(); + @visibleForTesting + http.Client client; + + @visibleForTesting + late InstabugHttpLogger logger; + + @override + void close() => client.close(); + + @override + Future delete( + Uri url, { + Map? headers, + Object? body, + Encoding? encoding, + }) async { + final startTime = DateTime.now(); + final requestHeader = headers ?? {}; + final w3cHeader = await getW3cHeader(requestHeader, startTime); + return client + .delete(url, body: body, headers: requestHeader, encoding: encoding) + .then((http.Response response) { + logger.onLogger(response, startTime: startTime, w3CHeader: w3cHeader); + return response; + }); + } + + Future getW3cHeader( + Map requestHeader, + DateTime startTime, + ) async { + final w3cHeader = await _networklogger.getW3CHeader( + requestHeader, + startTime.millisecondsSinceEpoch, + ); + if (w3cHeader?.isW3cHeaderFound == false && + w3cHeader?.w3CGeneratedHeader != null) { + requestHeader['traceparent'] = w3cHeader!.w3CGeneratedHeader!; + } + return w3cHeader; + } + + @override + Future get(Uri url, {Map? headers}) async { + final startTime = DateTime.now(); + final requestHeader = headers ?? {}; + final w3cHeader = await getW3cHeader(requestHeader, startTime); + return client + .get(url, headers: requestHeader) + .then((http.Response response) { + logger.onLogger(response, startTime: startTime, w3CHeader: w3cHeader); + return response; + }); + } + + @override + Future head(Uri url, {Map? headers}) async { + final startTime = DateTime.now(); + final requestHeader = headers ?? {}; + final w3cHeader = await getW3cHeader(requestHeader, startTime); + return client + .head(url, headers: requestHeader) + .then((http.Response response) { + logger.onLogger(response, startTime: startTime, w3CHeader: w3cHeader); + return response; + }); + } + + @override + Future patch( + Uri url, { + Map? headers, + Object? body, + Encoding? encoding, + }) async { + final startTime = DateTime.now(); + final requestHeader = headers ?? {}; + final w3cHeader = await getW3cHeader(requestHeader, startTime); + return client + .patch(url, headers: requestHeader, body: body, encoding: encoding) + .then((http.Response response) { + logger.onLogger(response, startTime: startTime, w3CHeader: w3cHeader); + return response; + }); + } + + @override + Future post( + Uri url, { + Map? headers, + Object? body, + Encoding? encoding, + }) async { + final startTime = DateTime.now(); + final requestHeader = headers ?? {}; + final w3cHeader = await getW3cHeader(requestHeader, startTime); + return client + .post(url, headers: requestHeader, body: body, encoding: encoding) + .then((http.Response response) { + logger.onLogger(response, startTime: startTime, w3CHeader: w3cHeader); + return response; + }); + } + + @override + Future put( + Uri url, { + Map? headers, + Object? body, + Encoding? encoding, + }) async { + final startTime = DateTime.now(); + final requestHeader = headers ?? {}; + final w3cHeader = await getW3cHeader(requestHeader, startTime); + return client + .put(url, headers: requestHeader, body: body, encoding: encoding) + .then((http.Response response) { + logger.onLogger(response, startTime: startTime, w3CHeader: w3cHeader); + return response; + }); + } + + @override + Future read(Uri url, {Map? headers}) => + client.read(url, headers: headers); + + @override + Future readBytes(Uri url, {Map? headers}) => + client.readBytes(url, headers: headers); + + @override + Future send(http.BaseRequest request) async { + final startTime = DateTime.now(); + final requestHeader = request.headers; + final w3cHeader = await getW3cHeader(requestHeader, startTime); + return client.send(request).then( + (http.StreamedResponse streamedResponse) => + http.Response.fromStream(streamedResponse) + .then((http.Response response) { + logger.onLogger(response, + startTime: startTime, w3CHeader: w3cHeader); + // Need to return new StreamedResponse, as body only can be listened once + return http.StreamedResponse( + Stream>.value(response.bodyBytes), + response.statusCode, + contentLength: response.contentLength, + request: response.request, + headers: response.headers, + isRedirect: response.isRedirect, + persistentConnection: response.persistentConnection, + reasonPhrase: response.reasonPhrase, + ); + }), + ); + } +} diff --git a/packages/instabug_http_client/lib/instabug_http_logger.dart b/packages/instabug_http_client/lib/instabug_http_logger.dart new file mode 100644 index 000000000..fc97a831a --- /dev/null +++ b/packages/instabug_http_client/lib/instabug_http_logger.dart @@ -0,0 +1,76 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:instabug_flutter/instabug_flutter.dart'; + +class InstabugHttpLogger { + void onLogger( + http.Response response, { + DateTime? startTime, + W3CHeader? w3CHeader, + }) { + final networkLogger = NetworkLogger(); + + final requestHeaders = {}; + response.request?.headers.forEach((String header, dynamic value) { + requestHeaders[header] = value; + }); + + final request = response.request; + + if (request == null) { + return; + } + final requestBody = request is http.MultipartRequest + ? json.encode(request.fields) + : request is http.Request + ? request.body + : ''; + + final requestData = NetworkData( + startTime: startTime!, + method: request.method, + url: request.url.toString(), + requestHeaders: requestHeaders, + requestBody: requestBody, + w3cHeader: w3CHeader, + ); + + final endTime = DateTime.now(); + + final responseHeaders = {}; + response.headers.forEach((String header, dynamic value) { + responseHeaders[header] = value; + }); + var requestBodySize = 0; + if (requestHeaders.containsKey('content-length')) { + requestBodySize = int.parse(responseHeaders['content-length'] ?? '0'); + } else { + requestBodySize = requestBody.length; + } + + var responseBodySize = 0; + if (responseHeaders.containsKey('content-length')) { + responseBodySize = int.parse(responseHeaders['content-length'] ?? '0'); + } else { + responseBodySize = response.body.length; + } + + networkLogger.networkLog( + requestData.copyWith( + status: response.statusCode, + duration: endTime.difference(requestData.startTime).inMicroseconds, + responseContentType: response.headers.containsKey('content-type') + ? response.headers['content-type'] + : '', + responseHeaders: responseHeaders, + responseBody: response.body, + requestBodySize: requestBodySize, + responseBodySize: responseBodySize, + requestContentType: request.headers.containsKey('content-type') + ? request.headers['content-type'] + : '', + ), + ); + } +} diff --git a/packages/instabug_http_client/pubspec.lock b/packages/instabug_http_client/pubspec.lock new file mode 100644 index 000000000..deb0402b8 --- /dev/null +++ b/packages/instabug_http_client/pubspec.lock @@ -0,0 +1,620 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + url: "https://pub.dev" + source: hosted + version: "61.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 + url: "https://pub.dev" + source: hosted + version: "5.13.0" + args: + dependency: transitive + description: + name: args + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + url: "https://pub.dev" + source: hosted + version: "2.6.0" + 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" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" + url: "https://pub.dev" + source: hosted + version: "2.4.13" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 + url: "https://pub.dev" + source: hosted + version: "7.3.2" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + url: "https://pub.dev" + source: hosted + version: "8.9.2" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" + url: "https://pub.dev" + source: hosted + version: "4.10.1" + collection: + dependency: transitive + description: + name: collection + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + url: "https://pub.dev" + source: hosted + version: "1.19.0" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + html: + dependency: transitive + description: + name: html + sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" + url: "https://pub.dev" + source: hosted + version: "0.15.6" + http: + dependency: "direct main" + description: + name: http + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + url: "https://pub.dev" + source: hosted + version: "0.13.6" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + instabug_flutter: + dependency: "direct main" + description: + path: "../instabug_flutter" + relative: true + source: path + version: "16.0.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + url: "https://pub.dev" + source: hosted + version: "10.0.7" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + url: "https://pub.dev" + source: hosted + version: "3.0.8" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + markdown: + dependency: transitive + description: + name: markdown + sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" + url: "https://pub.dev" + source: hosted + version: "7.3.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: "direct main" + description: + name: meta + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + url: "https://pub.dev" + source: hosted + version: "1.15.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mockito: + dependency: "direct dev" + description: + name: mockito + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" + url: "https://pub.dev" + source: hosted + version: "5.4.4" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + pana: + dependency: "direct dev" + description: + name: pana + sha256: "098eecfb7f80aecfff2395f9de1f19e31e7dc9a190708b75a1e708e6c2993c36" + url: "https://pub.dev" + source: hosted + version: "0.21.32" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + retry: + dependency: transitive + description: + name: retry + sha256: "822e118d5b3aafed083109c72d5f484c6dc66707885e07c0fbcb8b986bba7efc" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + safe_url_check: + dependency: transitive + description: + name: safe_url_check + sha256: "49a3e060a7869cbafc8f4845ca1ecbbaaa53179980a32f4fdfeab1607e90f41d" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + 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: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + tar: + dependency: transitive + description: + name: tar + sha256: "85ffd53e277f2bac8afa2885e6b195e26937e9c402424c3d88d92fd920b56de9" + url: "https://pub.dev" + source: hosted + version: "0.5.6" + 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: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + url: "https://pub.dev" + source: hosted + version: "0.7.3" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + url: "https://pub.dev" + source: hosted + version: "14.3.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" + url: "https://pub.dev" + source: hosted + version: "0.1.6" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/packages/instabug_http_client/pubspec.yaml b/packages/instabug_http_client/pubspec.yaml new file mode 100644 index 000000000..af206431b --- /dev/null +++ b/packages/instabug_http_client/pubspec.yaml @@ -0,0 +1,29 @@ +name: instabug_http_client +description: + This package is an add on to instabug_flutter. It intercepts any requests performed + with http Package and sends them to the report that will be sent to the dashboard. +version: 2.6.0 +homepage: https://github.com/Instabug/Instabug-Flutter#readme +documentation: https://docs.instabug.com/docs/flutter-overview +repository: https://github.com/Instabug/Instabug-Flutter/tree/refactor/monorepo/packages/instabug_http_client + +environment: + sdk: '>=2.12.0 <4.0.0' + +dependencies: + flutter: + sdk: flutter + http: ">=0.13.0 <2.0.0" + instabug_flutter: ">=14.0.0 <15.0.0" + meta: ^1.3.0 + +dev_dependencies: + build_runner: ^2.1.1 + flutter_test: + sdk: flutter + mockito: ^5.0.10 + pana: ^0.21.0 +# For information on the generic Dart part of this file, see the +# following page: https://www.dartlang.org/tools/pub/pubspec + +# The following section is specific to Flutter. diff --git a/packages/instabug_http_client/pubspec_overrides.yaml b/packages/instabug_http_client/pubspec_overrides.yaml new file mode 100644 index 000000000..1f0beaf62 --- /dev/null +++ b/packages/instabug_http_client/pubspec_overrides.yaml @@ -0,0 +1,4 @@ +# melos_managed_dependency_overrides: instabug_flutter +dependency_overrides: + instabug_flutter: + path: ../instabug_flutter diff --git a/packages/instabug_http_client/release.sh b/packages/instabug_http_client/release.sh new file mode 100644 index 000000000..39212c393 --- /dev/null +++ b/packages/instabug_http_client/release.sh @@ -0,0 +1,13 @@ +#!/bin/sh +VERSION=$(egrep -o "version: ([0-9]-*.*)+[0-9]" pubspec.yaml | cut -d ":" -f 2) +if [ ! "${VERSION}" ] || [ -z "${VERSION}" ];then + echo "Instabug: err: Version Number not found." + exit 1 +else + mkdir -p .pub-cache + cat < $HOME/.pub-cache/credentials.json + ${PUB_CREDENTIALS} + +EOF + flutter packages pub publish -f +fi \ No newline at end of file diff --git a/packages/instabug_http_client/test/instabug_http_client_test.dart b/packages/instabug_http_client/test/instabug_http_client_test.dart new file mode 100644 index 000000000..73014020b --- /dev/null +++ b/packages/instabug_http_client/test/instabug_http_client_test.dart @@ -0,0 +1,207 @@ +import 'dart:convert'; +import 'dart:io'; +// to maintain supported versions prior to Flutter 3.3 +// ignore: unnecessary_import +import 'dart:typed_data'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:http/http.dart' as http; +import 'package:http/testing.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter/src/generated/instabug.api.g.dart'; +import 'package:instabug_http_client/instabug_http_client.dart'; +import 'package:instabug_http_client/instabug_http_logger.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'instabug_http_client_test.mocks.dart'; + +@GenerateMocks([ + InstabugHttpLogger, + InstabugHttpClient, + InstabugHostApi, +]) +Future main() async { + TestWidgetsFlutterBinding.ensureInitialized(); + final mHost = MockInstabugHostApi(); + + setUpAll(() { + Instabug.$setHostApi(mHost); + NetworkLogger.$setHostApi(mHost); + when(mHost.isW3CFeatureFlagsEnabled()).thenAnswer( + (_) => Future>.value({ + 'isW3cCaughtHeaderEnabled': true, + 'isW3cExternalGeneratedHeaderEnabled': false, + 'isW3cExternalTraceIDEnabled': true, + }), + ); + }); + + const fakeResponse = { + 'id': '123', + 'activationCode': '111111', + }; + late Uri url; + final mockedResponse = http.Response(json.encode(fakeResponse), 200); + + late InstabugHttpClient instabugHttpClient; + + setUp(() { + url = Uri.parse('http://www.instabug.com'); + instabugHttpClient = InstabugHttpClient(); + instabugHttpClient.client = MockInstabugHttpClient(); + instabugHttpClient.logger = MockInstabugHttpLogger(); + }); + + test('expect instabug http client GET to return response', () async { + when( + instabugHttpClient.client.get(url, headers: anyNamed('headers')), + ).thenAnswer((_) async => mockedResponse); + final result = await instabugHttpClient.get(url); + expect(result, isInstanceOf()); + expect(result, mockedResponse); + verify( + instabugHttpClient.logger + .onLogger(mockedResponse, startTime: anyNamed('startTime')), + ).called(1); + }); + + test('expect instabug http client HEAD to return response', () async { + when( + instabugHttpClient.client.head(url, headers: anyNamed('headers')), + ).thenAnswer((_) async => mockedResponse); + final result = await instabugHttpClient.head(url); + expect(result, isInstanceOf()); + expect(result, mockedResponse); + verify( + instabugHttpClient.logger + .onLogger(mockedResponse, startTime: anyNamed('startTime')), + ).called(1); + }); + + test('expect instabug http client DELETE to return response', () async { + when( + instabugHttpClient.client.delete(url, headers: anyNamed('headers')), + ).thenAnswer((_) async => mockedResponse); + final result = await instabugHttpClient.delete(url); + expect(result, isInstanceOf()); + expect(result, mockedResponse); + verify( + instabugHttpClient.logger + .onLogger(mockedResponse, startTime: anyNamed('startTime')), + ).called(1); + }); + + test('expect instabug http client PATCH to return response', () async { + when( + instabugHttpClient.client.patch(url, headers: anyNamed('headers')), + ).thenAnswer((_) async => mockedResponse); + final result = await instabugHttpClient.patch(url); + expect(result, isInstanceOf()); + expect(result, mockedResponse); + verify( + instabugHttpClient.logger + .onLogger(mockedResponse, startTime: anyNamed('startTime')), + ).called(1); + }); + + test('expect instabug http client POST to return response', () async { + when( + instabugHttpClient.client.post(url, headers: anyNamed('headers')), + ).thenAnswer((_) async => mockedResponse); + final result = await instabugHttpClient.post(url); + expect(result, isInstanceOf()); + expect(result, mockedResponse); + verify( + instabugHttpClient.logger + .onLogger(mockedResponse, startTime: anyNamed('startTime')), + ).called(1); + }); + + test('expect instabug http client PUT to return response', () async { + when( + instabugHttpClient.client.put(url, headers: anyNamed('headers')), + ).thenAnswer((_) async => mockedResponse); + final result = await instabugHttpClient.put(url); + expect(result, isInstanceOf()); + expect(result.body, mockedResponse.body); + verify( + instabugHttpClient.logger + .onLogger(mockedResponse, startTime: anyNamed('startTime')), + ).called(1); + }); + + test('expect instabug http client READ to return response', () async { + const response = 'Some response string'; + when( + instabugHttpClient.client.read(url, headers: anyNamed('headers')), + ).thenAnswer((_) async => response); + + final result = await instabugHttpClient.read(url); + expect(result, isInstanceOf()); + expect(result, response); + }); + + test('expect instabug http client READBYTES to return response', () async { + final response = Uint8List(3); + instabugHttpClient.client = + MockClient((_) async => http.Response.bytes(response, 200)); + + final result = await instabugHttpClient.readBytes(url); + expect(result, isInstanceOf()); + expect(result, response); + }); + + test('expect instabug http client SEND to return response', () async { + final response = http.StreamedResponse( + const Stream>.empty(), + 200, + contentLength: 0, + ); + final request = http.StreamedRequest('POST', url) + ..headers[HttpHeaders.contentTypeHeader] = + 'application/json; charset=utf-8' + ..headers[HttpHeaders.userAgentHeader] = 'Dart'; + when(instabugHttpClient.client.send(request)) + .thenAnswer((_) async => response); + final responseFuture = instabugHttpClient.send(request); + request + ..sink.add('{"hello": "world"}'.codeUnits) + ..sink.close(); + + final result = await responseFuture; + expect(result, isInstanceOf()); + expect(result.headers, response.headers); + expect(result.statusCode, response.statusCode); + expect(result.contentLength, response.contentLength); + expect(result.isRedirect, response.isRedirect); + expect(result.persistentConnection, response.persistentConnection); + expect(result.reasonPhrase, response.reasonPhrase); + expect(result.request, response.request); + expect( + await result.stream.bytesToString(), + await response.stream.bytesToString(), + ); + final logger = instabugHttpClient.logger as MockInstabugHttpLogger; + verify(logger.onLogger(any, startTime: anyNamed('startTime'))).called(1); + }); + + test('expect instabug http client CLOSE to be called', () async { + instabugHttpClient.close(); + + verify(instabugHttpClient.client.close()); + }); + + test('stress test for GET method', () async { + when( + instabugHttpClient.client.get(url, headers: anyNamed('headers')), + ).thenAnswer((_) async => mockedResponse); + for (var i = 0; i < 10000; i++) { + await instabugHttpClient.get(url); + } + verify( + instabugHttpClient.logger + .onLogger(mockedResponse, startTime: anyNamed('startTime')), + ).called(10000); + }); +} diff --git a/pubspec.yaml b/pubspec.yaml index 86884fb71..e31787f54 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,39 +1,11 @@ -name: instabug_flutter -version: 15.0.2 -description: >- - Instabug empowers mobile teams to monitor, prioritize, and debug - performance and stability issues throughout the app development lifecycle. -homepage: https://www.instabug.com/platforms/flutter -repository: https://github.com/Instabug/Instabug-Flutter -documentation: https://docs.instabug.com/docs/flutter-overview - -dependencies: - flutter: - sdk: flutter - meta: ^1.3.0 - stack_trace: ^1.10.0 +name: instabug_flutter_mono +publish_to: none +environment: + sdk: '>=2.19.4 <4.0.0' + flutter: ">=2.10.0" dev_dependencies: - build_runner: ^2.0.3 - fake_async: ">=1.2.0 <1.4.0" - flutter_test: - sdk: flutter - lint: ^1.0.0 - # mockito v5.2.0 is needed for running Flutter 2 tests on CI - mockito: ">=5.2.0 <5.5.0" - pana: ^0.21.0 - # pigeon v3.0.0 is needed for running Flutter 2 tests on CI - pigeon: ">=3.0.0 <=10.1.5" + lint: 2.0.0 + melos: ^6.2.0 -flutter: - plugin: - platforms: - android: - package: com.instabug.flutter - pluginClass: InstabugFlutterPlugin - ios: - pluginClass: InstabugFlutterPlugin -environment: - sdk: ">=2.14.0 <4.0.0" - flutter: ">=1.17.0" diff --git a/scripts/init.sh b/scripts/init.sh new file mode 100644 index 000000000..1191ca84f --- /dev/null +++ b/scripts/init.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +if [ -d "android" ]; then + rm -rf "android" + echo "Folder android and its contents removed" +fi + +if [ -d "ios" ]; then + rm -rf "ios" + echo "Folder ios and its contents removed" +fi + + +if [ -d "build" ]; then + rm -rf "build" + echo "Folder build and its contents removed" +fi + +if [ -d "lib" ]; then + rm -rf "lib" + echo "Folder lib and its contents removed" +fi + +if [ -d "test" ]; then + rm -rf "test" + echo "Folder test and its contents removed" +fi + +if [ -d "example" ]; then + rm -rf "example" + echo "Folder example and its contents removed" +fi + +if command -v melos &> /dev/null +then + echo "Melos found" +else + echo "Melos not found" + dart pub global activate melos && echo 'export PATH="$PATH:$HOME/.pub-cache/bin"' >> $BASH_ENV +fi + + +melos bootstrap +melos dart_bootstrap +melos pigeon --no-select +melos generate --no-select +melos pods --no-select diff --git a/scripts/move_coverage_files.sh b/scripts/move_coverage_files.sh new file mode 100644 index 000000000..5deea44e2 --- /dev/null +++ b/scripts/move_coverage_files.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Set source and target directories +TARGET_DIR="../../../coverage" + + + # Create the target directory if it doesn't exist + mkdir -p "$TARGET_DIR" + + mv "lcov.info" "$TARGET_DIR/lcov-${MELOS_PACKAGE_NAME}.info" + + echo "All files moved successfully." + From 7eab68c9e0a2342d7dda5758dea7ed7317a5468c Mon Sep 17 00:00:00 2001 From: ahmed alaa <154802748+ahmedAlaaInstabug@users.noreply.github.com> Date: Wed, 20 Aug 2025 20:02:05 +0300 Subject: [PATCH 2/2] bump iOS SDK to v16.0.2 --- packages/instabug_flutter/CHANGELOG.md | 4 ++-- packages/instabug_flutter/example/ios/Podfile.lock | 8 ++++---- packages/instabug_flutter/ios/instabug_flutter.podspec | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/instabug_flutter/CHANGELOG.md b/packages/instabug_flutter/CHANGELOG.md index d0798641c..d745fffd3 100644 --- a/packages/instabug_flutter/CHANGELOG.md +++ b/packages/instabug_flutter/CHANGELOG.md @@ -16,9 +16,9 @@ - **BREAKING** Remove deprecated APIs ([#614](https://github.com/Instabug/Instabug-Flutter/pull/614)). See migration guide for more details. -- Bump Instabug iOS SDK to v15.1.1 ([#620](https://github.com/Instabug/Instabug-Flutter/pull/620)). [See release notes](https://github.com/Instabug/Instabug-iOS/releases/tag/16.0.1). +- Bump Instabug iOS SDK to v16.0.2 ([#620](https://github.com/Instabug/Instabug-Flutter/pull/620)). [See release notes](https://github.com/Instabug/Instabug-iOS/releases/tag/16.0.1). -- Bump Instabug Android SDK to v15.0.2 ([#620](https://github.com/Instabug/Instabug-Flutter/pull/620)). [See release notes](https://github.com/Instabug/Instabug-Android/releases/tag/v16.0.0). +- Bump Instabug Android SDK to v16.0.0 ([#620](https://github.com/Instabug/Instabug-Flutter/pull/620)). [See release notes](https://github.com/Instabug/Instabug-Android/releases/tag/v16.0.0). ## [15.0.2](https://github.com/Instabug/Instabug-Flutter/compare/v14.3.0...15.0.2) (Jul 7, 2025) diff --git a/packages/instabug_flutter/example/ios/Podfile.lock b/packages/instabug_flutter/example/ios/Podfile.lock index ad3bc6f81..fa6ff6432 100644 --- a/packages/instabug_flutter/example/ios/Podfile.lock +++ b/packages/instabug_flutter/example/ios/Podfile.lock @@ -1,9 +1,9 @@ PODS: - Flutter (1.0.0) - - Instabug (16.0.1) + - Instabug (16.0.2) - instabug_flutter (16.0.0): - Flutter - - Instabug (= 16.0.1) + - Instabug (= 16.0.2) - OCMock (3.6) - video_player_avfoundation (0.0.1): - Flutter @@ -30,8 +30,8 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - Instabug: f31a27e70cb6580aef656d1abf8c57a5bb5633d0 - instabug_flutter: 30131c9ec54d3a7a44ff74ac7ad51e3562813374 + Instabug: 125f729dea4e4a43e815ae06f9db0332e2a5fd60 + instabug_flutter: 156a51054e7e5dc9378fac1a8f6867b26968bfee OCMock: 5ea90566be239f179ba766fd9fbae5885040b992 video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b diff --git a/packages/instabug_flutter/ios/instabug_flutter.podspec b/packages/instabug_flutter/ios/instabug_flutter.podspec index 02608b997..1478297af 100644 --- a/packages/instabug_flutter/ios/instabug_flutter.podspec +++ b/packages/instabug_flutter/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', '16.0.1' + s.dependency 'Instabug', '16.0.2' end