diff --git a/README.md b/README.md index 9f4199d..1fd7afa 100644 --- a/README.md +++ b/README.md @@ -88,11 +88,85 @@ The showcase is where everything begins. Let's see the available options : * `bubbleShowcaseId` The showcase identifier. Must be unique across the app as it is used as a saving mean; for instance when the showcase should not be reopened (**required**). * `bubbleShowcaseVersion` The showcase version. Increase it when you update the showcase, this allows to redisplay the it to the user if `doNotReopenOnClose` is set to `true` (**required**). -* `doNotReopenOnClose` Whether this showcase should be reopened once closed. +* `doNotReopenOnClose` Whether this showcase should be reopened once closed. (default to `false`) * `bubbleSlides` The slides to display (**required** & **must not be empty**). * `child` The widget to display below the slides. It should be your app main widget. -* `counterText` The current slide counter text. `:i` targets the current slide number and `:n` targets the maximum slide number. -* `showCloseButton` Whether to show a little close button on the top left of the slide. +* `counterText` The current slide counter text. `:i` targets the current slide number and `:n` targets the maximum slide number. You can pass `null` to disable this. +* `showCloseButton` Whether to show a little close button on the top left of the slide. (default to `true`) +* `enabledClickOnOverlayToNextSlide` Whether to enable click on overlay to go to next slide. (default to `true`) +* `slideNumberStream` Trigger this to go to targeted slide. It is invoked by `Stream`. If receiving input is over length of slides or less, the showcase is finished. While providing position number less than -1, the showcase will stand still. +* `slideActionStream` Trigger this to control slide to go `next`, back to `previous` or `close`. You can use StreamController to control slide like this example: + +```dart +final StreamController slideActionConroller = StreamController(); + +BubbleShowcase( + bubbleShowcaseId: 'my_bubble_showcase', + bubbleShowcaseVersion: 2, + bubbleSlides: [ + AbsoluteBubbleSlide( + positionCalculator: (size) => Position( + top: 0, + right: 0, + bottom: 0, + left: 0, + ), + child: AbsoluteBubbleSlideChild( + positionCalculator: (size) => Position( + top: 0, + left: 0, + ), + widget: SpeechBubble( + nipLocation: NipLocation.LEFT, + color: Colors.blue, + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + children: [ + Text( + 'This is the top left corner of your app.', + style: TextStyle(color: Colors.white), + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: () => slideActionConroller + .add(SlideControllerAction.previous), + child: Text('previous'), + ), + Container( + margin: EdgeInsets.only(left: 16.0), + child: RaisedButton( + child: Text('Next'), + onPressed: () { + slideActionConroller + .add(SlideControllerAction.next); + }, + ), + ), + Container( + margin: EdgeInsets.only(left: 16.0), + child: RaisedButton( + child: Text('Done'), + onPressed: () { + slideActionConroller + .add(SlideControllerAction.close); + }, + ), + ) + ], + ), + ], + ), + ), + ), + ), + ), + ], + child: MyMainWidget(), +); +``` ### The slides @@ -118,7 +192,7 @@ The same positioning system is also available for children : | Position | Class name | Use case | Specific options | |----------|----------------------------|---------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------| | Absolute | `AbsoluteBubbleSlideChild` | You want to position the child according to a _x_, _y_ position on the screen and not the highlighted part of the screen. | `positionCalculator` The function that calculates the child position on the screen. | -| Relative | `RelativeBubbleSlideChild` | You want to position the child according to the highlighted zone. | `direction` Where to position the child compared to the highlighted zone. | +| Relative | `RelativeBubbleSlideChild` | You want to position the child according to the highlighted zone. | | All children have these options in common : diff --git a/example/.gitignore b/example/.gitignore index 07488ba..9d532b1 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -15,56 +15,27 @@ *.iws .idea/ -# Visual Studio Code related -.vscode/ +# 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 .packages .pub-cache/ .pub/ /build/ -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java +# Web related +lib/generated_plugin_registrant.dart -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* +# Symbolication related +app.*.symbols -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +# Obfuscation related +app.*.map.json diff --git a/example/.metadata b/example/.metadata index 07763f7..24544cb 100644 --- a/example/.metadata +++ b/example/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: 8661d8aecd626f7f57ccbcb735553edc05a2e713 + revision: 84f3d28555368a70270e9ac8390a9441df95e752 channel: stable project_type: app diff --git a/example/android/.gitignore b/example/android/.gitignore new file mode 100644 index 0000000..0a741cb --- /dev/null +++ b/example/android/.gitignore @@ -0,0 +1,11 @@ +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 diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index b9991ed..c55e72b 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -22,10 +22,15 @@ if (flutterVersionName == null) { } apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 28 + compileSdkVersion 29 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } lintOptions { disable 'InvalidPackage' @@ -34,11 +39,10 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "fr.skyost.bubble_showcase_example" - minSdkVersion 18 - targetSdkVersion 28 + minSdkVersion 16 + targetSdkVersion 29 versionCode flutterVersionCode.toInteger() versionName flutterVersionName - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { @@ -55,7 +59,5 @@ flutter { } dependencies { - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 7af231f..fdaa27c 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> + + + + diff --git a/example/android/app/src/main/java/fr/skyost/bubble_showcase_example/MainActivity.java b/example/android/app/src/main/java/fr/skyost/bubble_showcase_example/MainActivity.java deleted file mode 100644 index 4af9827..0000000 --- a/example/android/app/src/main/java/fr/skyost/bubble_showcase_example/MainActivity.java +++ /dev/null @@ -1,13 +0,0 @@ -package fr.skyost.bubble_showcase_example; - -import android.os.Bundle; -import io.flutter.app.FlutterActivity; -import io.flutter.plugins.GeneratedPluginRegistrant; - -public class MainActivity extends FlutterActivity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - GeneratedPluginRegistrant.registerWith(this); - } -} diff --git a/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt new file mode 100644 index 0000000..e793a00 --- /dev/null +++ b/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/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml index 00fa441..1f83a33 100644 --- a/example/android/app/src/main/res/values/styles.xml +++ b/example/android/app/src/main/res/values/styles.xml @@ -1,8 +1,18 @@ + + + diff --git a/example/android/build.gradle b/example/android/build.gradle index bb8a303..3100ad2 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,11 +1,13 @@ buildscript { + ext.kotlin_version = '1.3.50' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.5.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 7be3d8b..a673820 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,2 +1,4 @@ org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true android.enableR8=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 2819f02..296b146 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle index 5a2f14f..44e62bc 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -1,15 +1,11 @@ include ':app' -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/example/ios/.gitignore b/example/ios/.gitignore new file mode 100644 index 0000000..e96ef60 --- /dev/null +++ b/example/ios/.gitignore @@ -0,0 +1,32 @@ +*.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/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/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 9367d48..f2872cf 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - en + $(DEVELOPMENT_LANGUAGE) CFBundleExecutable App CFBundleIdentifier @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 8.0 + 9.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index d077b08..1e8c3c9 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -10,60 +10,32 @@ project 'Runner', { 'Release' => :release, } -def parse_KV_file(file, separator='=') - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return []; +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 - pods_ary = [] - skip_line_start_symbols = ["#", "/"] - File.foreach(file_abs_path) { |line| - next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } - plugin = line.split(pattern=separator) - if plugin.length == 2 - podname = plugin[0].strip() - path = plugin[1].strip() - podpath = File.expand_path("#{path}", file_abs_path) - pods_ary.push({:name => podname, :path => podpath}); - else - puts "Invalid plugin specification: #{line}" - end - } - return pods_ary + + 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 -target 'Runner' do - # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock - # referring to absolute paths on developers' machines. - system('rm -rf .symlinks') - system('mkdir -p .symlinks/plugins') +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - # Flutter Pods - generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') - if generated_xcode_build_settings.empty? - puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." - end - generated_xcode_build_settings.map { |p| - if p[:name] == 'FLUTTER_FRAMEWORK_DIR' - symlink = File.join('.symlinks', 'flutter') - File.symlink(File.dirname(p[:path]), symlink) - pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) - end - } +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! - # Plugin Pods - plugin_pods = parse_KV_file('../.flutter-plugins') - plugin_pods.map { |p| - symlink = File.join('.symlinks', 'plugins', p[:name]) - File.symlink(p[:path], symlink) - pod p[:name], :path => File.join(symlink, 'ios') - } + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end post_install do |installer| installer.pods_project.targets.each do |target| - target.build_configurations.each do |config| - config.build_settings['ENABLE_BITCODE'] = 'NO' - end + flutter_additional_ios_build_settings(target) end end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock new file mode 100644 index 0000000..a1fa05b --- /dev/null +++ b/example/ios/Podfile.lock @@ -0,0 +1,28 @@ +PODS: + - Flutter (1.0.0) + - shared_preferences (0.0.1): + - Flutter + - speech_bubble (0.0.1): + - Flutter + +DEPENDENCIES: + - Flutter (from `Flutter`) + - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) + - speech_bubble (from `.symlinks/plugins/speech_bubble/ios`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + shared_preferences: + :path: ".symlinks/plugins/shared_preferences/ios" + speech_bubble: + :path: ".symlinks/plugins/speech_bubble/ios" + +SPEC CHECKSUMS: + Flutter: 0e3d915762c693b495b44d77113d4970485de6ec + shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d + speech_bubble: 51ae0c27684a0d858d4283cafd66591337a851c2 + +PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c + +COCOAPODS: 1.9.3 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index e8c3b08..1bdca59 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -9,17 +9,11 @@ /* 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 */; }; - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; - 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; - 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; + 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 */; }; - CCF2252C4E88D4B9A2033EEF /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A8414E9C5B17F5A7B6C9CD3 /* libPods-Runner.a */; }; + F27CCBD7AF9646A2C12BA5FE /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E5AAB05ADA916FC056516E6 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -29,8 +23,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -38,19 +30,19 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0EEF965935D007618B48D82D /* 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 = ""; }; 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 = ""; }; - 3A8414E9C5B17F5A7B6C9CD3 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 4F277DBC5E97EFC665C342BF /* 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 = ""; }; + 5E5AAB05ADA916FC056516E6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6F13FF4B80F03E20142662B8 /* 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 = ""; }; + 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 = ""; }; - 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; 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 = ""; }; - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 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 = ""; }; @@ -62,36 +54,36 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, - CCF2252C4E88D4B9A2033EEF /* libPods-Runner.a in Frameworks */, + F27CCBD7AF9646A2C12BA5FE /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 16DB172CD2C2F940E4E9B55E /* Frameworks */ = { + 4BD01D78C30E295404D7BEDA /* Frameworks */ = { isa = PBXGroup; children = ( - 3A8414E9C5B17F5A7B6C9CD3 /* libPods-Runner.a */, + 5E5AAB05ADA916FC056516E6 /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; }; - 2A0E2AAF6BCEE2E725E65DE4 /* Pods */ = { + 8B1E6A9D1FBC70FEADC54815 /* Pods */ = { isa = PBXGroup; children = ( + 6F13FF4B80F03E20142662B8 /* Pods-Runner.debug.xcconfig */, + 4F277DBC5E97EFC665C342BF /* Pods-Runner.release.xcconfig */, + 0EEF965935D007618B48D82D /* Pods-Runner.profile.xcconfig */, ); name = Pods; + path = Pods; sourceTree = ""; }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( - 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, @@ -105,8 +97,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - 2A0E2AAF6BCEE2E725E65DE4 /* Pods */, - 16DB172CD2C2F940E4E9B55E /* Frameworks */, + 8B1E6A9D1FBC70FEADC54815 /* Pods */, + 4BD01D78C30E295404D7BEDA /* Frameworks */, ); sourceTree = ""; }; @@ -121,27 +113,18 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( - 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, - 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 97C147021CF9000F007C117D /* Info.plist */, - 97C146F11CF9000F007C117D /* Supporting Files */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, ); path = Runner; sourceTree = ""; }; - 97C146F11CF9000F007C117D /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 97C146F21CF9000F007C117D /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -149,14 +132,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - A72865157EB89044E71FEDA4 /* [CP] Check Pods Manifest.lock */, + 8C14159839D2F81466EB83E0 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 51CCF9BD1FAC17E9EC62F607 /* [CP] Embed Pods Frameworks */, + 3CCB5D031FE99DC4996071A1 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -173,17 +156,18 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0910; - ORGANIZATIONNAME = "The Chromium Authors"; + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; }; }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -206,7 +190,6 @@ files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); @@ -227,65 +210,65 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 51CCF9BD1FAC17E9EC62F607 /* [CP] Embed Pods Frameworks */ = { + 3CCB5D031FE99DC4996071A1 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../Flutter/Flutter.framework", + "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", + "${BUILT_PRODUCTS_DIR}/speech_bubble/speech_bubble.framework", ); name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - ); outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/speech_bubble.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + 8C14159839D2F81466EB83E0 /* [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 = ( ); - name = "Run Script"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + 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; }; - A72865157EB89044E71FEDA4 /* [CP] Check Pods Manifest.lock */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "Run Script"; 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; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; /* End PBXShellScriptBuildPhase section */ @@ -294,8 +277,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, - 97C146F31CF9000F007C117D /* main.m in Sources */, + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -324,7 +306,6 @@ /* Begin XCBuildConfiguration section */ 249021D3217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -336,12 +317,14 @@ 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; @@ -362,9 +345,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -375,8 +359,8 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = S8QB4VV633; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -388,15 +372,16 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = fr.skyost.rateMyAppExample; + 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; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -408,12 +393,14 @@ 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; @@ -440,7 +427,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -450,7 +437,6 @@ }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -462,12 +448,14 @@ 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; @@ -488,9 +476,11 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -501,6 +491,7 @@ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -513,8 +504,11 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = fr.skyost.rateMyAppExample; + 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; @@ -524,6 +518,7 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -536,8 +531,10 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = fr.skyost.rateMyAppExample; + 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; diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/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/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 786d6aa..a28140c 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ @@ -46,7 +45,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings index 949b678..f9b0d7c 100644 --- a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -2,7 +2,7 @@ - BuildSystemType - Original + PreviewsEnabled + diff --git a/example/ios/Runner/AppDelegate.h b/example/ios/Runner/AppDelegate.h deleted file mode 100644 index 36e21bb..0000000 --- a/example/ios/Runner/AppDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import -#import - -@interface AppDelegate : FlutterAppDelegate - -@end diff --git a/example/ios/Runner/AppDelegate.m b/example/ios/Runner/AppDelegate.m deleted file mode 100644 index 59a72e9..0000000 --- a/example/ios/Runner/AppDelegate.m +++ /dev/null @@ -1,13 +0,0 @@ -#include "AppDelegate.h" -#include "GeneratedPluginRegistrant.h" - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application - didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [GeneratedPluginRegistrant registerWithRegistry:self]; - // Override point for customization after application launch. - return [super application:application didFinishLaunchingWithOptions:launchOptions]; -} - -@end diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/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/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index 3d43d11..dc9ada4 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index 7b91cbf..fa183b3 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - en + $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -41,9 +41,5 @@ UIViewControllerBasedStatusBarAppearance - LSApplicationQueriesSchemes - - itms - diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/example/ios/Runner/main.m b/example/ios/Runner/main.m deleted file mode 100644 index dff6597..0000000 --- a/example/ios/Runner/main.m +++ /dev/null @@ -1,9 +0,0 @@ -#import -#import -#import "AppDelegate.h" - -int main(int argc, char* argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/example/lib/main.dart b/example/lib/main.dart index 9437d54..1f781f2 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'package:bubble_showcase/bubble_showcase.dart'; import 'package:flutter/material.dart'; import 'package:speech_bubble/speech_bubble.dart'; @@ -19,7 +20,6 @@ class _BubbleShowcaseDemoApp extends StatelessWidget { ); } -/// The main demo widget. class _BubbleShowcaseDemoWidget extends StatelessWidget { /// The title text global key. final GlobalKey _titleKey = GlobalKey(); @@ -27,9 +27,13 @@ class _BubbleShowcaseDemoWidget extends StatelessWidget { /// The first button global key. final GlobalKey _firstButtonKey = GlobalKey(); + final StreamController slideNumberConroller = StreamController(); + final StreamController slideActionConroller = + StreamController(); + @override Widget build(BuildContext context) { - TextStyle textStyle = Theme.of(context).textTheme.body1.copyWith( + TextStyle textStyle = Theme.of(context).textTheme.bodyText1.copyWith( color: Colors.white, ); return BubbleShowcase( @@ -40,7 +44,12 @@ class _BubbleShowcaseDemoWidget extends StatelessWidget { _secondSlide(textStyle), _thirdSlide(textStyle), ], + slideNumberStream: slideNumberConroller.stream, + slideActionStream: slideActionConroller.stream, child: _BubbleShowcaseDemoChild(_titleKey, _firstButtonKey), + counterText: null, + showCloseButton: false, + enabledClickOnOverlayToNextSlide: false, ); } @@ -55,20 +64,48 @@ class _BubbleShowcaseDemoWidget extends StatelessWidget { color: Colors.blue, child: Padding( padding: const EdgeInsets.all(10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, + child: Stack( children: [ - Text( - 'That\'s cool !', - style: textStyle.copyWith( - fontSize: 18, - fontWeight: FontWeight.bold, - ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'That\'s cool !', + style: textStyle.copyWith( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + Text( + 'This is my brand new title !', + style: textStyle, + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: () => slideNumberConroller.add(4), + child: Text('skip'), + ), + Container( + margin: EdgeInsets.only(left: 16.0), + child: RaisedButton( + child: Text('Next'), + onPressed: () { + slideNumberConroller.add(1); + }, + ), + ), + ], + ), + ], ), - Text( - 'This is my brand new title !', - style: textStyle, + Positioned.fill( + child: Align( + alignment: Alignment.topRight, + child: Text('1/3'), + ), ), ], ), @@ -94,9 +131,35 @@ class _BubbleShowcaseDemoWidget extends StatelessWidget { color: Colors.teal, child: Padding( padding: const EdgeInsets.all(10), - child: Text( - 'Look at me pointing absolutely nothing.\n(Or maybe that\'s an hidden navigation bar !)', - style: textStyle, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Look at me pointing absolutely nothing.\n(Or maybe that\'s an hidden navigation bar !)', + style: textStyle, + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: () => slideActionConroller + .add(SlideControllerAction.previous), + child: Text('previous'), + ), + Container( + margin: EdgeInsets.only(left: 16.0), + child: RaisedButton( + child: Text('Next'), + onPressed: () { + slideActionConroller + .add(SlideControllerAction.next); + }, + ), + ) + ], + ), + ], ), ), ), @@ -112,6 +175,8 @@ class _BubbleShowcaseDemoWidget extends StatelessWidget { spreadRadius: 15, ), child: RelativeBubbleSlideChild( + extraWidthLeft: 50.0, + extraWidthRight: 50.0, widget: Padding( padding: const EdgeInsets.only(top: 23), child: SpeechBubble( @@ -119,21 +184,45 @@ class _BubbleShowcaseDemoWidget extends StatelessWidget { color: Colors.purple, child: Padding( padding: const EdgeInsets.all(10), - child: Row( - mainAxisSize: MainAxisSize.min, + child: Column( children: [ - Padding( - padding: const EdgeInsets.only(right: 5), - child: Icon( - Icons.info_outline, - color: Colors.white, - ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.only(right: 5), + child: Icon( + Icons.info_outline, + color: Colors.white, + ), + ), + Expanded( + child: Text( + 'As said, this button is new.\nOh, and this one is oval by the way.', + style: textStyle, + ), + ), + ], ), - Expanded( - child: Text( - 'As said, this button is new.\nOh, and this one is oval by the way.', - style: textStyle, - ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: () => slideActionConroller + .add(SlideControllerAction.previous), + child: Text('previous'), + ), + Container( + margin: EdgeInsets.only(left: 16.0), + child: RaisedButton( + child: Text('Done'), + onPressed: () { + slideActionConroller + .add(SlideControllerAction.close); + }, + ), + ) + ], ), ], ), @@ -182,9 +271,10 @@ class _BubbleShowcaseDemoChild extends StatelessWidget { ), ), RaisedButton( - child: const Text('This button is old, please don\'t pay attention.'), + child: const Text( + 'This button is old, please don\'t pay attention.'), onPressed: () {}, - ) + ), ], ), ); diff --git a/example/pubspec.lock b/example/pubspec.lock index aa0303c..c6f1513 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,16 +7,16 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.2" + version: "2.5.0-nullsafety.1" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.1" bubble_showcase: - dependency: "direct dev" + dependency: "direct main" description: path: ".." relative: true @@ -28,35 +28,42 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.0-nullsafety.3" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" + version: "1.2.0-nullsafety.1" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.1.0-nullsafety.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.13" + version: "1.15.0-nullsafety.3" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety.1" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" file: dependency: transitive description: @@ -92,21 +99,21 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.8" + version: "0.12.10-nullsafety.1" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.3" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.1" path_provider_linux: dependency: transitive description: @@ -120,7 +127,14 @@ packages: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "1.0.4" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.4+3" platform: dependency: transitive description: @@ -134,7 +148,7 @@ packages: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "1.0.3" process: dependency: transitive description: @@ -148,35 +162,42 @@ packages: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "0.5.8" + version: "0.5.12+4" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "0.0.2+1" + version: "0.0.2+4" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+6" + version: "0.0.1+11" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.4" shared_preferences_web: dependency: transitive description: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "0.1.2+4" + version: "0.1.2+7" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+3" sky_engine: dependency: transitive description: flutter @@ -188,70 +209,77 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.2" speech_bubble: - dependency: "direct dev" + dependency: "direct main" description: name: speech_bubble url: "https://pub.dartlang.org" source: hosted - version: "0.0.6" + version: "0.0.7" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.5" + version: "1.10.0-nullsafety.1" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.1" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0-nullsafety.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.17" + version: "0.2.19-nullsafety.2" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0-nullsafety.3" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.3" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.3" xdg_directories: dependency: transitive description: name: xdg_directories url: "https://pub.dartlang.org" source: hosted - version: "0.1.0" + version: "0.1.2" sdks: - dart: ">=2.9.0-14.0.dev <3.0.0" + dart: ">=2.10.0-110 <2.11.0" flutter: ">=1.12.13+hotfix.5 <2.0.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index baa7195..051087c 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -2,19 +2,21 @@ name: bubble_showcase_example description: Demonstrates how to use the bubble_showcase plugin. publish_to: 'none' +version: 1.0.0+1 + environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: + bubble_showcase: + path: ../ flutter: sdk: flutter + speech_bubble: ^0.0.7 dev_dependencies: flutter_test: sdk: flutter - bubble_showcase: - path: ../ - speech_bubble: ^0.0.6 flutter: uses-material-design: true diff --git a/lib/src/showcase.dart b/lib/src/showcase.dart index aa269fd..d054491 100644 --- a/lib/src/showcase.dart +++ b/lib/src/showcase.dart @@ -1,10 +1,17 @@ library bubble_showcase; +import 'dart:async'; import 'package:bubble_showcase/src/slide.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:shared_preferences/shared_preferences.dart'; +enum SlideControllerAction { + next, + previous, + close, +} + /// The BubbleShowcase main widget. class BubbleShowcase extends StatefulWidget { /// This showcase identifier. Must be unique across the app. @@ -28,6 +35,15 @@ class BubbleShowcase extends StatefulWidget { /// Whether to show a close button. final bool showCloseButton; + /// Whether to enable click on overlay to go to next slide + final bool enabledClickOnOverlayToNextSlide; + + /// Trigger this stream to change slide by position number + final Stream slideNumberStream; + + /// Trigger to control slide + final Stream slideActionStream; + /// Creates a new bubble showcase instance. BubbleShowcase({ @required this.bubbleShowcaseId, @@ -37,6 +53,9 @@ class BubbleShowcase extends StatefulWidget { this.child, this.counterText = ':i/:n', this.showCloseButton = true, + this.enabledClickOnOverlayToNextSlide = true, + this.slideNumberStream, + this.slideActionStream, }) : assert(bubbleSlides.isNotEmpty); @override @@ -63,6 +82,9 @@ class _BubbleShowcaseState extends State /// The current slide entry. OverlayEntry _currentSlideEntry; + // StreamSubscription slideNumberSubscription; + // StreamSubscription slideActionSubscription; + @override void initState() { WidgetsBinding.instance.addPostFrameCallback((_) async { @@ -75,6 +97,18 @@ class _BubbleShowcaseState extends State WidgetsBinding.instance.addObserver(this); super.initState(); + if (widget.slideNumberStream != null) { + widget.slideNumberStream.listen( + (position) { + _goToNextEntryOrClose(position); + }, + ); + } + if (widget.slideActionStream != null) { + widget.slideActionStream.listen((action) { + _slideActionHandler(action); + }); + } } @override @@ -85,6 +119,12 @@ class _BubbleShowcaseState extends State _currentSlideEntry?.remove(); WidgetsBinding.instance.removeObserver(this); super.dispose(); + // if (slideNumberSubscription != null) { + // slideNumberSubscription.cancel(); + // } + // if (slideActionSubscription != null) { + // slideActionSubscription.cancel(); + // } } @override @@ -99,13 +139,43 @@ class _BubbleShowcaseState extends State }); } + @override + void didUpdateWidget(BubbleShowcase old) { + super.didUpdateWidget(old); + // in case the stream instance changed, subscribe to the new one + if (widget.slideNumberStream != null) { + if (widget.slideNumberStream != old.slideNumberStream) { + // if (slideNumberSubscription != null) { + // slideNumberSubscription.cancel(); + // } + widget.slideNumberStream.listen((position) { + _goToNextEntryOrClose(position); + }); + } + } + if (widget.slideActionStream != null) { + if (widget.slideActionStream != old.slideActionStream) { + // if (slideActionSubscription != null) { + // slideActionSubscription.cancel(); + // } + widget.slideActionStream.listen((action) { + _slideActionHandler(action); + }); + } + } + } + /// Returns whether the showcasing is finished. bool get _isFinished => _currentSlideIndex == -1 || - _currentSlideIndex == widget.bubbleSlides.length; + _currentSlideIndex >= widget.bubbleSlides.length; /// Allows to go to the next entry (or to close the showcase if needed). void _goToNextEntryOrClose(int position) { + if (position < -1) { + return; + } + _currentSlideIndex = position; _currentSlideEntry.remove(); @@ -124,15 +194,35 @@ class _BubbleShowcaseState extends State } } + void _slideActionHandler(SlideControllerAction action) { + switch (action) { + case SlideControllerAction.next: + _goToNextEntryOrClose(_currentSlideIndex + 1); + break; + case SlideControllerAction.previous: + + /// Prevent close when invoke previous on first slide + if (_currentSlideIndex != 0) { + _goToNextEntryOrClose(_currentSlideIndex - 1); + } + break; + case SlideControllerAction.close: + _goToNextEntryOrClose(-1); + break; + } + } + /// Creates the current slide entry. - OverlayEntry _createCurrentSlideEntry() => OverlayEntry( - builder: (context) => widget.bubbleSlides[_currentSlideIndex].build( - context, - widget, - _currentSlideIndex, - (position) { - setState(() => _goToNextEntryOrClose(position)); - }, - ), - ); + OverlayEntry _createCurrentSlideEntry() { + return OverlayEntry( + builder: (context) => widget.bubbleSlides[_currentSlideIndex].build( + context, + widget, + _currentSlideIndex, + (position) { + setState(() => _goToNextEntryOrClose(position)); + }, + ), + ); + } } diff --git a/lib/src/slide.dart b/lib/src/slide.dart index 01a5828..619edb3 100644 --- a/lib/src/slide.dart +++ b/lib/src/slide.dart @@ -30,8 +30,12 @@ abstract class BubbleSlide { }); /// Builds the whole slide widget. - Widget build(BuildContext context, BubbleShowcase bubbleShowcase, - int currentSlideIndex, void Function(int) goToSlide) { + Widget build( + BuildContext context, + BubbleShowcase bubbleShowcase, + int currentSlideIndex, + void Function(int) goToSlide, + ) { Position highlightPosition = getHighlightPosition(context, bubbleShowcase, currentSlideIndex); List children = [ @@ -83,7 +87,9 @@ abstract class BubbleSlide { } return GestureDetector( - onTap: () => goToSlide(currentSlideIndex + 1), + onTap: () => bubbleShowcase.enabledClickOnOverlayToNextSlide + ? goToSlide(currentSlideIndex + 1) + : null, child: Stack( children: children, ), @@ -190,11 +196,19 @@ abstract class BubbleSlideChild { class RelativeBubbleSlideChild extends BubbleSlideChild { /// The child direction. final AxisDirection direction; + final double extraWidthRight; + final double extraWidthLeft; + final double extraHeightTop; + final double extraHeightBottom; /// Creates a new relative bubble slide child instance. const RelativeBubbleSlideChild({ Widget widget, this.direction = AxisDirection.down, + this.extraWidthRight = 0.0, + this.extraWidthLeft = 0.0, + this.extraHeightTop = 0.0, + this.extraHeightBottom = 0.0, }) : super( widget: widget, ); @@ -205,27 +219,29 @@ class RelativeBubbleSlideChild extends BubbleSlideChild { switch (direction) { case AxisDirection.up: return Position( - right: parentSize.width - highlightPosition.right, + right: parentSize.width - highlightPosition.right - extraWidthRight, bottom: parentSize.height - highlightPosition.top, - left: highlightPosition.left, + left: highlightPosition.left - extraWidthLeft, ); case AxisDirection.right: return Position( - top: highlightPosition.top, - bottom: parentSize.height - highlightPosition.bottom, + top: highlightPosition.top - extraHeightTop, + bottom: + parentSize.height - highlightPosition.bottom - extraHeightBottom, right: parentSize.width - highlightPosition.left, ); case AxisDirection.left: return Position( - top: highlightPosition.top, - bottom: parentSize.height - highlightPosition.bottom, + top: highlightPosition.top - extraHeightTop, + bottom: + parentSize.height - highlightPosition.bottom - extraHeightBottom, left: highlightPosition.right, ); default: return Position( top: highlightPosition.bottom, - right: parentSize.width - highlightPosition.right, - left: highlightPosition.left, + right: parentSize.width - highlightPosition.right - extraWidthRight, + left: highlightPosition.left - extraWidthLeft, ); } } diff --git a/pubspec.lock b/pubspec.lock index cfdc62d..d2ce49f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,14 +7,14 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.0-nullsafety.3" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.13" + version: "1.15.0-nullsafety.3" file: dependency: transitive description: @@ -45,7 +45,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.3" path: dependency: transitive description: @@ -141,14 +141,14 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0-nullsafety.3" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.3" xdg_directories: dependency: transitive description: @@ -157,5 +157,5 @@ packages: source: hosted version: "0.1.0" sdks: - dart: ">=2.9.0-14.0.dev <3.0.0" + dart: ">=2.10.0-110 <2.11.0" flutter: ">=1.12.13+hotfix.5 <2.0.0" diff --git a/screenshots/preview.gif b/screenshots/preview.gif index b1a74fd..fd02bb0 100644 Binary files a/screenshots/preview.gif and b/screenshots/preview.gif differ