├── example
├── ios
│ ├── Runner
│ │ ├── Runner-Bridging-Header.h
│ │ ├── Assets.xcassets
│ │ │ ├── LaunchImage.imageset
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ ├── README.md
│ │ │ │ └── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ │ └── Contents.json
│ │ ├── AppDelegate.swift
│ │ ├── Base.lproj
│ │ │ ├── Main.storyboard
│ │ │ └── LaunchScreen.storyboard
│ │ └── Info.plist
│ ├── Flutter
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ └── AppFrameworkInfo.plist
│ ├── Runner.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ ├── xcshareddata
│ │ │ └── xcschemes
│ │ │ │ └── Runner.xcscheme
│ │ └── project.pbxproj
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── Podfile.lock
│ ├── .gitignore
│ └── Podfile
├── android
│ ├── gradle.properties
│ ├── app
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── res
│ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── drawable
│ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── drawable-v21
│ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── values
│ │ │ │ │ │ └── styles.xml
│ │ │ │ │ └── values-night
│ │ │ │ │ │ └── styles.xml
│ │ │ │ ├── kotlin
│ │ │ │ │ └── com
│ │ │ │ │ │ └── hamidwakili
│ │ │ │ │ │ └── another_flushbar_example
│ │ │ │ │ │ └── MainActivity.kt
│ │ │ │ └── AndroidManifest.xml
│ │ │ ├── debug
│ │ │ │ └── AndroidManifest.xml
│ │ │ └── profile
│ │ │ │ └── AndroidManifest.xml
│ │ └── build.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ ├── .gitignore
│ ├── settings.gradle
│ └── build.gradle
├── .metadata
├── README.md
├── .gitignore
├── test
│ └── widget_test.dart
├── pubspec.yaml
├── pubspec.lock
└── lib
│ └── main.dart
├── .gitignore
├── android
├── local.properties
├── app
│ └── src
│ │ └── main
│ │ └── java
│ │ └── io
│ │ └── flutter
│ │ └── plugins
│ │ └── GeneratedPluginRegistrant.java
└── another_flushbar_android.iml
├── readme_resources
├── rtl_bar.png
├── basic_bar.png
├── input_bar.png
├── text_bar.png
├── complete_bar.png
├── gradient_bar.png
├── position_bar.png
├── floating_style.png
├── flushbar_logo.png
├── grounded_style.png
├── flushbar_animated.gif
├── background_color_bar.png
├── icon_and_button_bar.png
├── left_bar_indicator.png
└── padding_and_radius.png
├── analysis_options.yaml
├── .metadata
├── LICENSE
├── pubspec.yaml
├── test
└── another_flushbar_test.dart
├── lib
├── flushbar_helper.dart
├── flushbar_route.dart
└── flushbar.dart
├── pubspec.lock
├── CHANGELOG.md
└── README.md
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .dart_tool/
3 |
4 | .packages
5 | .pub/
6 |
7 | build/
8 |
9 | .idea/
--------------------------------------------------------------------------------
/android/local.properties:
--------------------------------------------------------------------------------
1 | sdk.dir=/home/slayer/Android/Sdk
2 | flutter.sdk=/home/slayer/snap/flutter/common/flutter
--------------------------------------------------------------------------------
/readme_resources/rtl_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/rtl_bar.png
--------------------------------------------------------------------------------
/readme_resources/basic_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/basic_bar.png
--------------------------------------------------------------------------------
/readme_resources/input_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/input_bar.png
--------------------------------------------------------------------------------
/readme_resources/text_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/text_bar.png
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/readme_resources/complete_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/complete_bar.png
--------------------------------------------------------------------------------
/readme_resources/gradient_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/gradient_bar.png
--------------------------------------------------------------------------------
/readme_resources/position_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/position_bar.png
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
2 | linter:
3 | rules:
4 | constant_identifier_names: false
--------------------------------------------------------------------------------
/readme_resources/floating_style.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/floating_style.png
--------------------------------------------------------------------------------
/readme_resources/flushbar_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/flushbar_logo.png
--------------------------------------------------------------------------------
/readme_resources/grounded_style.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/grounded_style.png
--------------------------------------------------------------------------------
/readme_resources/flushbar_animated.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/flushbar_animated.gif
--------------------------------------------------------------------------------
/readme_resources/background_color_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/background_color_bar.png
--------------------------------------------------------------------------------
/readme_resources/icon_and_button_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/icon_and_button_bar.png
--------------------------------------------------------------------------------
/readme_resources/left_bar_indicator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/left_bar_indicator.png
--------------------------------------------------------------------------------
/readme_resources/padding_and_radius.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/readme_resources/padding_and_radius.png
--------------------------------------------------------------------------------
/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/X-SLAYER/another-flushbar/main/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/com/hamidwakili/another_flushbar_example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.hamidwakili.another_flushbar_example
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
7 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: c6290500f827e006858ef2d17081b363949f6ce0
8 | channel: master
9 |
10 | project_type: plugin
11 |
--------------------------------------------------------------------------------
/example/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: c6290500f827e006858ef2d17081b363949f6ce0
8 | channel: master
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/example/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Flutter (1.0.0)
3 |
4 | DEPENDENCIES:
5 | - Flutter (from `Flutter`)
6 |
7 | EXTERNAL SOURCES:
8 | Flutter:
9 | :path: Flutter
10 |
11 | SPEC CHECKSUMS:
12 | Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
13 |
14 | PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
15 |
16 | COCOAPODS: 1.10.0
17 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | 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.
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright [2018-2020] [André Haueisen Batista de Lima, Hamid Wakili]
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # another_flushbar_example
2 |
3 | Demonstrates how to use the another_flushbar plugin.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
13 |
14 | For help getting started with Flutter, view our
15 | [online documentation](https://flutter.dev/docs), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java:
--------------------------------------------------------------------------------
1 | package io.flutter.plugins;
2 |
3 | import io.flutter.plugin.common.PluginRegistry;
4 |
5 | /**
6 | * Generated file. Do not edit.
7 | */
8 | public final class GeneratedPluginRegistrant {
9 | public static void registerWith(PluginRegistry registry) {
10 | if (alreadyRegisteredWith(registry)) {
11 | return;
12 | }
13 | }
14 |
15 | private static boolean alreadyRegisteredWith(PluginRegistry registry) {
16 | final String key = GeneratedPluginRegistrant.class.getCanonicalName();
17 | if (registry.hasPlugin(key)) {
18 | return true;
19 | }
20 | registry.registrarFor(key);
21 | return false;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/example/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 9.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Web related
35 | lib/generated_plugin_registrant.dart
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
43 | # Android Studio will place build artifacts here
44 | /android/app/debug
45 | /android/app/profile
46 | /android/app/release
47 |
--------------------------------------------------------------------------------
/example/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:another_flushbar_example/main.dart';
12 |
13 | void main() {
14 | testWidgets('Verify Platform version', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(MyApp());
17 |
18 | // Verify that platform version is retrieved.
19 | expect(
20 | find.byWidgetPredicate(
21 | (Widget widget) =>
22 | widget is Text && widget.data.startsWith('Running on:'),
23 | ),
24 | findsOneWidget,
25 | );
26 | });
27 | }
28 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/another_flushbar_android.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | another_flushbar_example
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: another_flushbar
2 | description: A flexible widget for user notification. Customize your text, button, duration, animations and much more. For Android devs, it is made to replace Snackbars and Toasts.
3 | version: 1.10.27
4 | homepage: https://github.com/cmdrootaccess/another-flushbar
5 |
6 | environment:
7 | sdk: '>=2.12.0 <3.0.0'
8 |
9 | dependencies:
10 | flutter:
11 | sdk: flutter
12 |
13 | dev_dependencies:
14 | flutter_lints: ^1.0.4
15 | flutter_test:
16 | sdk: flutter
17 |
18 | # For information on the generic Dart part of this file, see the
19 | # following page: https://dart.dev/tools/pub/pubspec
20 |
21 | # The following section is specific to Flutter.
22 | flutter:
23 |
24 | # To add assets to your plugin package, add an assets section, like this:
25 | # assets:
26 | # - images/a_dot_burr.jpeg
27 | # - images/a_dot_ham.jpeg
28 | #
29 | # For details regarding assets in packages, see
30 | # https://flutter.dev/assets-and-images/#from-packages
31 | #
32 | # An image asset can refer to one or more resolution-specific "variants", see
33 | # https://flutter.dev/assets-and-images/#resolution-aware.
34 |
35 | # To add custom fonts to your plugin package, add a fonts section here,
36 | # in this "flutter" section. Each entry in this list should have a
37 | # "family" key with the font family name, and a "fonts" key with a
38 | # list giving the asset and other descriptors for the font. For
39 | # example:
40 | # fonts:
41 | # - family: Schyler
42 | # fonts:
43 | # - asset: fonts/Schyler-Regular.ttf
44 | # - asset: fonts/Schyler-Italic.ttf
45 | # style: italic
46 | # - family: Trajan Pro
47 | # fonts:
48 | # - asset: fonts/TrajanPro.ttf
49 | # - asset: fonts/TrajanPro_Bold.ttf
50 | # weight: 700
51 | #
52 | # For details regarding fonts in packages, see
53 | # https://flutter.dev/custom-fonts/#from-packages
54 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | compileSdkVersion 29
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | lintOptions {
36 | disable 'InvalidPackage'
37 | }
38 |
39 | defaultConfig {
40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
41 | applicationId "com.hamidwakili.another_flushbar_example"
42 | minSdkVersion 16
43 | targetSdkVersion 29
44 | versionCode flutterVersionCode.toInteger()
45 | versionName flutterVersionName
46 | }
47 |
48 | buildTypes {
49 | release {
50 | // TODO: Add your own signing config for the release build.
51 | // Signing with the debug keys for now, so `flutter run --release` works.
52 | signingConfig signingConfigs.debug
53 | }
54 | }
55 | }
56 |
57 | flutter {
58 | source '../..'
59 | }
60 |
61 | dependencies {
62 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
63 | }
64 |
--------------------------------------------------------------------------------
/test/another_flushbar_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_test/flutter_test.dart';
2 | import 'package:another_flushbar/flushbar.dart';
3 |
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter/widgets.dart';
6 |
7 | void main() {
8 | TestWidgetsFlutterBinding.ensureInitialized();
9 |
10 | test('Test Flushbar basic inicialization', () async {
11 | final flushbar = Flushbar(message: 'This is a test');
12 | expect(flushbar.title, null);
13 | expect(flushbar.message, 'This is a test');
14 | expect(flushbar.duration, null);
15 | expect(flushbar.backgroundColor, const Color(0xFF303030));
16 | expect(flushbar.flushbarPosition, FlushbarPosition.BOTTOM);
17 | expect(flushbar.flushbarStyle, FlushbarStyle.FLOATING);
18 | expect(flushbar.forwardAnimationCurve, Curves.easeOutCirc);
19 | expect(flushbar.reverseAnimationCurve, Curves.easeOutCirc);
20 | expect(flushbar.titleText, null);
21 | expect(flushbar.messageText, null);
22 | expect(flushbar.icon, null);
23 | expect(flushbar.leftBarIndicatorColor, null);
24 | expect(flushbar.boxShadows, null);
25 | expect(flushbar.backgroundGradient, null);
26 | expect(flushbar.mainButton, null);
27 | expect(flushbar.borderRadius, null);
28 | expect(flushbar.borderWidth, 1.0);
29 | expect(flushbar.borderColor, null);
30 | expect(flushbar.padding.left, 16);
31 | expect(flushbar.padding.right, 16);
32 | expect(flushbar.padding.top, 16);
33 | expect(flushbar.padding.bottom, 16);
34 | expect(flushbar.margin.left, 0);
35 | expect(flushbar.margin.right, 0);
36 | expect(flushbar.margin.top, 0);
37 | expect(flushbar.margin.bottom, 0);
38 | expect(flushbar.onTap, null);
39 | expect(flushbar.isDismissible, true);
40 | expect(flushbar.dismissDirection, FlushbarDismissDirection.VERTICAL);
41 | expect(flushbar.showProgressIndicator, false);
42 | expect(flushbar.progressIndicatorController, null);
43 | expect(flushbar.progressIndicatorBackgroundColor, null);
44 | expect(flushbar.progressIndicatorValueColor, null);
45 | expect(flushbar.routeBlur, null);
46 | expect(flushbar.routeColor, null);
47 | });
48 | }
49 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
13 |
17 |
21 |
26 |
30 |
31 |
32 |
33 |
34 |
35 |
37 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: another_flushbar_example
2 | description: Demonstrates how to use the another_flushbar plugin.
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `pub publish`. This is preferred for private packages.
6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
7 |
8 | environment:
9 | sdk: ">=2.7.0 <3.0.0"
10 |
11 | dependencies:
12 | flutter:
13 | sdk: flutter
14 |
15 | another_flushbar:
16 | # When depending on this package from a real application you should use:
17 | # another_flushbar: ^x.y.z
18 | # See https://dart.dev/tools/pub/dependencies#version-constraints
19 | # The example app is bundled with the plugin so we use a path dependency on
20 | # the parent directory to use the current plugin's version.
21 | path: ../
22 |
23 | # The following adds the Cupertino Icons font to your application.
24 | # Use with the CupertinoIcons class for iOS style icons.
25 | cupertino_icons: ^1.0.1
26 |
27 | dev_dependencies:
28 | flutter_test:
29 | sdk: flutter
30 |
31 | # For information on the generic Dart part of this file, see the
32 | # following page: https://dart.dev/tools/pub/pubspec
33 |
34 | # The following section is specific to Flutter.
35 | flutter:
36 |
37 | # The following line ensures that the Material Icons font is
38 | # included with your application, so that you can use the icons in
39 | # the material Icons class.
40 | uses-material-design: true
41 |
42 | # To add assets to your application, add an assets section, like this:
43 | # assets:
44 | # - images/a_dot_burr.jpeg
45 | # - images/a_dot_ham.jpeg
46 |
47 | # An image asset can refer to one or more resolution-specific "variants", see
48 | # https://flutter.dev/assets-and-images/#resolution-aware.
49 |
50 | # For details regarding adding assets from package dependencies, see
51 | # https://flutter.dev/assets-and-images/#from-packages
52 |
53 | # To add custom fonts to your application, add a fonts section here,
54 | # in this "flutter" section. Each entry in this list should have a
55 | # "family" key with the font family name, and a "fonts" key with a
56 | # list giving the asset and other descriptors for the font. For
57 | # example:
58 | # fonts:
59 | # - family: Schyler
60 | # fonts:
61 | # - asset: fonts/Schyler-Regular.ttf
62 | # - asset: fonts/Schyler-Italic.ttf
63 | # style: italic
64 | # - family: Trajan Pro
65 | # fonts:
66 | # - asset: fonts/TrajanPro.ttf
67 | # - asset: fonts/TrajanPro_Bold.ttf
68 | # weight: 700
69 | #
70 | # For details regarding fonts from package dependencies,
71 | # see https://flutter.dev/custom-fonts/#from-packages
72 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/lib/flushbar_helper.dart:
--------------------------------------------------------------------------------
1 | import 'flushbar.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class FlushbarHelper {
5 | /// Get a success notification flushbar.
6 | static Flushbar createSuccess(
7 | {required String message,
8 | String? title,
9 | Duration duration = const Duration(seconds: 3)}) {
10 | return Flushbar(
11 | title: title,
12 | message: message,
13 | icon: Icon(
14 | Icons.check_circle,
15 | color: Colors.green[300],
16 | ),
17 | leftBarIndicatorColor: Colors.green[300],
18 | duration: duration,
19 | );
20 | }
21 |
22 | /// Get an information notification flushbar
23 | static Flushbar createInformation(
24 | {required String message,
25 | String? title,
26 | Duration duration = const Duration(seconds: 3)}) {
27 | return Flushbar(
28 | title: title,
29 | message: message,
30 | icon: Icon(
31 | Icons.info_outline,
32 | size: 28.0,
33 | color: Colors.blue[300],
34 | ),
35 | leftBarIndicatorColor: Colors.blue[300],
36 | duration: duration,
37 | );
38 | }
39 |
40 | /// Get a error notification flushbar
41 | static Flushbar createError(
42 | {required String message,
43 | String? title,
44 | Duration duration = const Duration(seconds: 3)}) {
45 | return Flushbar(
46 | title: title,
47 | message: message,
48 | icon: Icon(
49 | Icons.warning,
50 | size: 28.0,
51 | color: Colors.red[300],
52 | ),
53 | leftBarIndicatorColor: Colors.red[300],
54 | duration: duration,
55 | );
56 | }
57 |
58 | /// Get a flushbar that can receive a user action through a button.
59 | static Flushbar createAction(
60 | {required String message,
61 | required Widget button,
62 | String? title,
63 | Duration duration = const Duration(seconds: 3)}) {
64 | return Flushbar(
65 | title: title,
66 | message: message,
67 | duration: duration,
68 | mainButton: button,
69 | );
70 | }
71 |
72 | // Get a flushbar that shows the progress of a async computation.
73 | static Flushbar createLoading(
74 | {required String message,
75 | required LinearProgressIndicator linearProgressIndicator,
76 | String? title,
77 | Duration duration = const Duration(seconds: 3),
78 | AnimationController? progressIndicatorController,
79 | Color? progressIndicatorBackgroundColor}) {
80 | return Flushbar(
81 | title: title,
82 | message: message,
83 | icon: Icon(
84 | Icons.cloud_upload,
85 | color: Colors.blue[300],
86 | ),
87 | duration: duration,
88 | showProgressIndicator: true,
89 | progressIndicatorController: progressIndicatorController,
90 | progressIndicatorBackgroundColor: progressIndicatorBackgroundColor,
91 | );
92 | }
93 |
94 | /// Get a flushbar that shows an user input form.
95 | static Flushbar createInputFlushbar({required Form textForm}) {
96 | return Flushbar(
97 | duration: null,
98 | userInputForm: textForm,
99 | );
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "2.8.2"
11 | boolean_selector:
12 | dependency: transitive
13 | description:
14 | name: boolean_selector
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "2.1.0"
18 | characters:
19 | dependency: transitive
20 | description:
21 | name: characters
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "1.2.0"
25 | charcode:
26 | dependency: transitive
27 | description:
28 | name: charcode
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.3.1"
32 | clock:
33 | dependency: transitive
34 | description:
35 | name: clock
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.1.0"
39 | collection:
40 | dependency: transitive
41 | description:
42 | name: collection
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "1.16.0"
46 | fake_async:
47 | dependency: transitive
48 | description:
49 | name: fake_async
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "1.3.0"
53 | flutter:
54 | dependency: "direct main"
55 | description: flutter
56 | source: sdk
57 | version: "0.0.0"
58 | flutter_lints:
59 | dependency: "direct dev"
60 | description:
61 | name: flutter_lints
62 | url: "https://pub.dartlang.org"
63 | source: hosted
64 | version: "1.0.4"
65 | flutter_test:
66 | dependency: "direct dev"
67 | description: flutter
68 | source: sdk
69 | version: "0.0.0"
70 | lints:
71 | dependency: transitive
72 | description:
73 | name: lints
74 | url: "https://pub.dartlang.org"
75 | source: hosted
76 | version: "1.0.1"
77 | matcher:
78 | dependency: transitive
79 | description:
80 | name: matcher
81 | url: "https://pub.dartlang.org"
82 | source: hosted
83 | version: "0.12.11"
84 | material_color_utilities:
85 | dependency: transitive
86 | description:
87 | name: material_color_utilities
88 | url: "https://pub.dartlang.org"
89 | source: hosted
90 | version: "0.1.4"
91 | meta:
92 | dependency: transitive
93 | description:
94 | name: meta
95 | url: "https://pub.dartlang.org"
96 | source: hosted
97 | version: "1.7.0"
98 | path:
99 | dependency: transitive
100 | description:
101 | name: path
102 | url: "https://pub.dartlang.org"
103 | source: hosted
104 | version: "1.8.1"
105 | sky_engine:
106 | dependency: transitive
107 | description: flutter
108 | source: sdk
109 | version: "0.0.99"
110 | source_span:
111 | dependency: transitive
112 | description:
113 | name: source_span
114 | url: "https://pub.dartlang.org"
115 | source: hosted
116 | version: "1.8.2"
117 | stack_trace:
118 | dependency: transitive
119 | description:
120 | name: stack_trace
121 | url: "https://pub.dartlang.org"
122 | source: hosted
123 | version: "1.10.0"
124 | stream_channel:
125 | dependency: transitive
126 | description:
127 | name: stream_channel
128 | url: "https://pub.dartlang.org"
129 | source: hosted
130 | version: "2.1.0"
131 | string_scanner:
132 | dependency: transitive
133 | description:
134 | name: string_scanner
135 | url: "https://pub.dartlang.org"
136 | source: hosted
137 | version: "1.1.0"
138 | term_glyph:
139 | dependency: transitive
140 | description:
141 | name: term_glyph
142 | url: "https://pub.dartlang.org"
143 | source: hosted
144 | version: "1.2.0"
145 | test_api:
146 | dependency: transitive
147 | description:
148 | name: test_api
149 | url: "https://pub.dartlang.org"
150 | source: hosted
151 | version: "0.4.9"
152 | vector_math:
153 | dependency: transitive
154 | description:
155 | name: vector_math
156 | url: "https://pub.dartlang.org"
157 | source: hosted
158 | version: "2.1.2"
159 | sdks:
160 | dart: ">=2.17.0-0 <3.0.0"
161 |
--------------------------------------------------------------------------------
/example/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | another_flushbar:
5 | dependency: "direct main"
6 | description:
7 | path: ".."
8 | relative: true
9 | source: path
10 | version: "1.10.27"
11 | async:
12 | dependency: transitive
13 | description:
14 | name: async
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "2.8.2"
18 | boolean_selector:
19 | dependency: transitive
20 | description:
21 | name: boolean_selector
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "2.1.0"
25 | characters:
26 | dependency: transitive
27 | description:
28 | name: characters
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.2.0"
32 | charcode:
33 | dependency: transitive
34 | description:
35 | name: charcode
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.3.1"
39 | clock:
40 | dependency: transitive
41 | description:
42 | name: clock
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "1.1.0"
46 | collection:
47 | dependency: transitive
48 | description:
49 | name: collection
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "1.16.0"
53 | cupertino_icons:
54 | dependency: "direct main"
55 | description:
56 | name: cupertino_icons
57 | url: "https://pub.dartlang.org"
58 | source: hosted
59 | version: "1.0.3"
60 | fake_async:
61 | dependency: transitive
62 | description:
63 | name: fake_async
64 | url: "https://pub.dartlang.org"
65 | source: hosted
66 | version: "1.3.0"
67 | flutter:
68 | dependency: "direct main"
69 | description: flutter
70 | source: sdk
71 | version: "0.0.0"
72 | flutter_test:
73 | dependency: "direct dev"
74 | description: flutter
75 | source: sdk
76 | version: "0.0.0"
77 | matcher:
78 | dependency: transitive
79 | description:
80 | name: matcher
81 | url: "https://pub.dartlang.org"
82 | source: hosted
83 | version: "0.12.11"
84 | material_color_utilities:
85 | dependency: transitive
86 | description:
87 | name: material_color_utilities
88 | url: "https://pub.dartlang.org"
89 | source: hosted
90 | version: "0.1.4"
91 | meta:
92 | dependency: transitive
93 | description:
94 | name: meta
95 | url: "https://pub.dartlang.org"
96 | source: hosted
97 | version: "1.7.0"
98 | path:
99 | dependency: transitive
100 | description:
101 | name: path
102 | url: "https://pub.dartlang.org"
103 | source: hosted
104 | version: "1.8.1"
105 | sky_engine:
106 | dependency: transitive
107 | description: flutter
108 | source: sdk
109 | version: "0.0.99"
110 | source_span:
111 | dependency: transitive
112 | description:
113 | name: source_span
114 | url: "https://pub.dartlang.org"
115 | source: hosted
116 | version: "1.8.2"
117 | stack_trace:
118 | dependency: transitive
119 | description:
120 | name: stack_trace
121 | url: "https://pub.dartlang.org"
122 | source: hosted
123 | version: "1.10.0"
124 | stream_channel:
125 | dependency: transitive
126 | description:
127 | name: stream_channel
128 | url: "https://pub.dartlang.org"
129 | source: hosted
130 | version: "2.1.0"
131 | string_scanner:
132 | dependency: transitive
133 | description:
134 | name: string_scanner
135 | url: "https://pub.dartlang.org"
136 | source: hosted
137 | version: "1.1.0"
138 | term_glyph:
139 | dependency: transitive
140 | description:
141 | name: term_glyph
142 | url: "https://pub.dartlang.org"
143 | source: hosted
144 | version: "1.2.0"
145 | test_api:
146 | dependency: transitive
147 | description:
148 | name: test_api
149 | url: "https://pub.dartlang.org"
150 | source: hosted
151 | version: "0.4.9"
152 | vector_math:
153 | dependency: transitive
154 | description:
155 | name: vector_math
156 | url: "https://pub.dartlang.org"
157 | source: hosted
158 | version: "2.1.2"
159 | sdks:
160 | dart: ">=2.17.0-0 <3.0.0"
161 |
--------------------------------------------------------------------------------
/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:another_flushbar/flushbar.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() {
5 | runApp(MyApp());
6 | }
7 |
8 | class MyApp extends StatelessWidget {
9 | // This widget is the root of your application.
10 | @override
11 | Widget build(BuildContext context) {
12 | return MaterialApp(
13 | title: 'Flutter Demo',
14 | theme: ThemeData(
15 | // This is the theme of your application.
16 | //
17 | // Try running your application with "flutter run". You'll see the
18 | // application has a blue toolbar. Then, without quitting the app, try
19 | // changing the primarySwatch below to Colors.green and then invoke
20 | // "hot reload" (press "r" in the console where you ran "flutter run",
21 | // or simply save your changes to "hot reload" in a Flutter IDE).
22 | // Notice that the counter didn't reset back to zero; the application
23 | // is not restarted.
24 | primarySwatch: Colors.blue,
25 | ),
26 | home: MyHomePage(title: 'Flutter Demo Home Page'),
27 | );
28 | }
29 | }
30 |
31 | class MyHomePage extends StatefulWidget {
32 | MyHomePage({Key key, this.title}) : super(key: key);
33 |
34 | // This widget is the home page of your application. It is stateful, meaning
35 | // that it has a State object (defined below) that contains fields that affect
36 | // how it looks.
37 |
38 | // This class is the configuration for the state. It holds the values (in this
39 | // case the title) provided by the parent (in this case the App widget) and
40 | // used by the build method of the State. Fields in a Widget subclass are
41 | // always marked "final".
42 |
43 | final String title;
44 |
45 | @override
46 | _MyHomePageState createState() => _MyHomePageState();
47 | }
48 |
49 | class _MyHomePageState extends State {
50 | @override
51 | Widget build(BuildContext context) {
52 | // This method is rerun every time setState is called, for instance as done
53 | // by the _incrementCounter method above.
54 | //
55 | // The Flutter framework has been optimized to make rerunning build methods
56 | // fast, so that you can just rebuild anything that needs updating rather
57 | // than having to individually change instances of widgets.
58 | return Scaffold(
59 | appBar: AppBar(
60 | // Here we take the value from the MyHomePage object that was created by
61 | // the App.build method, and use it to set our appbar title.
62 | title: Text(widget.title),
63 | ),
64 | body: Center(
65 | // Center is a layout widget. It takes a single child and positions it
66 | // in the middle of the parent.
67 | child: Column(
68 | // Column is also a layout widget. It takes a list of children and
69 | // arranges them vertically. By default, it sizes itself to fit its
70 | // children horizontally, and tries to be as tall as its parent.
71 | //
72 | // Invoke "debug painting" (press "p" in the console, choose the
73 | // "Toggle Debug Paint" action from the Flutter Inspector in Android
74 | // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
75 | // to see the wireframe for each widget.
76 | //
77 | // Column has various properties to control how it sizes itself and
78 | // how it positions its children. Here we use mainAxisAlignment to
79 | // center the children vertically; the main axis here is the vertical
80 | // axis because Columns are vertical (the cross axis would be
81 | // horizontal).
82 | mainAxisAlignment: MainAxisAlignment.center,
83 | children: [
84 | Text(
85 | 'Hello flushbar:',
86 | ),
87 | ],
88 | ),
89 | ),
90 | floatingActionButton: FloatingActionButton(
91 | onPressed: () async {
92 | await Flushbar(
93 | title: 'Hey Ninja',
94 | message:
95 | 'Lorem Ipsum is simply dummy text of the printing and typesetting industry',
96 | duration: Duration(seconds: 3),
97 | ).show(context);
98 | },
99 | tooltip: 'Increment',
100 | child: Icon(Icons.add),
101 | ), // This trailing comma makes auto-formatting nicer for build methods.
102 | );
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 1.10.27 - 2021-12-09
2 | - merge updates
3 | ## 1.10.26 - 2021-11-24
4 | - Update screenshot links
5 | ## 1.10.25 - 2021-11-01
6 | - RTL text
7 | ## 1.10.24 - 2021-07-6
8 | - Implemented endOffset parameter
9 | ## 1.10.23 - 2021-06-4
10 | - Prevents hiding flushbar when user clicks the back button.
11 | ## 1.10.22 - 2021-05-14
12 | - check if flushbar is null
13 | ## 1.10.21 - 2021-05-14
14 | - add radius to leftBarIndicatorColor
15 | ## 1.10.20 - 2021-04-24
16 | - If route was never initialized, do nothing
17 | ## 1.10.19 - 2021-04-23
18 | - Fix Flushbar is hidden behind keyboard
19 | ## 1.10.18 - 2021-04-16
20 | - Fix LateInitializationError: Field '_progressListener' has not been initialized
21 | ## 1.10.17 - 2021-03-16
22 | - Fix nullpointer on onStatusChanged & add pedantic analysis and formatting
23 | ## 1.10.16 - 2021-03-16
24 | - Remove unnecessary platform specific code
25 | ## 1.10.15 - 2021-03-11
26 | - Add isAppearing and isHiding methods
27 | ## 1.10.14 - 2021-03-10
28 | - add color and size parameter
29 | - Let the user choose which corner they want to apply a radius on.
30 | ## 1.10.13 - 2021-03-6
31 | - fix Expected value of SkDeletable, but got one of type Null
32 | - fix regression after merge generated_plugin_registrant.dart: Undefined name 'AnotherFlushbarPlugin
33 | ## 1.10.12 - 2021-03-6
34 | - added null safety support after merge from areille/null-safety merge
35 | ## 1.10.11 - 2021-02-22
36 | - fix [WEB] Undefined name 'AnotherFlushbarPlugin' in generated_plugin_registrant.dart
37 | ## 1.10.10 - 2021-02-16
38 | - FlushbarHelper.createAction() "button" parameter takes a FlatButton which is now deprecated in favor of TextButton
39 | ## 1.10.9 - 2021-02-16
40 | - added positionOffset which allows a vertical offset for the flushbar
41 | ## 1.10.8 - 2020-12-12
42 | - Web support
43 | ## 1.10.7 - 2020-06-12
44 | - Updated Example
45 |
46 | ## 1.10.6 - 2020-06-12
47 | - Fixed Readme
48 | ## 1.10.5 - 2020-06-12
49 |
50 | - Fixed 'overlayEntries.isEmpty': is not true
51 |
52 | ## [1.10.4] - 2020-15-05
53 | - [button] is now a [Widget] instead of [FlatButton]
54 | - Removed generic type requirement to extend Object
55 | - Fixed bar blur clipping
56 |
57 | ## [1.10.3] - 2020-15-05
58 | - Fixes example pictures
59 |
60 | ## [1.10.2] - 2020-15-05
61 | - Fixes SDK version
62 |
63 | ## [1.10.1] - 2020-07-05
64 | - With FLutter's 1.17 release, Flushbar 1.10 is now compatible with stable channel
65 |
66 | ## [1.10.0] - 2020-25-03
67 | - **Breaking change** fixes a breaking change introduced by Flutter. Only use this version if you are using flutter v1.15 or greater (currently on the beta channel)
68 | - **Breaking change** adds blockBackgroundInteraction property.
69 | - **Breaking change** overlayBlur renamed to routeBlur. Will be ignored if blockBackgroundInteraction is false
70 | - **Breaking change** overlayColor renamed to routeColor. Will be ignored if blockBackgroundInteraction is false
71 | - Now, if [showProgressIndicator] is true and [progressIndicatorController] is null, an infinite linear progress indicator will be shown
72 | - Performance improvements
73 | - Code refactoring
74 |
75 | ## [1.9.1] - 2019-21-10
76 | - Fixed shadows not showing up
77 |
78 | ## [1.9.0] - 2019-01-09
79 | - Added `maxWidth` property
80 | - Added `barBlur` which applies a BackdropFilter only to Flushbar's background
81 | - Default animation curve changed from `fastOutSlowIn` to `easeOutCirc`
82 |
83 | ## [1.8.2] - 2019-02-08
84 | - Blur overlay is now dismissible by click if `isDismissible == true`
85 | - Blur overlay will now animate until it disappears instead of vanishing
86 |
87 | ## [1.8.1] - 2019-29-07
88 | - Removed context requirement from flushbar_route
89 | - Fix onTap requiring a return value
90 |
91 | ## [1.8.0] - 2019-17-07
92 | - **Breaking Change** renamed `aroundPadding` to `margin`
93 | - Flushbar now supports uniform borders (same border on all sides)
94 | - Added `borderColor` property
95 | - Added `borderWidth` property
96 | - Added `padding` property - default still complies with material design specs
97 |
98 | ## [1.7.1+1] - 2019-10-07
99 | - Fixed environment variables
100 |
101 | ## [1.7.1] - 2019-10-07
102 | - Changed file docs to comply with dartdoc directives
103 | - Flutter minimum version for Flushbar is now 1.7.8
104 | - With Flutter version 1.7.8 hitting stable, there is no version restriction for stable channel users anymore
105 |
106 | ## [1.7.0] - 2019-05-06
107 | - add onTap property
108 | - fix exception caused by user dismissal while flushbar is appearing or hiding
109 |
110 | ## [1.6.0] - 2019-31-05
111 | - **breaking change** this fixes `The method 'detach' isn't defined for the class 'FocusScopeNode'`
112 |
113 | ## [1.5.3] - 2019-27-05
114 | - update README file
115 |
116 | ## [1.5.2] - 2019-26-05
117 | - `titleText` and `messageText` are now widgets so users can use `RichText` or `Text`
118 | - Add `shouldIconPulse` property
119 |
120 | ## [1.5.0] - 2019-04-05
121 | - **Breaking Change** boxShadow is now called boxShadows and is a List
122 |
123 | ## [1.4.0] - 2019-08-04
124 | - Add `overlayBlur` property that pushes an overlay blocking user input on the background. Only takes effect if greater then 0.0
125 | - Add `overlayColor` property that changes the overlay color. Default is transparent. Only takes effect if overlayBlur is greater then 0.0
126 | - Create new file for FlushbarRoute
127 |
128 | ## [1.3.1] - 2019-02-04
129 | - Constructor now has strongly typed parameters (my bad for forgetting it)
130 | - Improved null message error
131 |
132 | ## [1.3.0] - 2019-14-03
133 | - **Breaking Change** expect for `onStatusChanged`, all properties are now final. Two dot notation does
134 | not work anymore. Since you can only use the instance one time, this
135 | is the best practice.
136 | - Add `dismissDirection` property.
137 | - **Behaviour change** dismiss is now vertical by default. This is more natural since
138 | Flushbar show animation is also vertical.
139 | - It is now possible to dismiss a Flushbar that is not the top route.
140 | The only inconvenient is that it will not animate back (simply disappear) and the listener, if used, will not register the dismissal.
141 | - Updated README file
142 |
143 | ## [1.2.4] - 2019-05-03
144 | - Added FlushbarStyle.FLOATING & FlushbarStyle.GROUNDED
145 | - Fixed icon animation being started even if icon is null
146 |
147 | ## [1.2.3] - 2019-25-02
148 | - **Breaking Change** Flushbar now accepts a BoxShadow for a more customized shadow
149 |
150 | ## [1.2.2] - 2019-22-02
151 | - Fixed a bug when push an route after flushbar, and flushbar timer pop the current route out
152 |
153 | ## [1.2.1] - 2019-11-01
154 | - aroundPadding is now more flexible and receives EdgeInsets instead of an int
155 |
156 | ## [1.2.0] - 2018-09-12
157 | - add animationDuration argument. You can now control how long does it take to show and dismiss Flushbar
158 |
159 | ## [1.1.2] - 2018-24-10
160 | - icon argument can now be any widget, though I recommend using Icon or Image
161 | - added null checks
162 |
163 | ## [1.1.1] - 2018-17-10
164 |
165 | - Fixed bug where calling Navigator.push() on Flushbar swipe dismissal did not pop the route
166 | - Fixed bug where swipe to dismiss a padded Flushbar caused to being stuck at the edge
167 |
168 | ## [1.1.0] - 2018-11-10
169 |
170 | - Added two new features: aroundPadding and borderRadius
171 | - Fixed a bug where the overlay background was not null
172 |
173 | ## [1.0.1] - 2018-11-02
174 |
175 | - Texts now respond to alignment
176 |
177 | ## [1.0.0] - 2018-11-02
178 |
179 | - No changes. Simply reached stable after a month without new bugs
180 |
181 | ## [0.9.2] - 2018-09-29
182 |
183 | ### Changes
184 |
185 | - Dismissing a Flushbar that is not the top route no longer throws an exception
186 | - Dismissing a Flushbar that is not the top route has the following effects:
187 | * It does not animate back. It simply vanishes
188 | * FlushbarStatus listener will not register `FlushbarStatus.IS_HIDING` or `FlushbarStatus.DISMISSED`
189 | * It returns no value when the Future yield by `dismiss()` completes
190 |
191 | ### Fixes
192 |
193 | - Fixed an issue where a dismissible Flushbar would not cancel the timer and pop two routes instead of one
194 |
195 | ## [0.9.1] - 2018-09-25
196 |
197 | ### Changes
198 |
199 | - Fixed an issue where Flushbar could get stuck when swipe to dismiss was used
200 | - Minor layout tweeks
201 | - Flushbar gets a weird logo! Do not judge me. I'm not a designer :)
202 | - README file update
203 | - README file fixes
204 |
205 | ## [0.9.0] - 2018-09-10
206 |
207 | Looking good for version 1.0. Please, report any issues your have.
208 |
209 | ### Changes
210 |
211 | - **IMPORTANT** `dismiss()` now returns a future when the animation is completed and route is poped. That makes it easier to concatenate two or more Flushbars.
212 | - Major changes on how `show` and `dismiss` animations work, making Flushbar more reliable.
213 | - Trying to `dismiss()` a Flushbar that is not the top route is going to throw an error.
214 | - Pressing the back button will now properly `dismiss()` Flushbar.
215 | - Performance improvements. In and out animations are smoother.
216 |
217 | ### Layout Changes
218 |
219 | - Removed top padding when `flushbarPosition == FlushbarPosition.TOP`
220 |
221 | ## [0.8.3] - 2018-09-07
222 |
223 | ### Fixes
224 |
225 | - Fixed issue when `isDismissible` is set to false [Issue #6](https://github.com/AndreHaueisen/flushbar/issues/6#issue-357423067)
226 | - Fixed issue where the keyboard would hide Flushbar [Issue #7](https://github.com/AndreHaueisen/flushbar/issues/7#issue-357946307)
227 |
228 | ## [0.8.2] - 2018-08-27
229 |
230 | ### Changes
231 |
232 | - Add `key` property
233 | - Fixed bug here using flushbar_helper progressIndicator did not show
234 | - Fixed documentation about progressIndicator
235 |
236 | ## [0.8.1] - 2018-08-12
237 |
238 | ### Changes
239 |
240 | - Fixed Dart version issue
241 |
242 | ## [0.8.0] - 2018-08-11
243 | ### Breaking changes
244 | - Changed the behaviour of linearProgressIndicator to allow the user to controll its progress. See README.md for examples
245 | ### Changes
246 | - Added a left vertical bar to better convey the humor of the notification. See README.md for examples
247 | - Title is not mandatory anymore
248 |
249 | ## [0.7.6] - 2018-08-07
250 | ### Changes
251 | - Version update to supprt master channel
252 |
253 | ## [0.7.5] - 2018-07-28
254 | ### Changes
255 | - Fix bug where keyboard did not show when using a Form
256 | - Flushbar is now compatible with the master channel
257 | - Bug fixes
258 |
259 | ## [0.7.1] - 2018-07-08
260 | ### Changes
261 | - Flushbar doc update
262 |
263 | ## [0.7.0] - 2018-07-08
264 | ### Breaking changes
265 | - Flushbar does not need a global instance anymore
266 | - Flushbar it now made be used only one time. After it hits the dismissed state, that instance wont work anymore
267 | - Due to the behaviour above, there is no need to call commitChanges() anymore
268 | - Flushbar does not need to be within a Stack widget anymore
269 | - Purged state eliminated
270 | - FlushbarMorph is now called FlushbarHelper
271 |
272 | ### Changes
273 | - README.md is updated
274 |
275 | ### Known issues
276 | - When using a Form, the keyboard is not shown. Still figuring out how to solve it.
277 |
278 | ## [0.5.6] - 2018-06-20
279 | ### Changed
280 | - Fixed dependency issue
281 |
282 | ## [0.5.5] - 2018-06-20
283 | ### Changed
284 | - Updated flushbar_morph
285 | - Updated sdk version
286 |
287 | ## [0.5.4] - 2018-06-16
288 | ### Changed
289 | - Flushbar now animates size changes when commit is called while showing
290 | - Layout refinements
291 |
292 | ## [0.5.2] - 2018-06-05
293 | ### Changed
294 | - User input now receives a Form to facilitate field validation
295 |
296 | ## [0.5.1] - 2018-06-05
297 | ### Changed
298 | - Fixed brain fart. Same changes as 0.5.0
299 |
300 | ## [0.5.0] - 2018-06-05
301 | ### Changed
302 | - Removed change...() functions. Cascade notation is now recommended
303 | - Update readme file
304 | - Default message font size reduced from 16.0 to 14.0
305 | - Default title font size reduced from 16.0 to 15.0
306 |
307 | ## [0.4.7] - 2018-06-04
308 | ### Changed
309 | - Fixed bug with bar duration
310 | - Blink animation when Flushbar is not dismissed now animates the whole bar
311 | and is synchronised with content change.
312 |
313 | ## [0.4.5] - 2018-06-03
314 | ### Added
315 | - Blink animation when commitChanges() is called when Flushbar is not dismissed. This provides a
316 | smooth content transition
317 | - Helper class to morph Flushbar (FlushbarMorph)
318 | ### Changed
319 | - Code cleanup
320 |
321 | ## [0.4.0] - 2018-05-27
322 | ### Added
323 | - InputTextField
324 |
325 | ## [0.3.1] - 2018-05-27
326 | ### Changed
327 | - Fixed bar being automatically called
328 | - Title and message are not required at construction time
329 | - Better usage example
330 | - Removed callback from constructor
331 |
332 | ## [0.3.0] - 2018-05-27
333 | ### Changed
334 | - Removed the possibility to chose icon position
335 | - Widgets are now aligned correctly
336 | - Documentation improvements
337 |
338 | ## [0.2.5] - 2018-05-26
339 | ### Changed
340 | - Bug fixes
341 | - Moved icon animation into the flushbar
342 | - changeStatusListener() is now activated on change
343 |
344 | ## [0.2.0] - 2018-05-24
345 | ### Added
346 | - Removed requirement for a initial widget
347 | - OnStatusChanged callback so it is possible to listen to the various Flushbar status
348 | - The callback can be changed using changeStatusListener()
349 | - Started working on the README.md file
350 |
351 | ### Changed
352 | - IconAwareAnimation is now more general and it is called PulseAnimator
353 | - Flushbar now accepts an Icon instead of only the IconData and IconColor
354 | - Alignment changes
355 | - Default background color
356 |
357 | ## [0.0.1] - 2018-05-23
358 |
359 | ### Added
360 | - Flushbar creation
361 | - Single button action
362 | - Status listeners
363 | - Left or right icon positioning
364 | - Top or bottom positioning
--------------------------------------------------------------------------------
/lib/flushbar_route.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:ui';
3 |
4 | import 'package:flutter/material.dart';
5 |
6 | import 'flushbar.dart';
7 |
8 | class FlushbarRoute extends OverlayRoute {
9 | final Flushbar flushbar;
10 | final Builder _builder;
11 | final Completer _transitionCompleter = Completer();
12 | final FlushbarStatusCallback? _onStatusChanged;
13 |
14 | Animation? _filterBlurAnimation;
15 | Animation? _filterColorAnimation;
16 | Alignment? _initialAlignment;
17 | Alignment? _endAlignment;
18 | bool _wasDismissedBySwipe = false;
19 | Timer? _timer;
20 | T? _result;
21 | FlushbarStatus? currentStatus;
22 |
23 | FlushbarRoute({
24 | required this.flushbar,
25 | RouteSettings? settings,
26 | }) : _builder = Builder(builder: (BuildContext innerContext) {
27 | return GestureDetector(
28 | onTap:
29 | flushbar.onTap != null ? () => flushbar.onTap!(flushbar) : null,
30 | child: flushbar,
31 | );
32 | }),
33 | _onStatusChanged = flushbar.onStatusChanged,
34 | super(settings: settings) {
35 | _configureAlignment(flushbar.flushbarPosition);
36 | }
37 |
38 | void _configureAlignment(FlushbarPosition flushbarPosition) {
39 | switch (flushbar.flushbarPosition) {
40 | case FlushbarPosition.TOP:
41 | {
42 | _initialAlignment = const Alignment(-1.0, -2.0);
43 | _endAlignment = flushbar.endOffset != null
44 | ? const Alignment(-1.0, -1.0) +
45 | Alignment(flushbar.endOffset!.dx, flushbar.endOffset!.dy)
46 | : const Alignment(-1.0, -1.0);
47 | break;
48 | }
49 | case FlushbarPosition.BOTTOM:
50 | {
51 | _initialAlignment = const Alignment(-1.0, 2.0);
52 | _endAlignment = flushbar.endOffset != null
53 | ? const Alignment(-1.0, 1.0) +
54 | Alignment(flushbar.endOffset!.dx, flushbar.endOffset!.dy)
55 | : const Alignment(-1.0, 1.0);
56 | break;
57 | }
58 | }
59 | }
60 |
61 | Future get completed => _transitionCompleter.future;
62 | bool get opaque => false;
63 |
64 | @override
65 | Future willPop() {
66 | if (!flushbar.isDismissible) {
67 | return Future.value(RoutePopDisposition.doNotPop);
68 | }
69 |
70 | return Future.value(RoutePopDisposition.pop);
71 | }
72 |
73 | @override
74 | Iterable createOverlayEntries() {
75 | final overlays = [];
76 |
77 | if (flushbar.blockBackgroundInteraction) {
78 | overlays.add(
79 | OverlayEntry(
80 | builder: (BuildContext context) {
81 | return Listener(
82 | onPointerDown:
83 | flushbar.isDismissible ? (_) => flushbar.dismiss() : null,
84 | child: _createBackgroundOverlay(),
85 | );
86 | },
87 | maintainState: false,
88 | opaque: opaque),
89 | );
90 | }
91 |
92 | overlays.add(
93 | OverlayEntry(
94 | builder: (BuildContext context) {
95 | final Widget annotatedChild = Semantics(
96 | focused: false,
97 | container: true,
98 | explicitChildNodes: true,
99 | child: AlignTransition(
100 | alignment: _animation!,
101 | child: flushbar.isDismissible
102 | ? _getDismissibleFlushbar(_builder)
103 | : _getFlushbar(),
104 | ),
105 | );
106 | return annotatedChild;
107 | },
108 | maintainState: false,
109 | opaque: opaque),
110 | );
111 |
112 | return overlays;
113 | }
114 |
115 | Widget _createBackgroundOverlay() {
116 | if (_filterBlurAnimation != null && _filterColorAnimation != null) {
117 | return AnimatedBuilder(
118 | animation: _filterBlurAnimation!,
119 | builder: (context, child) {
120 | return BackdropFilter(
121 | filter: ImageFilter.blur(
122 | sigmaX: _filterBlurAnimation!.value,
123 | sigmaY: _filterBlurAnimation!.value),
124 | child: Container(
125 | constraints: const BoxConstraints.expand(),
126 | color: _filterColorAnimation!.value,
127 | ),
128 | );
129 | },
130 | );
131 | }
132 |
133 | if (_filterBlurAnimation != null) {
134 | return AnimatedBuilder(
135 | animation: _filterBlurAnimation!,
136 | builder: (context, child) {
137 | return BackdropFilter(
138 | filter: ImageFilter.blur(
139 | sigmaX: _filterBlurAnimation!.value,
140 | sigmaY: _filterBlurAnimation!.value),
141 | child: Container(
142 | constraints: const BoxConstraints.expand(),
143 | color: Colors.transparent,
144 | ),
145 | );
146 | },
147 | );
148 | }
149 |
150 | if (_filterColorAnimation != null) {
151 | AnimatedBuilder(
152 | animation: _filterColorAnimation!,
153 | builder: (context, child) {
154 | return Container(
155 | constraints: const BoxConstraints.expand(),
156 | color: _filterColorAnimation!.value,
157 | );
158 | },
159 | );
160 | }
161 |
162 | return Container(
163 | constraints: const BoxConstraints.expand(),
164 | color: Colors.transparent,
165 | );
166 | }
167 |
168 | /// This string is a workaround until Dismissible supports a returning item
169 | String dismissibleKeyGen = '';
170 |
171 | Widget _getDismissibleFlushbar(Widget child) {
172 | return Dismissible(
173 | direction: _getDismissDirection(),
174 | resizeDuration: null,
175 | confirmDismiss: (_) {
176 | if (currentStatus == FlushbarStatus.IS_APPEARING ||
177 | currentStatus == FlushbarStatus.IS_HIDING) {
178 | return Future.value(false);
179 | }
180 | return Future.value(true);
181 | },
182 | key: Key(dismissibleKeyGen),
183 | onDismissed: (_) {
184 | dismissibleKeyGen += '1';
185 | _cancelTimer();
186 | _wasDismissedBySwipe = true;
187 |
188 | if (isCurrent) {
189 | navigator!.pop();
190 | } else {
191 | navigator!.removeRoute(this);
192 | }
193 | },
194 | child: _getFlushbar(),
195 | );
196 | }
197 |
198 | DismissDirection _getDismissDirection() {
199 | if (flushbar.dismissDirection == FlushbarDismissDirection.HORIZONTAL) {
200 | return DismissDirection.horizontal;
201 | } else {
202 | if (flushbar.flushbarPosition == FlushbarPosition.TOP) {
203 | return DismissDirection.up;
204 | } else {
205 | return DismissDirection.down;
206 | }
207 | }
208 | }
209 |
210 | Widget _getFlushbar() {
211 | return Container(
212 | margin: flushbar.margin,
213 | child: _builder,
214 | );
215 | }
216 |
217 | @override
218 | bool get finishedWhenPopped =>
219 | _controller!.status == AnimationStatus.dismissed;
220 |
221 | /// The animation that drives the route's transition and the previous route's
222 | /// forward transition.
223 | Animation? get animation => _animation;
224 | Animation? _animation;
225 |
226 | /// The animation controller that the route uses to drive the transitions.
227 | ///
228 | /// The animation itself is exposed by the [animation] property.
229 | @protected
230 | AnimationController? get controller => _controller;
231 | AnimationController? _controller;
232 |
233 | /// Called to create the animation controller that will drive the transitions to
234 | /// this route from the previous one, and back to the previous route from this
235 | /// one.
236 | AnimationController createAnimationController() {
237 | assert(!_transitionCompleter.isCompleted,
238 | 'Cannot reuse a $runtimeType after disposing it.');
239 | assert(flushbar.animationDuration >= Duration.zero);
240 | return AnimationController(
241 | duration: flushbar.animationDuration,
242 | debugLabel: debugLabel,
243 | vsync: navigator!,
244 | );
245 | }
246 |
247 | /// Called to create the animation that exposes the current progress of
248 | /// the transition controlled by the animation controller created by
249 | /// [createAnimationController()].
250 | Animation createAnimation() {
251 | assert(!_transitionCompleter.isCompleted,
252 | 'Cannot reuse a $runtimeType after disposing it.');
253 | assert(_controller != null);
254 | return AlignmentTween(begin: _initialAlignment, end: _endAlignment).animate(
255 | CurvedAnimation(
256 | parent: _controller!,
257 | curve: flushbar.forwardAnimationCurve,
258 | reverseCurve: flushbar.reverseAnimationCurve,
259 | ),
260 | );
261 | }
262 |
263 | Animation? createBlurFilterAnimation() {
264 | if (flushbar.routeBlur == null) return null;
265 |
266 | return Tween(begin: 0.0, end: flushbar.routeBlur).animate(
267 | CurvedAnimation(
268 | parent: _controller!,
269 | curve: const Interval(
270 | 0.0,
271 | 0.35,
272 | curve: Curves.easeInOutCirc,
273 | ),
274 | ),
275 | );
276 | }
277 |
278 | Animation? createColorFilterAnimation() {
279 | if (flushbar.routeColor == null) return null;
280 |
281 | return ColorTween(begin: Colors.transparent, end: flushbar.routeColor)
282 | .animate(
283 | CurvedAnimation(
284 | parent: _controller!,
285 | curve: const Interval(
286 | 0.0,
287 | 0.35,
288 | curve: Curves.easeInOutCirc,
289 | ),
290 | ),
291 | );
292 | }
293 |
294 | //copy of `routes.dart`
295 | void _handleStatusChanged(AnimationStatus status) {
296 | switch (status) {
297 | case AnimationStatus.completed:
298 | currentStatus = FlushbarStatus.SHOWING;
299 | if (_onStatusChanged != null) _onStatusChanged!(currentStatus);
300 | if (overlayEntries.isNotEmpty) overlayEntries.first.opaque = opaque;
301 |
302 | break;
303 | case AnimationStatus.forward:
304 | currentStatus = FlushbarStatus.IS_APPEARING;
305 | if (_onStatusChanged != null) _onStatusChanged!(currentStatus);
306 | break;
307 | case AnimationStatus.reverse:
308 | currentStatus = FlushbarStatus.IS_HIDING;
309 | if (_onStatusChanged != null) _onStatusChanged!(currentStatus);
310 | if (overlayEntries.isNotEmpty) overlayEntries.first.opaque = false;
311 | break;
312 | case AnimationStatus.dismissed:
313 | assert(!overlayEntries.first.opaque);
314 | // We might still be the current route if a subclass is controlling the
315 | // the transition and hits the dismissed status. For example, the iOS
316 | // back gesture drives this animation to the dismissed status before
317 | // popping the navigator.
318 | currentStatus = FlushbarStatus.DISMISSED;
319 | if (_onStatusChanged != null) _onStatusChanged!(currentStatus);
320 |
321 | if (!isCurrent) {
322 | navigator!.finalizeRoute(this);
323 | if (overlayEntries.isNotEmpty) {
324 | overlayEntries.clear();
325 | }
326 | assert(overlayEntries.isEmpty);
327 | }
328 | break;
329 | }
330 | changedInternalState();
331 | }
332 |
333 | @override
334 | void install() {
335 | assert(!_transitionCompleter.isCompleted,
336 | 'Cannot install a $runtimeType after disposing it.');
337 | _controller = createAnimationController();
338 | assert(_controller != null,
339 | '$runtimeType.createAnimationController() returned null.');
340 | _filterBlurAnimation = createBlurFilterAnimation();
341 | _filterColorAnimation = createColorFilterAnimation();
342 | _animation = createAnimation();
343 | assert(_animation != null, '$runtimeType.createAnimation() returned null.');
344 | super.install();
345 | }
346 |
347 | @override
348 | TickerFuture didPush() {
349 | assert(_controller != null,
350 | '$runtimeType.didPush called before calling install() or after calling dispose().');
351 | assert(!_transitionCompleter.isCompleted,
352 | 'Cannot reuse a $runtimeType after disposing it.');
353 | _animation!.addStatusListener(_handleStatusChanged);
354 | _configureTimer();
355 | super.didPush();
356 | return _controller!.forward();
357 | }
358 |
359 | @override
360 | void didReplace(Route? oldRoute) {
361 | assert(_controller != null,
362 | '$runtimeType.didReplace called before calling install() or after calling dispose().');
363 | assert(!_transitionCompleter.isCompleted,
364 | 'Cannot reuse a $runtimeType after disposing it.');
365 | if (oldRoute is FlushbarRoute) {
366 | _controller!.value = oldRoute._controller!.value;
367 | }
368 | _animation!.addStatusListener(_handleStatusChanged);
369 | super.didReplace(oldRoute);
370 | }
371 |
372 | @override
373 | bool didPop(T? result) {
374 | assert(_controller != null,
375 | '$runtimeType.didPop called before calling install() or after calling dispose().');
376 | assert(!_transitionCompleter.isCompleted,
377 | 'Cannot reuse a $runtimeType after disposing it.');
378 |
379 | _result = result;
380 | _cancelTimer();
381 |
382 | if (_wasDismissedBySwipe) {
383 | Timer(const Duration(milliseconds: 200), () {
384 | _controller!.reset();
385 | });
386 |
387 | _wasDismissedBySwipe = false;
388 | } else {
389 | _controller!.reverse();
390 | }
391 |
392 | return super.didPop(result);
393 | }
394 |
395 | void _configureTimer() {
396 | if (flushbar.duration != null) {
397 | if (_timer != null && _timer!.isActive) {
398 | _timer!.cancel();
399 | }
400 | _timer = Timer(flushbar.duration!, () {
401 | if (isCurrent) {
402 | navigator!.pop();
403 | } else if (isActive) {
404 | navigator!.removeRoute(this);
405 | }
406 | });
407 | } else {
408 | if (_timer != null) {
409 | _timer!.cancel();
410 | }
411 | }
412 | }
413 |
414 | void _cancelTimer() {
415 | if (_timer != null && _timer!.isActive) {
416 | _timer!.cancel();
417 | }
418 | }
419 |
420 | /// Whether this route can perform a transition to the given route.
421 | ///
422 | /// Subclasses can override this method to restrict the set of routes they
423 | /// need to coordinate transitions with.
424 | bool canTransitionTo(FlushbarRoute nextRoute) => true;
425 |
426 | /// Whether this route can perform a transition from the given route.
427 | ///
428 | /// Subclasses can override this method to restrict the set of routes they
429 | /// need to coordinate transitions with.
430 | bool canTransitionFrom(FlushbarRoute previousRoute) => true;
431 |
432 | @override
433 | void dispose() {
434 | assert(!_transitionCompleter.isCompleted,
435 | 'Cannot dispose a $runtimeType twice.');
436 | _controller?.dispose();
437 | _transitionCompleter.complete(_result);
438 | super.dispose();
439 | }
440 |
441 | /// A short description of this route useful for debugging.
442 | String get debugLabel => '$runtimeType';
443 |
444 | @override
445 | String toString() => '$runtimeType(animation: $_controller)';
446 | }
447 |
448 | FlushbarRoute showFlushbar(
449 | {required BuildContext context, required Flushbar flushbar}) {
450 | return FlushbarRoute(
451 | flushbar: flushbar,
452 | settings: const RouteSettings(name: FLUSHBAR_ROUTE_NAME),
453 | );
454 | }
455 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # another_flushbar
2 |
3 | Use this package if you need more customization when notifying your user. For Android developers, it is made to substitute
4 | toasts and snackbars. IOS developers, I don't know what you use there, but you will like it.
5 |
6 | See the [install instructions](https://pub.dev/packages/another_flushbar/install).
7 |
8 | ## Quick reference
9 |
10 | Since customization requires a lot of properties, here is a quick cheatsheet:
11 |
12 | Property | What does it do
13 | -------- | ---------------
14 | title | The title displayed to the user
15 | titleColor | The title color displayed to the user
16 | titleSize | The title size displayed to the user
17 | message | The message displayed to the user.
18 | messageColor | The message color displayed to the user.
19 | messageSize | The message size displayed to the user.
20 | titleText | Replaces [title]. Although this accepts a [widget], **it is meant to receive [Text] or [RichText]**
21 | messageText | Replaces [message]. Although this accepts a [widget], **it is meant to receive [Text] or [RichText]**
22 | icon | You can use any widget here, but I recommend [Icon] or [Image] as indication of what kind of message you are displaying. Other widgets may break the layout
23 | shouldIconPulse | An option to animate the icon (if present). Defaults to true.
24 | maxWidth | Used to limit Flushbar width (usually on large screens)
25 | margin | Adds a custom margin to Flushbar
26 | padding | Adds a custom padding to Flushbar. The default follows material design guide line
27 | borderRadius | Adds a radius to specified corners of Flushbar. Best combined with [margin]. I do not recommend using it with [showProgressIndicator] or [leftBarIndicatorColor]
28 | textDirection | [TextDirection.ltr] by default. [Directionality.of(context)] to know whether it would be [TextDirection.ltr] or [TextDirection.rtl]
29 | borderColor | Adds a border to every side of Flushbar. I do not recommend using it with [showProgressIndicator] or [leftBarIndicatorColor]
30 | borderWidth | Changes the width of the border if [borderColor] is specified
31 | backgroundColor | Flushbar background color. Will be ignored if [backgroundGradient] is not null.
32 | leftBarIndicatorColor | If not null, shows a left vertical bar to better indicate the humor of the notification. It is not possible to use it with a [Form] and I do not recommend using it with [LinearProgressIndicator].
33 | boxShadows | The shadows generated by Flushbar. Leave it null if you don't want a shadow. You can use more than one if you feel the need. Check [this example](https://github.com/flutter/flutter/blob/main/packages/flutter/lib/src/material/shadows.dart)
34 | backgroundGradient | Flushbar background gradient. Makes [backgroundColor] be ignored.
35 | mainButton | Use if you need an action from the user. [FlatButton] is recommended here.
36 | onTap | A callback that registers the user's click anywhere. An alternative to [mainButton]
37 | duration | How long until Flushbar will hide itself (be dismissed). To make it indefinite, leave it null.
38 | isDismissible | Determines if the user can swipe or click the overlay (if [routeBlur] > 0) to dismiss. It is recommended that you set [duration] != null if this is false. If the user swipes to dismiss or clicks the overlay, no value will be returned.
39 | dismissDirection | FlushbarDismissDirection.VERTICAL by default. Can also be [FlushbarDismissDirection.HORIZONTAL] in which case both left and right dismiss are allowed.
40 | flushbarPosition | Flushbar can be based on [FlushbarPosition.TOP] or on [FlushbarPosition.BOTTOM] of your screen. [FlushbarPosition.BOTTOM] is the default.
41 | flushbarStyle | Flushbar can be floating or be grounded to the edge of the screen. If grounded, I do not recommend using [margin] or [borderRadius]. [FlushbarStyle.FLOATING] is the default
42 | forwardAnimationCurve | The [Curve] animation used when show() is called. [Curves.easeOut] is default.
43 | reverseAnimationCurve | The [Curve] animation used when dismiss() is called. [Curves.fastOutSlowIn] is default.
44 | animationDuration | Use it to speed up or slow down the animation duration
45 | showProgressIndicator | true if you want to show a [LinearProgressIndicator]. If [progressIndicatorController] is null, an infinite progress indicator will be shown
46 | progressIndicatorController | An optional [AnimationController] when you want to control the progress of your [LinearProgressIndicator]. You are responsible for controlling the progress
47 | progressIndicatorBackgroundColor | a [LinearProgressIndicator] configuration parameter.
48 | progressIndicatorValueColor | a [LinearProgressIndicator] configuration parameter.
49 | barBlur | Default is 0.0. If different than 0.0, blurs only Flushbar's background. To take effect, make sure your [backgroundColor] has some opacity. The greater the value, the greater the blur.
50 | blockBackgroundInteraction | Determines if user can interact with the screen behind it. If this is false, [routeBlur] and [routeColor] will be ignored
51 | routeBlur | Default is 0.0. If different than 0.0, creates a blurred overlay that prevents the user from interacting with the screen. The greater the value, the greater the blur. It does not take effect if [blockBackgroundInteraction] is false
52 | routeColor | Default is [Colors.transparent]. Only takes effect if [routeBlur] > 0.0. Make sure you use a color with transparency e.g. `Colors.grey[600].withOpacity(0.2)`. It does not take effect if [blockBackgroundInteraction] is false
53 | userInputForm | A [TextFormField] in case you want a simple user input. Every other widget is ignored if this is not null.
54 | onStatusChanged | a callback for you to listen to the different Flushbar status
55 |
56 | #### Quick tip
57 |
58 | If you use a lot of those properties, it makes sense to make a factory to help with your Flushbar's base appearance.
59 | Things like shadows, padding, margins, text styles usually don't change within the app. Take a look at FlushbarHelper class and use it as an example.
60 |
61 | ## We are on YouTube!
62 |
63 | While studying Flutter I stumbled on two amazing tutorials on how to use Flushbar.
64 | Make sure you show those guys some love.
65 | 1. A beginners [tutorial](https://www.youtube.com/watch?v=KNpxyyA8MDA) by **Matej Rešetár**
66 | 2. A more [advanced usage](https://www.youtube.com/watch?v=FRCvqkyeCzQ) by **Javier González Rodríguez**
67 |
68 | ## Getting Started
69 |
70 | The examples bellow were updated for version 1.3.0. Changes might have been made. See the [changelog](CHANGELOG.md) if any of the examples do not
71 | reflect Flushbar's current state.
72 |
73 | ### The possibilities
74 |
75 | 
76 |
77 | ### A basic Flushbar
78 |
79 | The most basic Flushbar uses only a message. Failing to provide it before you call `show()` will result in a runtime error.
80 | `Duration`, if not provided, will create an infinite Flushbar, only dismissible by code, back button clicks, or a drag (case `isDismissible` is set to `true`).
81 |
82 | - Note that only `message` is a required parameter. All the other ones are optional
83 |
84 | ```dart
85 | class YourAwesomeApp extends StatelessWidget {
86 |
87 | @override
88 | Widget build(BuildContext context) {
89 | return MaterialApp(
90 | title: 'YourAwesomeApp',
91 | home: Scaffold(
92 | Container(
93 | child: Center(
94 | child: MaterialButton(
95 | onPressed: (){
96 | Flushbar(
97 | title: "Hey Ninja",
98 | message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
99 | duration: Duration(seconds: 3),
100 | )..show(context);
101 | },
102 | ),
103 | ),
104 | ),
105 | ),
106 | );
107 | }
108 | }
109 | ```
110 |
111 | 
112 |
113 | ### Lets get crazy Flushbar
114 |
115 | Here is how customized things can get.
116 |
117 | ```dart
118 | Flushbar(
119 | title: "Hey Ninja",
120 | titleColor: Colors.white,
121 | message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
122 | flushbarPosition: FlushbarPosition.TOP,
123 | flushbarStyle: FlushbarStyle.FLOATING,
124 | reverseAnimationCurve: Curves.decelerate,
125 | forwardAnimationCurve: Curves.elasticOut,
126 | backgroundColor: Colors.red,
127 | boxShadows: [BoxShadow(color: Colors.blue[800], offset: Offset(0.0, 2.0), blurRadius: 3.0)],
128 | backgroundGradient: LinearGradient(colors: [Colors.blueGrey, Colors.black]),
129 | isDismissible: false,
130 | duration: Duration(seconds: 4),
131 | icon: Icon(
132 | Icons.check,
133 | color: Colors.greenAccent,
134 | ),
135 | mainButton: FlatButton(
136 | onPressed: () {},
137 | child: Text(
138 | "CLAP",
139 | style: TextStyle(color: Colors.amber),
140 | ),
141 | ),
142 | showProgressIndicator: true,
143 | progressIndicatorBackgroundColor: Colors.blueGrey,
144 | titleText: Text(
145 | "Hello Hero",
146 | style: TextStyle(
147 | fontWeight: FontWeight.bold, fontSize: 20.0, color: Colors.yellow[600], fontFamily: "ShadowsIntoLightTwo"),
148 | ),
149 | messageText: Text(
150 | "You killed that giant monster in the city. Congratulations!",
151 | style: TextStyle(fontSize: 18.0, color: Colors.green, fontFamily: "ShadowsIntoLightTwo"),
152 | ),
153 | );
154 | ```
155 |
156 | 
157 |
158 | - Don't forget to call `show()` or the bar will stay hidden.
159 | - To deactivate any of those properties, pass `null` to it.
160 |
161 | ### Styles
162 | Flushbar can be either floating or grounded to the edge of the screen.
163 | I don't recommend using `margin` or `borderRadius` if you chose `FlushbarStyle.GROUNDED` style.
164 |
165 | ```dart
166 | Flushbar(flushbarStyle: FlushbarStyle.FLOATING)
167 | ```
168 | or
169 | ```dart
170 | Flushbar(flushbarStyle: FlushbarStyle.GROUNDED)
171 | ```
172 | Floating Style | Grounded Style
173 | :------------------------------------------------------:|:-------------------------------------------------------:
174 |  | 
175 |
176 | ### Padding and Border Radius
177 | You can give it some padding and a border radius. Works best with `FlushbarStyle.FLOATING`
178 |
179 | ```dart
180 | Flushbar(
181 | margin: EdgeInsets.all(8),
182 | borderRadius: BorderRadius.circular(8),
183 | );
184 |
185 | ```
186 | 
187 |
188 | ### Left indicator bar
189 |
190 | Flushbar has a lateral bar to better convey the humor of the notification. To use it, simple give `leftBarIndicatorColor` a color.
191 |
192 | ```dart
193 | Flushbar(
194 | message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
195 | icon: Icon(
196 | Icons.info_outline,
197 | size: 28.0,
198 | color: Colors.blue[300],
199 | ),
200 | duration: Duration(seconds: 3),
201 | leftBarIndicatorColor: Colors.blue[300],
202 | )..show(context);
203 | ```
204 |
205 | 
206 |
207 | ### Customize your text
208 |
209 | If you need a more fancy text, you can use [Text](https://docs.flutter.io/flutter/widgets/Text-class.html) or [RichText](https://api.flutter.dev/flutter/widgets/RichText-class.html)
210 | and pass it to the `titleText` or `messageText` variables.
211 |
212 | - Note that `title` will be ignored if `titleText` is not `null`
213 | - Note that `message` will be ignored if `messageText` is not `null`
214 |
215 | ```dart
216 | Flushbar(
217 | title: "Hey Ninja", //ignored since titleText != null
218 | message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry", //ignored since messageText != null
219 | titleText: Text("Hello Hero", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0 color: Colors.yellow[600], fontFamily:"ShadowsIntoLightTwo"),),
220 | messageText: Text("You killed that giant monster in the city. Congratulations!", style: TextStyle(fontSize: 16.0, color: Colors.green[fontFamily: "ShadowsIntoLightTwo"),),
221 | )..show(context);
222 | ```
223 |
224 | 
225 |
226 | ### Customize background and shadow
227 |
228 | You can paint the background with any color you want. You can use any shadow you want.
229 | Just give it a `backgroundColor` and `boxShadows`.
230 |
231 | ```dart
232 | Flushbar(
233 | title: "Hey Ninja",
234 | message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
235 | backgroundColor: Colors.red,
236 | boxShadows: [BoxShadow(color: Colors.red[800], offset: Offset(0.0, 2.0), blurRadius: 3.0,)],
237 | )..show(context);
238 | ```
239 |
240 | 
241 |
242 | Want a gradient in the background? No problem.
243 |
244 | - Note that `backgroundColor` will be ignored while `backgroundGradient` is not `null`
245 |
246 | ```dart
247 | Flushbar(
248 | title: "Hey Ninja",
249 | message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
250 | backgroundGradient: LinearGradient(colors: [Colors.blue, Colors.teal]),
251 | backgroundColor: Colors.red,
252 | boxShadows: [BoxShadow(color: Colors.blue[800], offset: Offset(0.0, 2.0), blurRadius: 3.0,)],
253 | )..show(context);
254 | ```
255 |
256 | 
257 |
258 | ### Icon and button action
259 |
260 | Let us put a Icon that has a `PulseAnimation`. Icons have this animation by default and cannot be changed as of now.
261 | Also, let us put a button. Have you noticed that `show()` returns a `Future`?
262 | This Future will yield a value when you call `dismiss([T result])`.
263 | I recommend that you specify the `result` generic type if you intend to collect an user input.
264 |
265 | ```dart
266 | Flushbar flush;
267 | bool _wasButtonClicked;
268 | ```
269 |
270 | ```dart
271 | @override
272 | Widget build(BuildContext context) {
273 | return Container(
274 | child: Center(
275 | child: MaterialButton(
276 | onPressed: () {
277 | flush = Flushbar(
278 | title: "Hey Ninja",
279 | message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
280 | icon: Icon(
281 | Icons.info_outline,
282 | color: Colors.blue,),
283 | mainButton: FlatButton(
284 | onPressed: () {
285 | flush.dismiss(true); // result = true
286 | },
287 | child: Text(
288 | "ADD",
289 | style: TextStyle(color: Colors.amber),
290 | ),
291 | ),) // is the type of the result passed to dismiss() and collected by show().then((result){})
292 | ..show(context).then((result) {
293 | setState(() { // setState() is optional here
294 | _wasButtonClicked = result;
295 | });
296 | });
297 | },
298 | ),
299 | ),
300 | );
301 | }
302 | ```
303 |
304 | 
305 |
306 | ### Flushbar position
307 |
308 | Flushbar can be at `FlushbarPosition.BOTTOM` or `FlushbarPosition.TOP`.
309 |
310 | ```dart
311 | Flushbar(
312 | flushbarPosition: FlushbarPosition.TOP,
313 | title: "Hey Ninja",
314 | message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",)..show(context);
315 | ```
316 |
317 | 
318 |
319 | ### Duration and dismiss policy
320 |
321 | By default, Flushbar is infinite. To set a duration, use the `duration` property.
322 | By default, Flushbar is dismissible by the user. A right or left drag will dismiss it.
323 | Set `isDismissible` to `false` to change this behaviour.
324 |
325 | ```dart
326 | Flushbar(
327 | title: "Hey Ninja",
328 | message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
329 | duration: Duration(seconds: 3),
330 | isDismissible: false,
331 | )..show(context);
332 | ```
333 |
334 | ### Progress Indicator
335 |
336 | If you are loading something, use a [LinearProgressIndicator](https://docs.flutter.io/flutter/material/LinearProgressIndicator-class.html)
337 | If you want an undetermined progress indicator, do not set `progressIndicatorController`.
338 | If you want a determined progress indicator, you now have full control over the progress since you own the `AnimationController`
339 |
340 | - There is no need to add a listener to your controller just to call `setState(){}`. Once you pass in your controller, `Flushbar` will do this automatically. Just make sure you call `_controller.forward()`
341 |
342 | ```dart
343 |
344 | AnimationController _controller = AnimationController(
345 | vsync: this,
346 | duration: Duration(seconds: 3),
347 | );
348 |
349 | Flushbar(
350 | title: "Hey Ninja",
351 | message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
352 | showProgressIndicator: true,
353 | progressIndicatorController: _controller,
354 | progressIndicatorBackgroundColor: Colors.grey[800],
355 | )..show(context);
356 | ```
357 |
358 | ### Show and dismiss animation curves
359 |
360 | You can set custom animation curves using `forwardAnimationCurve` and `reverseAnimationCurve`.
361 |
362 | ```dart
363 | Flushbar(
364 | forwardAnimationCurve: Curves.decelerate,
365 | reverseAnimationCurve: Curves.easeOut,
366 | title: "Hey Ninja",
367 | message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
368 | )..show(context);
369 | ```
370 |
371 | ### Listen to status updates
372 |
373 | You can listen to status update using the `onStatusChanged` property.
374 |
375 | - Note that when you pass a new listener using `onStatusChanged`, it will activate once immediately so you can check in what state the Flushbar is.
376 |
377 | ```dart
378 |
379 | Flushbar flushbar = Flushbar(title: "Hey Ninja", message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry");
380 |
381 | flushbar
382 | ..onStatusChanged = (FlushbarStatus status) {
383 | switch (status) {
384 | case FlushbarStatus.SHOWING:
385 | {
386 | doSomething();
387 | break;
388 | }
389 | case FlushbarStatus.IS_APPEARING:
390 | {
391 | doSomethingElse();
392 | break;
393 | }
394 | case FlushbarStatus.IS_HIDING:
395 | {
396 | doSomethingElse();
397 | break;
398 | }
399 | case FlushbarStatus.DISMISSED:
400 | {
401 | doSomethingElse();
402 | break;
403 | }
404 | }
405 | }
406 | ..show(context);
407 |
408 | ```
409 |
410 | ### Input text
411 |
412 | Sometimes we just want a simple user input. Use the property`userInputForm`.
413 |
414 | - Note that buttons, messages, and icons will be ignored if `userInputForm != null`
415 | - `dismiss(result)` will yield result. `dismiss()` will yield null.
416 |
417 | ```dart
418 | Flushbar> flush;
419 | final GlobalKey _formKey = GlobalKey();
420 | ```
421 |
422 | ```dart
423 | TextFormField getFormField(String text) {
424 | return TextFormField(
425 | initialValue: text,
426 | style: TextStyle(color: Colors.white),
427 | maxLength: 100,
428 | maxLines: 1,
429 | maxLengthEnforced: true,
430 | decoration: InputDecoration(
431 | fillColor: Colors.white10,
432 | filled: true,
433 | icon: Icon(
434 | Icons.label,
435 | color: Colors.grey[500],
436 | ),
437 | border: UnderlineInputBorder(),
438 | helperText: "Helper Text",
439 | helperStyle: TextStyle(color: Colors.grey),
440 | labelText: "Label Text",
441 | labelStyle: TextStyle(color: Colors.grey)),
442 | );
443 | }
444 |
445 | flush = Flushbar>(
446 | userInputForm = Form(
447 | key: _formKey,
448 | child: Column(
449 | mainAxisSize: MainAxisSize.min,
450 | children: [
451 | getTextFormField("Initial Value"),
452 | getTextFormField("Initial Value Two"),
453 | ]
454 | Align(
455 | alignment: Alignment.bottomRight,
456 | child: Padding(
457 | padding: const EdgeInsets.only(top: 8.0),
458 | child: MaterialButton(
459 | textColor: Colors.amberAccent,
460 | child: Text("SUBMIT"),
461 | onPressed: () {
462 | flush.dismiss([_controller1.value.text, _controller2.value.text]);
463 | },
464 | ),
465 | ),
466 | )
467 | ],),),
468 | )..show(context).then((result) {
469 | if (result != null) {
470 | String userInput1 = result[0];
471 | String userInput2 = result[1];
472 | }
473 | });
474 | ```
475 |
476 | This example tries to mimic the [Material Design style guide](https://material.io/design/components/text-fields.html#anatomy)
477 |
478 | 
479 |
480 | ### RTL text
481 |
482 | 
483 |
484 | You can add `textDirection: Directionality.of(context)` for rtl.
485 |
486 | ```dart
487 | Flushbar(
488 | message: "لوريم إيبسوم هو ببساطة نص شكلي يستخدم في صناعة الطباعة والتنضيد",
489 | icon: Icon(
490 | Icons.info_outline,
491 | size: 28.0,
492 | color: Colors.blue[300],
493 | ),
494 | margin: EdgeInsets.all(6.0),
495 | flushbarStyle: FlushbarStyle.FLOATING,
496 | flushbarPosition: FlushbarPosition.TOP,
497 | textDirection: Directionality.of(context),
498 | borderRadius: BorderRadius.circular(12),
499 | duration: Duration(seconds: 3),
500 | leftBarIndicatorColor: Colors.blue[300],
501 | )..show(context);
502 | ```
503 |
504 | ## Flushbar Helper
505 |
506 | I made a helper class to facilitate the creation of the most common Flushbars.
507 |
508 | ```dart
509 | FlushbarHelper.createSuccess({message, title, duration});
510 | FlushbarHelper.createInformation({message, title, duration});
511 | FlushbarHelper.createError({message, title, duration});
512 | FlushbarHelper.createAction({message, title, duration flatButton});
513 | FlushbarHelper.createLoading({message,linearProgressIndicator, title, duration, progressIndicatorController, progressIndicatorBackgroundColor});
514 | FlushbarHelper.createInputFlushbar({textForm});
515 | ```
516 |
517 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
16 | AE43D7684848AD66E55F5000 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 89FA0030DDC8AE375CD07954 /* Pods_Runner.framework */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXCopyFilesBuildPhase section */
20 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
21 | isa = PBXCopyFilesBuildPhase;
22 | buildActionMask = 2147483647;
23 | dstPath = "";
24 | dstSubfolderSpec = 10;
25 | files = (
26 | );
27 | name = "Embed Frameworks";
28 | runOnlyForDeploymentPostprocessing = 0;
29 | };
30 | /* End PBXCopyFilesBuildPhase section */
31 |
32 | /* Begin PBXFileReference section */
33 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
34 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
35 | 1D283147CA76A05B0474F106 /* 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 = ""; };
36 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
37 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
38 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
39 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
40 | 8113E54F0F1E61393898D6F7 /* 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 = ""; };
41 | 89FA0030DDC8AE375CD07954 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
42 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
43 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
44 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
45 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
46 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
47 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
48 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
49 | CE09A55E4E01124515DC3A40 /* 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 = ""; };
50 | /* End PBXFileReference section */
51 |
52 | /* Begin PBXFrameworksBuildPhase section */
53 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
54 | isa = PBXFrameworksBuildPhase;
55 | buildActionMask = 2147483647;
56 | files = (
57 | AE43D7684848AD66E55F5000 /* Pods_Runner.framework in Frameworks */,
58 | );
59 | runOnlyForDeploymentPostprocessing = 0;
60 | };
61 | /* End PBXFrameworksBuildPhase section */
62 |
63 | /* Begin PBXGroup section */
64 | 5F1245786B26EB128502322A /* Frameworks */ = {
65 | isa = PBXGroup;
66 | children = (
67 | 89FA0030DDC8AE375CD07954 /* Pods_Runner.framework */,
68 | );
69 | name = Frameworks;
70 | sourceTree = "";
71 | };
72 | 9740EEB11CF90186004384FC /* Flutter */ = {
73 | isa = PBXGroup;
74 | children = (
75 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
76 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
77 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
78 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
79 | );
80 | name = Flutter;
81 | sourceTree = "";
82 | };
83 | 97C146E51CF9000F007C117D = {
84 | isa = PBXGroup;
85 | children = (
86 | 9740EEB11CF90186004384FC /* Flutter */,
87 | 97C146F01CF9000F007C117D /* Runner */,
88 | 97C146EF1CF9000F007C117D /* Products */,
89 | FB2A5CCAFD87C6238F76D6B1 /* Pods */,
90 | 5F1245786B26EB128502322A /* Frameworks */,
91 | );
92 | sourceTree = "";
93 | };
94 | 97C146EF1CF9000F007C117D /* Products */ = {
95 | isa = PBXGroup;
96 | children = (
97 | 97C146EE1CF9000F007C117D /* Runner.app */,
98 | );
99 | name = Products;
100 | sourceTree = "";
101 | };
102 | 97C146F01CF9000F007C117D /* Runner */ = {
103 | isa = PBXGroup;
104 | children = (
105 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
106 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
107 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
108 | 97C147021CF9000F007C117D /* Info.plist */,
109 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
110 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
111 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
112 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
113 | );
114 | path = Runner;
115 | sourceTree = "";
116 | };
117 | FB2A5CCAFD87C6238F76D6B1 /* Pods */ = {
118 | isa = PBXGroup;
119 | children = (
120 | 1D283147CA76A05B0474F106 /* Pods-Runner.debug.xcconfig */,
121 | CE09A55E4E01124515DC3A40 /* Pods-Runner.release.xcconfig */,
122 | 8113E54F0F1E61393898D6F7 /* Pods-Runner.profile.xcconfig */,
123 | );
124 | name = Pods;
125 | path = Pods;
126 | sourceTree = "";
127 | };
128 | /* End PBXGroup section */
129 |
130 | /* Begin PBXNativeTarget section */
131 | 97C146ED1CF9000F007C117D /* Runner */ = {
132 | isa = PBXNativeTarget;
133 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
134 | buildPhases = (
135 | 15B4DD1E83109262CF345277 /* [CP] Check Pods Manifest.lock */,
136 | 9740EEB61CF901F6004384FC /* Run Script */,
137 | 97C146EA1CF9000F007C117D /* Sources */,
138 | 97C146EB1CF9000F007C117D /* Frameworks */,
139 | 97C146EC1CF9000F007C117D /* Resources */,
140 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
141 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
142 | );
143 | buildRules = (
144 | );
145 | dependencies = (
146 | );
147 | name = Runner;
148 | productName = Runner;
149 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
150 | productType = "com.apple.product-type.application";
151 | };
152 | /* End PBXNativeTarget section */
153 |
154 | /* Begin PBXProject section */
155 | 97C146E61CF9000F007C117D /* Project object */ = {
156 | isa = PBXProject;
157 | attributes = {
158 | LastUpgradeCheck = 1020;
159 | ORGANIZATIONNAME = "";
160 | TargetAttributes = {
161 | 97C146ED1CF9000F007C117D = {
162 | CreatedOnToolsVersion = 7.3.1;
163 | LastSwiftMigration = 1100;
164 | };
165 | };
166 | };
167 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
168 | compatibilityVersion = "Xcode 9.3";
169 | developmentRegion = en;
170 | hasScannedForEncodings = 0;
171 | knownRegions = (
172 | en,
173 | Base,
174 | );
175 | mainGroup = 97C146E51CF9000F007C117D;
176 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
177 | projectDirPath = "";
178 | projectRoot = "";
179 | targets = (
180 | 97C146ED1CF9000F007C117D /* Runner */,
181 | );
182 | };
183 | /* End PBXProject section */
184 |
185 | /* Begin PBXResourcesBuildPhase section */
186 | 97C146EC1CF9000F007C117D /* Resources */ = {
187 | isa = PBXResourcesBuildPhase;
188 | buildActionMask = 2147483647;
189 | files = (
190 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
191 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
192 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
193 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
194 | );
195 | runOnlyForDeploymentPostprocessing = 0;
196 | };
197 | /* End PBXResourcesBuildPhase section */
198 |
199 | /* Begin PBXShellScriptBuildPhase section */
200 | 15B4DD1E83109262CF345277 /* [CP] Check Pods Manifest.lock */ = {
201 | isa = PBXShellScriptBuildPhase;
202 | buildActionMask = 2147483647;
203 | files = (
204 | );
205 | inputFileListPaths = (
206 | );
207 | inputPaths = (
208 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
209 | "${PODS_ROOT}/Manifest.lock",
210 | );
211 | name = "[CP] Check Pods Manifest.lock";
212 | outputFileListPaths = (
213 | );
214 | outputPaths = (
215 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
216 | );
217 | runOnlyForDeploymentPostprocessing = 0;
218 | shellPath = /bin/sh;
219 | 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";
220 | showEnvVarsInLog = 0;
221 | };
222 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
223 | isa = PBXShellScriptBuildPhase;
224 | buildActionMask = 2147483647;
225 | files = (
226 | );
227 | inputPaths = (
228 | );
229 | name = "Thin Binary";
230 | outputPaths = (
231 | );
232 | runOnlyForDeploymentPostprocessing = 0;
233 | shellPath = /bin/sh;
234 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
235 | };
236 | 9740EEB61CF901F6004384FC /* Run Script */ = {
237 | isa = PBXShellScriptBuildPhase;
238 | buildActionMask = 2147483647;
239 | files = (
240 | );
241 | inputPaths = (
242 | );
243 | name = "Run Script";
244 | outputPaths = (
245 | );
246 | runOnlyForDeploymentPostprocessing = 0;
247 | shellPath = /bin/sh;
248 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
249 | };
250 | /* End PBXShellScriptBuildPhase section */
251 |
252 | /* Begin PBXSourcesBuildPhase section */
253 | 97C146EA1CF9000F007C117D /* Sources */ = {
254 | isa = PBXSourcesBuildPhase;
255 | buildActionMask = 2147483647;
256 | files = (
257 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
258 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
259 | );
260 | runOnlyForDeploymentPostprocessing = 0;
261 | };
262 | /* End PBXSourcesBuildPhase section */
263 |
264 | /* Begin PBXVariantGroup section */
265 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
266 | isa = PBXVariantGroup;
267 | children = (
268 | 97C146FB1CF9000F007C117D /* Base */,
269 | );
270 | name = Main.storyboard;
271 | sourceTree = "";
272 | };
273 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
274 | isa = PBXVariantGroup;
275 | children = (
276 | 97C147001CF9000F007C117D /* Base */,
277 | );
278 | name = LaunchScreen.storyboard;
279 | sourceTree = "";
280 | };
281 | /* End PBXVariantGroup section */
282 |
283 | /* Begin XCBuildConfiguration section */
284 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
285 | isa = XCBuildConfiguration;
286 | buildSettings = {
287 | ALWAYS_SEARCH_USER_PATHS = NO;
288 | CLANG_ANALYZER_NONNULL = YES;
289 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
290 | CLANG_CXX_LIBRARY = "libc++";
291 | CLANG_ENABLE_MODULES = YES;
292 | CLANG_ENABLE_OBJC_ARC = YES;
293 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
294 | CLANG_WARN_BOOL_CONVERSION = YES;
295 | CLANG_WARN_COMMA = YES;
296 | CLANG_WARN_CONSTANT_CONVERSION = YES;
297 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
298 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
299 | CLANG_WARN_EMPTY_BODY = YES;
300 | CLANG_WARN_ENUM_CONVERSION = YES;
301 | CLANG_WARN_INFINITE_RECURSION = YES;
302 | CLANG_WARN_INT_CONVERSION = YES;
303 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
304 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
305 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
306 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
307 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
308 | CLANG_WARN_STRICT_PROTOTYPES = YES;
309 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
310 | CLANG_WARN_UNREACHABLE_CODE = YES;
311 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
312 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
313 | COPY_PHASE_STRIP = NO;
314 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
315 | ENABLE_NS_ASSERTIONS = NO;
316 | ENABLE_STRICT_OBJC_MSGSEND = YES;
317 | GCC_C_LANGUAGE_STANDARD = gnu99;
318 | GCC_NO_COMMON_BLOCKS = YES;
319 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
320 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
321 | GCC_WARN_UNDECLARED_SELECTOR = YES;
322 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
323 | GCC_WARN_UNUSED_FUNCTION = YES;
324 | GCC_WARN_UNUSED_VARIABLE = YES;
325 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
326 | MTL_ENABLE_DEBUG_INFO = NO;
327 | SDKROOT = iphoneos;
328 | SUPPORTED_PLATFORMS = iphoneos;
329 | TARGETED_DEVICE_FAMILY = "1,2";
330 | VALIDATE_PRODUCT = YES;
331 | };
332 | name = Profile;
333 | };
334 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
335 | isa = XCBuildConfiguration;
336 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
337 | buildSettings = {
338 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
339 | CLANG_ENABLE_MODULES = YES;
340 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
341 | ENABLE_BITCODE = NO;
342 | INFOPLIST_FILE = Runner/Info.plist;
343 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
344 | PRODUCT_BUNDLE_IDENTIFIER = com.hamidwakili.anotherFlushbarExample;
345 | PRODUCT_NAME = "$(TARGET_NAME)";
346 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
347 | SWIFT_VERSION = 5.0;
348 | VERSIONING_SYSTEM = "apple-generic";
349 | };
350 | name = Profile;
351 | };
352 | 97C147031CF9000F007C117D /* Debug */ = {
353 | isa = XCBuildConfiguration;
354 | buildSettings = {
355 | ALWAYS_SEARCH_USER_PATHS = NO;
356 | CLANG_ANALYZER_NONNULL = YES;
357 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
358 | CLANG_CXX_LIBRARY = "libc++";
359 | CLANG_ENABLE_MODULES = YES;
360 | CLANG_ENABLE_OBJC_ARC = YES;
361 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
362 | CLANG_WARN_BOOL_CONVERSION = YES;
363 | CLANG_WARN_COMMA = YES;
364 | CLANG_WARN_CONSTANT_CONVERSION = YES;
365 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
366 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
367 | CLANG_WARN_EMPTY_BODY = YES;
368 | CLANG_WARN_ENUM_CONVERSION = YES;
369 | CLANG_WARN_INFINITE_RECURSION = YES;
370 | CLANG_WARN_INT_CONVERSION = YES;
371 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
372 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
373 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
374 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
375 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
376 | CLANG_WARN_STRICT_PROTOTYPES = YES;
377 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
378 | CLANG_WARN_UNREACHABLE_CODE = YES;
379 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
380 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
381 | COPY_PHASE_STRIP = NO;
382 | DEBUG_INFORMATION_FORMAT = dwarf;
383 | ENABLE_STRICT_OBJC_MSGSEND = YES;
384 | ENABLE_TESTABILITY = YES;
385 | GCC_C_LANGUAGE_STANDARD = gnu99;
386 | GCC_DYNAMIC_NO_PIC = NO;
387 | GCC_NO_COMMON_BLOCKS = YES;
388 | GCC_OPTIMIZATION_LEVEL = 0;
389 | GCC_PREPROCESSOR_DEFINITIONS = (
390 | "DEBUG=1",
391 | "$(inherited)",
392 | );
393 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
394 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
395 | GCC_WARN_UNDECLARED_SELECTOR = YES;
396 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
397 | GCC_WARN_UNUSED_FUNCTION = YES;
398 | GCC_WARN_UNUSED_VARIABLE = YES;
399 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
400 | MTL_ENABLE_DEBUG_INFO = YES;
401 | ONLY_ACTIVE_ARCH = YES;
402 | SDKROOT = iphoneos;
403 | TARGETED_DEVICE_FAMILY = "1,2";
404 | };
405 | name = Debug;
406 | };
407 | 97C147041CF9000F007C117D /* Release */ = {
408 | isa = XCBuildConfiguration;
409 | buildSettings = {
410 | ALWAYS_SEARCH_USER_PATHS = NO;
411 | CLANG_ANALYZER_NONNULL = YES;
412 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
413 | CLANG_CXX_LIBRARY = "libc++";
414 | CLANG_ENABLE_MODULES = YES;
415 | CLANG_ENABLE_OBJC_ARC = YES;
416 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
417 | CLANG_WARN_BOOL_CONVERSION = YES;
418 | CLANG_WARN_COMMA = YES;
419 | CLANG_WARN_CONSTANT_CONVERSION = YES;
420 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
421 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
422 | CLANG_WARN_EMPTY_BODY = YES;
423 | CLANG_WARN_ENUM_CONVERSION = YES;
424 | CLANG_WARN_INFINITE_RECURSION = YES;
425 | CLANG_WARN_INT_CONVERSION = YES;
426 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
427 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
428 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
429 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
430 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
431 | CLANG_WARN_STRICT_PROTOTYPES = YES;
432 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
433 | CLANG_WARN_UNREACHABLE_CODE = YES;
434 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
435 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
436 | COPY_PHASE_STRIP = NO;
437 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
438 | ENABLE_NS_ASSERTIONS = NO;
439 | ENABLE_STRICT_OBJC_MSGSEND = YES;
440 | GCC_C_LANGUAGE_STANDARD = gnu99;
441 | GCC_NO_COMMON_BLOCKS = YES;
442 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
443 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
444 | GCC_WARN_UNDECLARED_SELECTOR = YES;
445 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
446 | GCC_WARN_UNUSED_FUNCTION = YES;
447 | GCC_WARN_UNUSED_VARIABLE = YES;
448 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
449 | MTL_ENABLE_DEBUG_INFO = NO;
450 | SDKROOT = iphoneos;
451 | SUPPORTED_PLATFORMS = iphoneos;
452 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
453 | TARGETED_DEVICE_FAMILY = "1,2";
454 | VALIDATE_PRODUCT = YES;
455 | };
456 | name = Release;
457 | };
458 | 97C147061CF9000F007C117D /* Debug */ = {
459 | isa = XCBuildConfiguration;
460 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
461 | buildSettings = {
462 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
463 | CLANG_ENABLE_MODULES = YES;
464 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
465 | ENABLE_BITCODE = NO;
466 | INFOPLIST_FILE = Runner/Info.plist;
467 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
468 | PRODUCT_BUNDLE_IDENTIFIER = com.hamidwakili.anotherFlushbarExample;
469 | PRODUCT_NAME = "$(TARGET_NAME)";
470 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
471 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
472 | SWIFT_VERSION = 5.0;
473 | VERSIONING_SYSTEM = "apple-generic";
474 | };
475 | name = Debug;
476 | };
477 | 97C147071CF9000F007C117D /* Release */ = {
478 | isa = XCBuildConfiguration;
479 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
480 | buildSettings = {
481 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
482 | CLANG_ENABLE_MODULES = YES;
483 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
484 | ENABLE_BITCODE = NO;
485 | INFOPLIST_FILE = Runner/Info.plist;
486 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
487 | PRODUCT_BUNDLE_IDENTIFIER = com.hamidwakili.anotherFlushbarExample;
488 | PRODUCT_NAME = "$(TARGET_NAME)";
489 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
490 | SWIFT_VERSION = 5.0;
491 | VERSIONING_SYSTEM = "apple-generic";
492 | };
493 | name = Release;
494 | };
495 | /* End XCBuildConfiguration section */
496 |
497 | /* Begin XCConfigurationList section */
498 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
499 | isa = XCConfigurationList;
500 | buildConfigurations = (
501 | 97C147031CF9000F007C117D /* Debug */,
502 | 97C147041CF9000F007C117D /* Release */,
503 | 249021D3217E4FDB00AE95B9 /* Profile */,
504 | );
505 | defaultConfigurationIsVisible = 0;
506 | defaultConfigurationName = Release;
507 | };
508 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
509 | isa = XCConfigurationList;
510 | buildConfigurations = (
511 | 97C147061CF9000F007C117D /* Debug */,
512 | 97C147071CF9000F007C117D /* Release */,
513 | 249021D4217E4FDB00AE95B9 /* Profile */,
514 | );
515 | defaultConfigurationIsVisible = 0;
516 | defaultConfigurationName = Release;
517 | };
518 | /* End XCConfigurationList section */
519 | };
520 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
521 | }
522 |
--------------------------------------------------------------------------------
/lib/flushbar.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:ui';
3 |
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter/scheduler.dart';
6 |
7 | import 'flushbar_route.dart' as route;
8 |
9 | // ignore: constant_identifier_names
10 | const String FLUSHBAR_ROUTE_NAME = '/flushbarRoute';
11 |
12 | typedef FlushbarStatusCallback = void Function(FlushbarStatus? status);
13 | typedef OnTap = void Function(Flushbar flushbar);
14 |
15 | /// A highly customizable widget so you can notify your user when you fell like he needs a beautiful explanation.
16 | // ignore: must_be_immutable
17 | class Flushbar extends StatefulWidget {
18 | Flushbar(
19 | {Key? key,
20 | this.title,
21 | this.titleColor,
22 | this.titleSize,
23 | this.message,
24 | this.messageSize,
25 | this.messageColor,
26 | this.titleText,
27 | this.messageText,
28 | this.icon,
29 | this.shouldIconPulse = true,
30 | this.maxWidth,
31 | this.margin = const EdgeInsets.all(0.0),
32 | this.padding = const EdgeInsets.all(16),
33 | this.borderRadius,
34 | this.textDirection = TextDirection.ltr,
35 | this.borderColor,
36 | this.borderWidth = 1.0,
37 | this.backgroundColor = const Color(0xFF303030),
38 | this.leftBarIndicatorColor,
39 | this.boxShadows,
40 | this.backgroundGradient,
41 | this.mainButton,
42 | this.onTap,
43 | this.duration,
44 | this.isDismissible = true,
45 | this.dismissDirection = FlushbarDismissDirection.VERTICAL,
46 | this.showProgressIndicator = false,
47 | this.progressIndicatorController,
48 | this.progressIndicatorBackgroundColor,
49 | this.progressIndicatorValueColor,
50 | this.flushbarPosition = FlushbarPosition.BOTTOM,
51 | this.positionOffset = 0.0,
52 | this.flushbarStyle = FlushbarStyle.FLOATING,
53 | this.forwardAnimationCurve = Curves.easeOutCirc,
54 | this.reverseAnimationCurve = Curves.easeOutCirc,
55 | this.animationDuration = const Duration(seconds: 1),
56 | FlushbarStatusCallback? onStatusChanged,
57 | this.barBlur = 0.0,
58 | this.blockBackgroundInteraction = false,
59 | this.routeBlur,
60 | this.routeColor,
61 | this.userInputForm,
62 | this.endOffset,
63 | this.flushbarRoute // Please dont init this
64 | })
65 | // ignore: prefer_initializing_formals
66 | : onStatusChanged = onStatusChanged,
67 | super(key: key) {
68 | onStatusChanged = onStatusChanged ?? (status) {};
69 | }
70 |
71 | /// A callback for you to listen to the different Flushbar status
72 | final FlushbarStatusCallback? onStatusChanged;
73 |
74 | /// The title displayed to the user
75 | final String? title;
76 |
77 | /// The title text size displayed to the user
78 | final double? titleSize;
79 |
80 | /// Color title displayed to the user ? default is black
81 | final Color? titleColor;
82 |
83 | /// The message displayed to the user.
84 | final String? message;
85 |
86 | /// The message text size displayed to the user.
87 | final double? messageSize;
88 |
89 | /// Color message displayed to the user ? default is black
90 | final Color? messageColor;
91 |
92 | /// Replaces [title]. Although this accepts a [Widget], it is meant to receive [Text] or [RichText]
93 | final Widget? titleText;
94 |
95 | /// Replaces [message]. Although this accepts a [Widget], it is meant to receive [Text] or [RichText]
96 | final Widget? messageText;
97 |
98 | /// Will be ignored if [backgroundGradient] is not null
99 | final Color backgroundColor;
100 |
101 | /// If not null, shows a left vertical bar to better indicate the humor of the notification.
102 | /// It is not possible to use it with a [Form] and I do not recommend using it with [LinearProgressIndicator]
103 | final Color? leftBarIndicatorColor;
104 |
105 | /// [boxShadows] The shadows generated by Flushbar. Leave it null if you don't want a shadow.
106 | /// You can use more than one if you feel the need.
107 | /// Check (this example)[https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/material/shadows.dart]
108 | final List? boxShadows;
109 |
110 | /// Makes [backgroundColor] be ignored.
111 | final Gradient? backgroundGradient;
112 |
113 | /// You can use any widget here, but I recommend [Icon] or [Image] as indication of what kind
114 | /// of message you are displaying. Other widgets may break the layout
115 | final Widget? icon;
116 |
117 | /// An option to animate the icon (if present). Defaults to true.
118 | final bool shouldIconPulse;
119 |
120 | /// Use if you need an action from the user. [TextButton] is recommended here
121 | final Widget? mainButton;
122 |
123 | /// A callback that registers the user's click anywhere. An alternative to [mainButton]
124 | final OnTap? onTap;
125 |
126 | /// How long until Flushbar will hide itself (be dismissed). To make it indefinite, leave it null.
127 | final Duration? duration;
128 |
129 | /// True if you want to show a [LinearProgressIndicator].
130 | /// If [progressIndicatorController] is null, an infinite progress indicator will be shown
131 | final bool showProgressIndicator;
132 |
133 | /// An optional [AnimationController] when you want to control the progress of your [LinearProgressIndicator].
134 | /// You are responsible for controlling the progress
135 | final AnimationController? progressIndicatorController;
136 |
137 | /// A [LinearProgressIndicator] configuration parameter.
138 | final Color? progressIndicatorBackgroundColor;
139 |
140 | /// A [LinearProgressIndicator] configuration parameter.
141 | final Animation? progressIndicatorValueColor;
142 |
143 | /// Determines if the user can swipe or click the overlay (if [routeBlur] > 0) to dismiss.
144 | /// It is recommended that you set [duration] != null if this is false.
145 | /// If the user swipes to dismiss or clicks the overlay, no value will be returned.
146 | final bool isDismissible;
147 |
148 | /// Used to limit Flushbar width (usually on large screens)
149 | final double? maxWidth;
150 |
151 | /// Adds a custom margin to Flushbar
152 | final EdgeInsets margin;
153 |
154 | /// Adds a custom padding to Flushbar
155 | /// The default follows material design guide line
156 | final EdgeInsets padding;
157 |
158 | /// Adds a radius to corners specified of Flushbar. Best combined with [margin].
159 | /// I do not recommend using it with [showProgressIndicator] or [leftBarIndicatorColor].
160 | final BorderRadius? borderRadius;
161 |
162 | /// [TextDirection.ltr] by default
163 | /// added to support rtl languages
164 | final TextDirection textDirection;
165 |
166 | // Adds a border to every side of Flushbar
167 | /// I do not recommend using it with [showProgressIndicator] or [leftBarIndicatorColor].
168 | final Color? borderColor;
169 |
170 | /// Changes the width of the border if [borderColor] is specified
171 | final double borderWidth;
172 |
173 | /// Flushbar can be based on [FlushbarPosition.TOP] or on [FlushbarPosition.BOTTOM] of your screen.
174 | /// [FlushbarPosition.BOTTOM] is the default.
175 | final FlushbarPosition flushbarPosition;
176 |
177 | final double positionOffset;
178 |
179 | /// [FlushbarDismissDirection.VERTICAL] by default.
180 | /// Can also be [FlushbarDismissDirection.HORIZONTAL] in which case both left and right dismiss are allowed.
181 | final FlushbarDismissDirection dismissDirection;
182 |
183 | /// Flushbar can be floating or be grounded to the edge of the screen.
184 | /// If grounded, I do not recommend using [margin] or [borderRadius]. [FlushbarStyle.FLOATING] is the default
185 | /// If grounded, I do not recommend using a [backgroundColor] with transparency or [barBlur]
186 | final FlushbarStyle flushbarStyle;
187 |
188 | /// The [Curve] animation used when show() is called. [Curves.easeOut] is default
189 | final Curve forwardAnimationCurve;
190 |
191 | /// The [Curve] animation used when dismiss() is called. [Curves.fastOutSlowIn] is default
192 | final Curve reverseAnimationCurve;
193 |
194 | /// Use it to speed up or slow down the animation duration
195 | final Duration animationDuration;
196 |
197 | /// Default is 0.0. If different than 0.0, blurs only Flushbar's background.
198 | /// To take effect, make sure your [backgroundColor] has some opacity.
199 | /// The greater the value, the greater the blur.
200 | final double barBlur;
201 |
202 | /// Determines if user can interact with the screen behind it
203 | /// If this is false, [routeBlur] and [routeColor] will be ignored
204 | final bool blockBackgroundInteraction;
205 |
206 | /// Default is 0.0. If different than 0.0, creates a blurred
207 | /// overlay that prevents the user from interacting with the screen.
208 | /// The greater the value, the greater the blur.
209 | /// It does not take effect if [blockBackgroundInteraction] is false
210 | final double? routeBlur;
211 |
212 | /// Default is [Colors.transparent]. Only takes effect if [routeBlur] > 0.0.
213 | /// Make sure you use a color with transparency here e.g. Colors.grey[600].withOpacity(0.2).
214 | /// It does not take effect if [blockBackgroundInteraction] is false
215 | final Color? routeColor;
216 |
217 | /// A [TextFormField] in case you want a simple user input. Every other widget is ignored if this is not null.
218 | final Form? userInputForm;
219 |
220 | /// Offset to be added to the end Flushbar position.
221 | /// Intended to replace [margin] when you need items below Flushbar to be accessible
222 | final Offset? endOffset;
223 |
224 | route.FlushbarRoute? flushbarRoute;
225 |
226 | /// Show the flushbar. Kicks in [FlushbarStatus.IS_APPEARING] state followed by [FlushbarStatus.SHOWING]
227 | Future show(BuildContext context) async {
228 | flushbarRoute = route.showFlushbar(
229 | context: context,
230 | flushbar: this,
231 | ) as route.FlushbarRoute;
232 |
233 | return await Navigator.of(context, rootNavigator: false)
234 | .push(flushbarRoute as Route);
235 | }
236 |
237 | /// Dismisses the flushbar causing is to return a future containing [result].
238 | /// When this future finishes, it is guaranteed that Flushbar was dismissed.
239 | Future dismiss([T? result]) async {
240 | // If route was never initialized, do nothing
241 | if (flushbarRoute == null) {
242 | return null;
243 | }
244 |
245 | if (flushbarRoute!.isCurrent) {
246 | flushbarRoute!.navigator!.pop(result);
247 | return flushbarRoute!.completed;
248 | } else if (flushbarRoute!.isActive) {
249 | // removeRoute is called every time you dismiss a Flushbar that is not the top route.
250 | // It will not animate back and listeners will not detect FlushbarStatus.IS_HIDING or FlushbarStatus.DISMISSED
251 | // To avoid this, always make sure that Flushbar is the top route when it is being dismissed
252 | flushbarRoute!.navigator!.removeRoute(flushbarRoute!);
253 | }
254 |
255 | return null;
256 | }
257 |
258 | /// Checks if the flushbar is visible
259 | bool isShowing() {
260 | if (flushbarRoute == null) {
261 | return false;
262 | }
263 | return flushbarRoute!.currentStatus == FlushbarStatus.SHOWING;
264 | }
265 |
266 | /// Checks if the flushbar is dismissed
267 | bool isDismissed() {
268 | if (flushbarRoute == null) {
269 | return false;
270 | }
271 | return flushbarRoute!.currentStatus == FlushbarStatus.DISMISSED;
272 | }
273 |
274 | bool isAppearing() {
275 | if (flushbarRoute == null) {
276 | return false;
277 | }
278 | return flushbarRoute!.currentStatus == FlushbarStatus.IS_APPEARING;
279 | }
280 |
281 | bool isHiding() {
282 | if (flushbarRoute == null) {
283 | return false;
284 | }
285 | return flushbarRoute!.currentStatus == FlushbarStatus.IS_HIDING;
286 | }
287 |
288 | @override
289 | State createState() => _FlushbarState();
290 | }
291 |
292 | class _FlushbarState extends State>
293 | with TickerProviderStateMixin {
294 | final Duration _pulseAnimationDuration = const Duration(seconds: 1);
295 | final Widget _emptyWidget = const SizedBox();
296 | final double _initialOpacity = 1.0;
297 | final double _finalOpacity = 0.4;
298 |
299 | GlobalKey? _backgroundBoxKey;
300 | FlushbarStatus? currentStatus;
301 | AnimationController? _fadeController;
302 | late Animation _fadeAnimation;
303 | late bool _isTitlePresent;
304 | late double _messageTopMargin;
305 | FocusScopeNode? _focusNode;
306 | late FocusAttachment _focusAttachment;
307 | late Completer _boxHeightCompleter;
308 |
309 | CurvedAnimation? _progressAnimation;
310 |
311 | @override
312 | void initState() {
313 | super.initState();
314 |
315 | _backgroundBoxKey = GlobalKey();
316 | _boxHeightCompleter = Completer();
317 |
318 | assert(
319 | widget.userInputForm != null ||
320 | ((widget.message != null && widget.message!.isNotEmpty) ||
321 | widget.messageText != null),
322 | 'A message is mandatory if you are not using userInputForm. Set either a message or messageText');
323 |
324 | _isTitlePresent = (widget.title != null || widget.titleText != null);
325 | _messageTopMargin = _isTitlePresent ? 6.0 : widget.padding.top;
326 |
327 | _configureLeftBarFuture();
328 | _configureProgressIndicatorAnimation();
329 |
330 | if (widget.icon != null && widget.shouldIconPulse) {
331 | _configurePulseAnimation();
332 | _fadeController?.forward();
333 | }
334 |
335 | _focusNode = FocusScopeNode();
336 | _focusAttachment = _focusNode!.attach(context);
337 | }
338 |
339 | @override
340 | void dispose() {
341 | _fadeController?.dispose();
342 | widget.progressIndicatorController?.dispose();
343 |
344 | _focusAttachment.detach();
345 | _focusNode!.dispose();
346 | super.dispose();
347 | }
348 |
349 | void _configureLeftBarFuture() {
350 | SchedulerBinding.instance.addPostFrameCallback(
351 | (_) {
352 | final keyContext = _backgroundBoxKey!.currentContext;
353 |
354 | if (keyContext != null) {
355 | final box = keyContext.findRenderObject() as RenderBox;
356 | _boxHeightCompleter.complete(box.size);
357 | }
358 | },
359 | );
360 | }
361 |
362 | void _configureProgressIndicatorAnimation() {
363 | if (widget.showProgressIndicator &&
364 | widget.progressIndicatorController != null) {
365 | _progressAnimation = CurvedAnimation(
366 | curve: Curves.linear, parent: widget.progressIndicatorController!);
367 | }
368 | }
369 |
370 | void _configurePulseAnimation() {
371 | _fadeController =
372 | AnimationController(vsync: this, duration: _pulseAnimationDuration);
373 | _fadeAnimation = Tween(begin: _initialOpacity, end: _finalOpacity).animate(
374 | CurvedAnimation(
375 | parent: _fadeController!,
376 | curve: Curves.linear,
377 | ),
378 | );
379 |
380 | _fadeController!.addStatusListener((status) {
381 | if (status == AnimationStatus.completed) {
382 | _fadeController!.reverse();
383 | }
384 | if (status == AnimationStatus.dismissed) {
385 | _fadeController!.forward();
386 | }
387 | });
388 |
389 | _fadeController!.forward();
390 | }
391 |
392 | //TODO : review EdgeInsets
393 | @override
394 | Widget build(BuildContext context) {
395 | return Align(
396 | heightFactor: 1.0,
397 | child: Material(
398 | color: widget.flushbarStyle == FlushbarStyle.FLOATING
399 | ? Colors.transparent
400 | : widget.backgroundColor,
401 | child: SafeArea(
402 | minimum: widget.flushbarPosition == FlushbarPosition.BOTTOM
403 | ? EdgeInsets.only(
404 | bottom: MediaQuery.of(context).viewInsets.bottom)
405 | : EdgeInsets.only(top: MediaQuery.of(context).viewInsets.top),
406 | // ? EdgeInsets.only(
407 | // bottom: (MediaQuery.of(context).padding.bottom +
408 | // widget.positionOffset))
409 | // : EdgeInsets.only(
410 | // top: (MediaQuery.of(context).padding.top) +
411 | // widget.positionOffset),
412 | bottom: widget.flushbarPosition == FlushbarPosition.BOTTOM,
413 | top: widget.flushbarPosition == FlushbarPosition.TOP,
414 | left: false,
415 | right: false,
416 | child: _getFlushbar(),
417 | ),
418 | ),
419 | );
420 | }
421 |
422 | Widget _getFlushbar() {
423 | Widget flushbar;
424 |
425 | if (widget.userInputForm != null) {
426 | flushbar = _generateInputFlushbar();
427 | } else {
428 | flushbar = _generateFlushbar();
429 | }
430 |
431 | return Stack(
432 | children: [
433 | FutureBuilder(
434 | future: _boxHeightCompleter.future,
435 | builder: (context, AsyncSnapshot snapshot) {
436 | if (snapshot.hasData) {
437 | if (widget.barBlur == 0) {
438 | //fixes https://github.com/cmdrootaccess/another-flushbar/issues/8
439 | return _emptyWidget;
440 | }
441 | return ClipRRect(
442 | borderRadius: widget.borderRadius,
443 | child: BackdropFilter(
444 | filter: ImageFilter.blur(
445 | sigmaX: widget.barBlur, sigmaY: widget.barBlur),
446 | child: Container(
447 | height: snapshot.data!.height,
448 | width: snapshot.data!.width,
449 | decoration: BoxDecoration(
450 | color: Colors.transparent,
451 | borderRadius: widget.borderRadius,
452 | ),
453 | ),
454 | ),
455 | );
456 | }
457 | return _emptyWidget;
458 | },
459 | ),
460 | flushbar,
461 | ],
462 | );
463 | }
464 |
465 | Widget _generateInputFlushbar() {
466 | return Container(
467 | key: _backgroundBoxKey,
468 | constraints: widget.maxWidth != null
469 | ? BoxConstraints(maxWidth: widget.maxWidth!)
470 | : null,
471 | decoration: BoxDecoration(
472 | color: widget.backgroundColor,
473 | gradient: widget.backgroundGradient,
474 | boxShadow: widget.boxShadows,
475 | borderRadius: widget.borderRadius,
476 | border: widget.borderColor != null
477 | ? Border.all(color: widget.borderColor!, width: widget.borderWidth)
478 | : null,
479 | ),
480 | child: Padding(
481 | padding: const EdgeInsets.only(
482 | left: 8.0, right: 8.0, bottom: 8.0, top: 16.0),
483 | child: FocusScope(
484 | node: _focusNode,
485 | autofocus: true,
486 | child: widget.userInputForm!,
487 | ),
488 | ),
489 | );
490 | }
491 |
492 | Widget _generateFlushbar() {
493 | return Container(
494 | key: _backgroundBoxKey,
495 | constraints: widget.maxWidth != null
496 | ? BoxConstraints(maxWidth: widget.maxWidth!)
497 | : null,
498 | decoration: BoxDecoration(
499 | color: widget.backgroundColor,
500 | gradient: widget.backgroundGradient,
501 | boxShadow: widget.boxShadows,
502 | borderRadius: widget.borderRadius,
503 | border: widget.borderColor != null
504 | ? Border.all(color: widget.borderColor!, width: widget.borderWidth)
505 | : null,
506 | ),
507 | child: Column(
508 | mainAxisSize: MainAxisSize.min,
509 | children: [
510 | _buildProgressIndicator(),
511 | Row(
512 | mainAxisSize: MainAxisSize.max,
513 | children: _getAppropriateRowLayout(),
514 | ),
515 | ],
516 | ),
517 | );
518 | }
519 |
520 | Widget _buildProgressIndicator() {
521 | if (widget.showProgressIndicator && _progressAnimation != null) {
522 | return AnimatedBuilder(
523 | animation: _progressAnimation!,
524 | builder: (_, __) {
525 | return LinearProgressIndicator(
526 | value: _progressAnimation!.value,
527 | backgroundColor: widget.progressIndicatorBackgroundColor,
528 | valueColor: widget.progressIndicatorValueColor,
529 | );
530 | });
531 | }
532 |
533 | if (widget.showProgressIndicator) {
534 | return LinearProgressIndicator(
535 | backgroundColor: widget.progressIndicatorBackgroundColor,
536 | valueColor: widget.progressIndicatorValueColor,
537 | );
538 | }
539 |
540 | return _emptyWidget;
541 | }
542 |
543 | List _getAppropriateRowLayout() {
544 | double buttonRightPadding;
545 | var iconPadding = 0.0;
546 | if (widget.padding.right - 12 < 0) {
547 | buttonRightPadding = 4;
548 | } else {
549 | buttonRightPadding = widget.padding.right - 12;
550 | }
551 |
552 | if (widget.padding.left > 16.0) {
553 | iconPadding = widget.padding.left;
554 | }
555 |
556 | if (widget.icon == null && widget.mainButton == null) {
557 | return [
558 | _buildLeftBarIndicator(),
559 | Expanded(
560 | flex: 1,
561 | child: Column(
562 | crossAxisAlignment: CrossAxisAlignment.stretch,
563 | mainAxisSize: MainAxisSize.min,
564 | children: [
565 | (_isTitlePresent)
566 | ? Padding(
567 | padding: EdgeInsets.only(
568 | top: widget.padding.top,
569 | left: widget.padding.left,
570 | right: widget.padding.right,
571 | ),
572 | child: _getTitleText(),
573 | )
574 | : _emptyWidget,
575 | Padding(
576 | padding: EdgeInsets.only(
577 | top: _messageTopMargin,
578 | left: widget.padding.left,
579 | right: widget.padding.right,
580 | bottom: widget.padding.bottom,
581 | ),
582 | child: widget.messageText ?? _getDefaultNotificationText(),
583 | ),
584 | ],
585 | ),
586 | ),
587 | ];
588 | } else if (widget.icon != null && widget.mainButton == null) {
589 | return [
590 | _buildLeftBarIndicator(),
591 | ConstrainedBox(
592 | constraints: BoxConstraints.tightFor(width: 42.0 + iconPadding),
593 | child: _getIcon(),
594 | ),
595 | Expanded(
596 | flex: 1,
597 | child: Column(
598 | crossAxisAlignment: CrossAxisAlignment.stretch,
599 | mainAxisSize: MainAxisSize.min,
600 | children: [
601 | (_isTitlePresent)
602 | ? Padding(
603 | padding: EdgeInsets.only(
604 | top: widget.padding.top,
605 | left: 4.0,
606 | right: widget.padding.left,
607 | ),
608 | child: _getTitleText(),
609 | )
610 | : _emptyWidget,
611 | Padding(
612 | padding: EdgeInsets.only(
613 | top: _messageTopMargin,
614 | left: 4.0,
615 | right: widget.padding.right,
616 | bottom: widget.padding.bottom,
617 | ),
618 | child: widget.messageText ?? _getDefaultNotificationText(),
619 | ),
620 | ],
621 | ),
622 | ),
623 | ];
624 | } else if (widget.icon == null && widget.mainButton != null) {
625 | return [
626 | _buildLeftBarIndicator(),
627 | Expanded(
628 | flex: 1,
629 | child: Column(
630 | crossAxisAlignment: CrossAxisAlignment.stretch,
631 | mainAxisSize: MainAxisSize.min,
632 | children: [
633 | (_isTitlePresent)
634 | ? Padding(
635 | padding: EdgeInsets.only(
636 | top: widget.padding.top,
637 | left: widget.padding.left,
638 | right: widget.padding.right,
639 | ),
640 | child: _getTitleText(),
641 | )
642 | : _emptyWidget,
643 | Padding(
644 | padding: EdgeInsets.only(
645 | top: _messageTopMargin,
646 | left: widget.padding.left,
647 | right: 8.0,
648 | bottom: widget.padding.bottom,
649 | ),
650 | child: widget.messageText ?? _getDefaultNotificationText(),
651 | ),
652 | ],
653 | ),
654 | ),
655 | Padding(
656 | padding: EdgeInsets.only(right: buttonRightPadding),
657 | child: _getMainActionButton(),
658 | ),
659 | ];
660 | } else {
661 | return [
662 | _buildLeftBarIndicator(),
663 | ConstrainedBox(
664 | constraints: BoxConstraints.tightFor(width: 42.0 + iconPadding),
665 | child: _getIcon(),
666 | ),
667 | Expanded(
668 | flex: 1,
669 | child: Column(
670 | crossAxisAlignment: CrossAxisAlignment.stretch,
671 | mainAxisSize: MainAxisSize.min,
672 | children: [
673 | (_isTitlePresent)
674 | ? Padding(
675 | padding: EdgeInsets.only(
676 | top: widget.padding.top,
677 | left: 4.0,
678 | right: 8.0,
679 | ),
680 | child: _getTitleText(),
681 | )
682 | : _emptyWidget,
683 | Padding(
684 | padding: EdgeInsets.only(
685 | top: _messageTopMargin,
686 | left: 4.0,
687 | right: 8.0,
688 | bottom: widget.padding.bottom,
689 | ),
690 | child: widget.messageText ?? _getDefaultNotificationText(),
691 | ),
692 | ],
693 | ),
694 | ),
695 | _getMainActionButton() != null
696 | ? Padding(
697 | padding: EdgeInsets.only(right: buttonRightPadding),
698 | child: _getMainActionButton(),
699 | )
700 | : _emptyWidget,
701 | ];
702 | }
703 | }
704 |
705 | Widget _buildLeftBarIndicator() {
706 | if (widget.leftBarIndicatorColor != null) {
707 | return FutureBuilder(
708 | future: _boxHeightCompleter.future,
709 | builder: (BuildContext buildContext, AsyncSnapshot snapshot) {
710 | if (snapshot.hasData) {
711 | return Container(
712 | width: 8.0,
713 | height: snapshot.data!.height,
714 | decoration: BoxDecoration(
715 | borderRadius: widget.borderRadius == null
716 | ? null
717 | : widget.textDirection == TextDirection.ltr
718 | ? BorderRadius.only(
719 | topLeft: widget.borderRadius!.topLeft,
720 | bottomLeft: widget.borderRadius!.bottomLeft)
721 | : BorderRadius.only(
722 | topRight: widget.borderRadius!.topRight,
723 | bottomRight: widget.borderRadius!.bottomRight),
724 | color: widget.leftBarIndicatorColor,
725 | ),
726 | );
727 | } else {
728 | return _emptyWidget;
729 | }
730 | },
731 | );
732 | } else {
733 | return _emptyWidget;
734 | }
735 | }
736 |
737 | Widget? _getIcon() {
738 | if (widget.icon != null && widget.icon is Icon && widget.shouldIconPulse) {
739 | return FadeTransition(
740 | opacity: _fadeAnimation,
741 | child: widget.icon,
742 | );
743 | } else if (widget.icon != null) {
744 | return widget.icon;
745 | } else {
746 | return _emptyWidget;
747 | }
748 | }
749 |
750 | Widget? _getTitleText() {
751 | return widget.titleText ??
752 | Text(
753 | widget.title ?? '',
754 | style: TextStyle(
755 | fontSize: widget.titleSize ?? 16.0,
756 | color: widget.titleColor ?? Colors.white,
757 | fontWeight: FontWeight.bold),
758 | );
759 | }
760 |
761 | Text _getDefaultNotificationText() {
762 | return Text(
763 | widget.message ?? '',
764 | style: TextStyle(
765 | fontSize: widget.messageSize ?? 14.0,
766 | color: widget.messageColor ?? Colors.white),
767 | );
768 | }
769 |
770 | Widget? _getMainActionButton() {
771 | if (widget.mainButton != null) {
772 | return widget.mainButton;
773 | } else {
774 | return null;
775 | }
776 | }
777 | }
778 |
779 | /// Indicates if flushbar is going to start at the [TOP] or at the [BOTTOM]
780 | enum FlushbarPosition { TOP, BOTTOM }
781 |
782 | /// Indicates if flushbar will be attached to the edge of the screen or not
783 | enum FlushbarStyle { FLOATING, GROUNDED }
784 |
785 | /// Indicates the direction in which it is possible to dismiss
786 | /// If vertical, dismiss up will be allowed if [FlushbarPosition.TOP]
787 | /// If vertical, dismiss down will be allowed if [FlushbarPosition.BOTTOM]
788 | enum FlushbarDismissDirection { HORIZONTAL, VERTICAL }
789 |
790 | /// Indicates the animation status
791 | /// [FlushbarStatus.SHOWING] Flushbar has stopped and the user can see it
792 | /// [FlushbarStatus.DISMISSED] Flushbar has finished its mission and returned any pending values
793 | /// [FlushbarStatus.IS_APPEARING] Flushbar is moving towards [FlushbarStatus.SHOWING]
794 | /// [FlushbarStatus.IS_HIDING] Flushbar is moving towards [] [FlushbarStatus.DISMISSED]
795 | enum FlushbarStatus { SHOWING, DISMISSED, IS_APPEARING, IS_HIDING }
796 |
--------------------------------------------------------------------------------