├── .gitignore ├── .metadata ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── example ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── prabhanu │ │ │ │ │ └── chat_bubble_example │ │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── 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 │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── 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-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── main.m ├── lib │ └── main.dart ├── pubspec.lock ├── pubspec.yaml └── test │ └── widget_test.dart ├── images ├── logo │ └── logo.png ├── messages │ └── img1.png └── screenshots │ ├── 2022_12_29_main1.jpg │ ├── 2022_12_29_main2.jpg │ ├── 2022_2_4_main1.png │ ├── 2022_2_4_main2.png │ ├── 2022_7_3_main1.png │ ├── 2022_7_3_main2.png │ ├── audio_bubble.png │ ├── datechip.png │ ├── image_bubble.jpg │ ├── imsg.png │ ├── imsg1.png │ ├── messagebar.jpeg │ ├── screenshot_1.png │ ├── screenshot_1_old.png │ ├── screenshot_2.png │ ├── screenshot_2_old.png │ ├── screenshot_3_old.png │ ├── screenshot_4_old.png │ └── single_bubble.png ├── lib ├── algo │ ├── algo.dart │ └── date_chip_text.dart ├── bubbles │ ├── bubble_normal.dart │ ├── bubble_normal_audio.dart │ ├── bubble_normal_image.dart │ ├── bubble_special_one.dart │ ├── bubble_special_three.dart │ └── bubble_special_two.dart ├── chat_bubbles.dart ├── date_chips │ └── date_chip.dart └── message_bars │ └── message_bar.dart ├── pubspec.lock ├── pubspec.yaml └── test └── chatbubbles_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | .fvm/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | build/ 33 | 34 | 35 | 36 | # Android related 37 | **/android/**/gradle-wrapper.jar 38 | **/android/.gradle 39 | **/android/captures/ 40 | **/android/gradlew 41 | **/android/gradlew.bat 42 | **/android/local.properties 43 | **/android/**/GeneratedPluginRegistrant.java 44 | 45 | # iOS/XCode related 46 | **/ios/**/*.mode1v3 47 | **/ios/**/*.mode2v3 48 | **/ios/**/*.moved-aside 49 | **/ios/**/*.pbxuser 50 | **/ios/**/*.perspectivev3 51 | **/ios/**/*sync/ 52 | **/ios/**/.sconsign.dblite 53 | **/ios/**/.tags* 54 | **/ios/**/.vagrant/ 55 | **/ios/**/DerivedData/ 56 | **/ios/**/Icon? 57 | **/ios/**/Pods/ 58 | **/ios/**/.symlinks/ 59 | **/ios/**/profile 60 | **/ios/**/xcuserdata 61 | **/ios/.generated/ 62 | **/ios/Flutter/App.framework 63 | **/ios/Flutter/Flutter.framework 64 | **/ios/Flutter/Flutter.podspec 65 | **/ios/Flutter/Generated.xcconfig 66 | **/ios/Flutter/app.flx 67 | **/ios/Flutter/app.zip 68 | **/ios/Flutter/flutter_assets/ 69 | **/ios/Flutter/flutter_export_environment.sh 70 | **/ios/ServiceDefinitions.json 71 | **/ios/Runner/GeneratedPluginRegistrant.* 72 | 73 | # Exceptions to above rules. 74 | !**/ios/**/default.mode1v3 75 | !**/ios/**/default.mode2v3 76 | !**/ios/**/default.pbxuser 77 | !**/ios/**/default.perspectivev3 78 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 79 | -------------------------------------------------------------------------------- /.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: 0b8abb4724aa590dd0f429683339b1e045a1594d 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.7.0] - 05/01/2025 2 | 3 | * support up-to-date dependencies 4 | * update the example 5 | * update the documentation 6 | 7 | ## [1.6.0] - 20/01/2024 8 | 9 | ### For Message Bar 10 | * Customizable text style for message bar text 11 | 12 | ### For BubbleNormal Widget 13 | 14 | * Added optional [leading] widget for _non senders_ 15 | * Added optional [trailing] widget for _sender_ 16 | * Added [margin] and [padding] properties 17 | * Added tap callbacks such as [onTap], [onDoubleTap] and [onLongPress]. 18 | * Changes the texts to selectable texts 19 | 20 | ### For BubbleNormalImage Widget 21 | 22 | BubbleNormalImage Widget- 23 | * Added optional [leading] widget for _non senders_ 24 | * Added optional [trailing] widget for _sender_ 25 | * Added [margin] and [padding] parameters 26 | * Added Tap Callbacks such as [onTap] and [onLongPress]. 27 | 28 | ### For DateChip Widget 29 | * Fixes [DateChip] taking full width 30 | 31 | ### Other 32 | * Updated the environment to allow support for latest dart sdks 33 | * Updated the documentation within code to be easier to read 34 | 35 | ## [1.5.0] - 11/08/2023 36 | 37 | * Customizable constrains for bubbles 38 | * Customizable message bar hint text 39 | * Customizable message bar hint style 40 | * Update the example 41 | 42 | ## [1.4.1] - 26/01/2023 43 | 44 | * Support up-to-date dependencies 45 | 46 | ## [1.4.0] - 29/12/2022 47 | 48 | * Add `BubbleNormalImage` image chat bubble widget 49 | 50 | ## [1.3.1] - 16/08/2022 51 | 52 | * Support up-to-date dependencies 53 | 54 | ## [1.3.0] - 03/07/2022 55 | 56 | * Add `MessageBar` widget 57 | 58 | ## [1.2.0] - 04/02/2022 59 | 60 | * Add iMessage's chat bubble shape bubble widget (`BubbleSpecialThree`). 61 | 62 | ## [1.1.0] - 27/06/2021 63 | 64 | * Audio chat bubble widget(`BubbleNormalAudio`) for the bubble normal widget set. 65 | 66 | ## [1.0.0+3] - 16/05/2021 67 | 68 | * Update `README` main example code. 69 | 70 | ## [1.0.0+2] - 15/05/2021 71 | 72 | * dartfmt formatting. 73 | 74 | ## [1.0.0+1] - 15/05/2021 75 | 76 | * dartfmt formatting. 77 | 78 | ## [1.0.0] - 15/05/2021 79 | 80 | * Add `DateChip` widget 81 | 82 | ## [0.8.1] - 26/04/2021 83 | 84 | * set priority for message status tick (seen > delivered > sent) 85 | 86 | ## [0.8.0+1] - 22/03/2021 87 | 88 | * Update README.md example. 89 | 90 | ## [0.8.0] - 15/03/2021 91 | 92 | * Add the option to customize the chat bubble text styles by changing `textStyle` parameter 93 | 94 | ## [0.7.9+3] - 10/03/2021 95 | 96 | * null-safety. 97 | 98 | ## [0.7.8+2] - 21/10/2020 99 | 100 | * dartfmt formatting. 101 | 102 | ## [0.7.8+1] - 20/07/2020 103 | 104 | * Update README.md example. 105 | 106 | ## [0.7.8] - 20/07/2020 107 | 108 | * Add message states(sent, delivered, seen) flag for BubbleSpecialOne and BubbleSpecialTwo. 109 | * Update the example. 110 | 111 | ## [0.7.5+1] - 18/07/2020 112 | 113 | * Add some dartdoc comments. 114 | 115 | ## [0.7.5] - 21/06/2020 116 | 117 | * Add message states(sent, delivered, seen) flag for BubbleNormal. 118 | * Update the example. 119 | 120 | ## [0.7.1+6] - 17/05/2020 121 | 122 | * Update the example. 123 | 124 | ## [0.7.1+5] - 10/05/2020 125 | 126 | * Update README.md file. 127 | 128 | ## [0.7.1+4] - 10/05/2020 129 | 130 | * Update package description. 131 | 132 | ## [0.7.1+3] - 09/05/2020 133 | 134 | * Update package description. 135 | 136 | ## [0.7.1+2] - 09/05/2020 137 | 138 | * Update package description. 139 | 140 | ## [0.7.1+1] - 09/05/2020 141 | 142 | * Update package description. 143 | 144 | ## [0.7.1] - 09/05/2020 145 | 146 | * Update package description. 147 | 148 | ## [0.7.0] - 09/05/2020 149 | 150 | * First release with an example. 151 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | prabhanu96@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributor Guidelines 2 | 3 | Thank you for your interest in contributing to our Flutter plugin! We welcome all contributions, whether it's filing an issue, creating a pull request, or helping other community members with their questions. To ensure a positive and productive experience for everyone, please review the following guidelines before contributing. 4 | 5 | ## Issues 6 | 7 | If you find a bug or have a feature request, please create an issue in the GitHub repository. Before creating an issue, please search for existing issues to avoid creating duplicates. When creating a new issue, please provide the following information: 8 | 9 | - A clear and descriptive title 10 | - A detailed description of the issue, including any error messages or stack traces 11 | - Steps to reproduce the issue 12 | - Expected behavior 13 | - Any additional information or screenshots that can help us understand the issue better 14 | 15 | ## Pull Requests 16 | 17 | We welcome pull requests from contributors of all skill levels. Before creating a pull request, please make sure that: 18 | 19 | - The code follows our [coding standards](#coding-standards). 20 | - All tests pass locally. 21 | - The pull request has a clear and descriptive title. 22 | - The pull request includes a detailed description of the changes made. 23 | - The pull request includes any necessary documentation changes. 24 | 25 | ## Coding Standards 26 | 27 | To maintain consistency and readability, we follow the [Flutter Style Guide](https://flutter.dev/docs/development/style-guide). Please make sure that your code follows these guidelines before submitting a pull request. 28 | 29 | ## License 30 | 31 | By contributing to this project, you agree that your contributions will be licensed under the [MIT License](LICENSE). 32 | 33 | ## Attribution 34 | 35 | This contributor guidelines document is adapted from the [Atom Contributor Guidelines](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). 36 | 37 | ## Conclusion 38 | 39 | We value your contributions and look forward to working with you! If you have any questions, please do not hesitate to reach out to the project team or community members for help. 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Prabhanu Gunaweera 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chat_bubbles plugin 2 | 3 | ![Pub Version](https://img.shields.io/pub/v/chat_bubbles?color=blue) 4 | ![GitHub](https://img.shields.io/github/license/prahack/chat_bubbles) 5 | ![GitHub forks](https://img.shields.io/github/forks/prahack/chat_bubbles) 6 | ![GitHub Repo stars](https://img.shields.io/github/stars/prahack/chat_bubbles) 7 | ![GitHub last commit](https://img.shields.io/github/last-commit/prahack/chat_bubbles) 8 | ![likes](https://img.shields.io/pub/likes/chat_bubbles?logo=dart) 9 | ![popularity](https://img.shields.io/pub/popularity/chat_bubbles?logo=dart) 10 | ![pub points](https://img.shields.io/pub/points/chat_bubbles?logo=dart) 11 | 12 | Flutter chat bubble widgets, similar to the Whatsapp and more shapes. Audio and Image chat bubble widgets are also included. Easy to use and implement chat bubbles. 13 | 14 | ## Getting Started 15 | 16 | Add this to your package's `pubspec.yaml` file: 17 | 18 | ```yaml 19 | dependencies: 20 | chat_bubbles: ^1.7.0 21 | ``` 22 | 23 | ## Usage 24 | 25 | Then you just have to import the package with 26 | 27 | ```dart 28 | import 'package:chat_bubbles/chat_bubbles.dart' 29 | ``` 30 | 31 | Now you can use this plugin to implement various types of Chat Bubbles, Audio Chat Bubbles and Date chips. 32 | 33 | ## Examples 34 | 35 | ### iMessage's bubble example 36 | 37 | 38 | 39 | ```dart 40 | BubbleSpecialThree( 41 | text: 'Added iMessage shape bubbles', 42 | color: Color(0xFF1B97F3), 43 | tail: false, 44 | textStyle: TextStyle( 45 | color: Colors.white, 46 | fontSize: 16 47 | ), 48 | ), 49 | BubbleSpecialThree( 50 | text: 'Please try and give some feedback on it!', 51 | color: Color(0xFF1B97F3), 52 | tail: true, 53 | textStyle: TextStyle( 54 | color: Colors.white, 55 | fontSize: 16 56 | ), 57 | ), 58 | BubbleSpecialThree( 59 | text: 'Sure', 60 | color: Color(0xFFE8E8EE), 61 | tail: false, 62 | isSender: false, 63 | ), 64 | BubbleSpecialThree( 65 | text: "I tried. It's awesome!!!", 66 | color: Color(0xFFE8E8EE), 67 | tail: false, 68 | isSender: false, 69 | ), 70 | BubbleSpecialThree( 71 | text: "Thanks", 72 | color: Color(0xFFE8E8EE), 73 | tail: true, 74 | isSender: false, 75 | ) 76 | ``` 77 | 78 | ### Single bubble example 79 | 80 | 81 | 82 | 83 | ```dart 84 | BubbleSpecialOne( 85 | text: 'Hi, How are you? ', 86 | isSender: false, 87 | color: Colors.purple.shade100, 88 | textStyle: TextStyle( 89 | fontSize: 20, 90 | color: Colors.purple, 91 | fontStyle: FontStyle.italic, 92 | fontWeight: FontWeight.bold, 93 | ), 94 | ), 95 | ``` 96 | 97 | ### Audio chat bubble example 98 | 99 | 100 | 101 | ```dart 102 | Duration duration = new Duration(); 103 | Duration position = new Duration(); 104 | bool isPlaying = false; 105 | bool isLoading = false; 106 | bool isPause = false; 107 | 108 | BubbleNormalAudio( 109 | color: Color(0xFFE8E8EE), 110 | duration: duration.inSeconds.toDouble(), 111 | position: position.inSeconds.toDouble(), 112 | isPlaying: isPlaying, 113 | isLoading: isLoading, 114 | isPause: isPause, 115 | onSeekChanged: _changeSeek, 116 | onPlayPauseButtonClick: _playAudio, 117 | sent: true, 118 | ), 119 | ``` 120 | 121 | ### Image chat bubble example 122 | 123 | 124 | 125 | ```dart 126 | BubbleNormalImage( 127 | id: 'id001', 128 | image: _image(), 129 | color: Colors.purpleAccent, 130 | tail: true, 131 | delivered: true, 132 | ), 133 | ``` 134 | 135 | ### Date Chip example 136 | 137 | 138 | 139 | ```dart 140 | DateChip( 141 | date: new DateTime(2021, 5, 7), 142 | color: Color(0x558AD3D5), 143 | ), 144 | ``` 145 | 146 | ### Message bar example 147 | 148 | 149 | 150 | ```dart 151 | MessageBar( 152 | onSend: (_) => print(_), 153 | actions: [ 154 | InkWell( 155 | child: Icon( 156 | Icons.add, 157 | color: Colors.black, 158 | size: 24, 159 | ), 160 | onTap: () {}, 161 | ), 162 | Padding( 163 | padding: EdgeInsets.only(left: 8, right: 8), 164 | child: InkWell( 165 | child: Icon( 166 | Icons.camera_alt, 167 | color: Colors.green, 168 | size: 24, 169 | ), 170 | onTap: () {}, 171 | ), 172 | ), 173 | ], 174 | ), 175 | ``` 176 | 177 | ### Main example (Chat View) 178 | 179 | 180 | Checkout the plugin example to figure out more. 181 | 182 | ```dart 183 | Duration duration = new Duration(); 184 | Duration position = new Duration(); 185 | bool isPlaying = false; 186 | bool isLoading = false; 187 | bool isPause = false; 188 | 189 | @override 190 | Widget build(BuildContext context) { 191 | final now = new DateTime.now(); 192 | return Scaffold( 193 | appBar: AppBar( 194 | title: Text(widget.title), 195 | ), 196 | body: Stack( 197 | children: [ 198 | SingleChildScrollView( 199 | child: Column( 200 | children: [ 201 | BubbleNormalImage( 202 | id: 'id001', 203 | image: _image(), 204 | color: Colors.purpleAccent, 205 | tail: true, 206 | delivered: true, 207 | ), 208 | BubbleNormalAudio( 209 | color: Color(0xFFE8E8EE), 210 | duration: duration.inSeconds.toDouble(), 211 | position: position.inSeconds.toDouble(), 212 | isPlaying: isPlaying, 213 | isLoading: isLoading, 214 | isPause: isPause, 215 | onSeekChanged: _changeSeek, 216 | onPlayPauseButtonClick: _playAudio, 217 | sent: true, 218 | ), 219 | BubbleNormal( 220 | text: 'bubble normal with tail', 221 | isSender: false, 222 | color: Color(0xFF1B97F3), 223 | tail: true, 224 | textStyle: TextStyle( 225 | fontSize: 20, 226 | color: Colors.white, 227 | ), 228 | ), 229 | BubbleNormal( 230 | text: 'bubble normal with tail', 231 | isSender: true, 232 | color: Color(0xFFE8E8EE), 233 | tail: true, 234 | sent: true, 235 | ), 236 | DateChip( 237 | date: new DateTime(now.year, now.month, now.day - 2), 238 | ), 239 | BubbleNormal( 240 | text: 'bubble normal without tail', 241 | isSender: false, 242 | color: Color(0xFF1B97F3), 243 | tail: false, 244 | textStyle: TextStyle( 245 | fontSize: 20, 246 | color: Colors.white, 247 | ), 248 | ), 249 | BubbleNormal( 250 | text: 'bubble normal without tail', 251 | color: Color(0xFFE8E8EE), 252 | tail: false, 253 | sent: true, 254 | seen: true, 255 | delivered: true, 256 | ), 257 | BubbleSpecialOne( 258 | text: 'bubble special one with tail', 259 | isSender: false, 260 | color: Color(0xFF1B97F3), 261 | textStyle: TextStyle( 262 | fontSize: 20, 263 | color: Colors.white, 264 | ), 265 | ), 266 | DateChip( 267 | date: new DateTime(now.year, now.month, now.day - 1), 268 | ), 269 | BubbleSpecialOne( 270 | text: 'bubble special one with tail', 271 | color: Color(0xFFE8E8EE), 272 | seen: true, 273 | ), 274 | BubbleSpecialOne( 275 | text: 'bubble special one without tail', 276 | isSender: false, 277 | tail: false, 278 | color: Color(0xFF1B97F3), 279 | textStyle: TextStyle( 280 | fontSize: 20, 281 | color: Colors.black, 282 | ), 283 | ), 284 | BubbleSpecialOne( 285 | text: 'bubble special one without tail', 286 | tail: false, 287 | color: Color(0xFFE8E8EE), 288 | sent: true, 289 | ), 290 | BubbleSpecialTwo( 291 | text: 'bubble special tow with tail', 292 | isSender: false, 293 | color: Color(0xFF1B97F3), 294 | textStyle: TextStyle( 295 | fontSize: 20, 296 | color: Colors.black, 297 | ), 298 | ), 299 | DateChip( 300 | date: now, 301 | ), 302 | BubbleSpecialTwo( 303 | text: 'bubble special tow with tail', 304 | isSender: true, 305 | color: Color(0xFFE8E8EE), 306 | sent: true, 307 | ), 308 | BubbleSpecialTwo( 309 | text: 'bubble special tow without tail', 310 | isSender: false, 311 | tail: false, 312 | color: Color(0xFF1B97F3), 313 | textStyle: TextStyle( 314 | fontSize: 20, 315 | color: Colors.black, 316 | ), 317 | ), 318 | BubbleSpecialTwo( 319 | text: 'bubble special tow without tail', 320 | tail: false, 321 | color: Color(0xFFE8E8EE), 322 | delivered: true, 323 | ), 324 | BubbleSpecialThree( 325 | text: 'bubble special three without tail', 326 | color: Color(0xFF1B97F3), 327 | tail: false, 328 | textStyle: TextStyle(color: Colors.white, fontSize: 16), 329 | ), 330 | BubbleSpecialThree( 331 | text: 'bubble special three with tail', 332 | color: Color(0xFF1B97F3), 333 | tail: true, 334 | textStyle: TextStyle(color: Colors.white, fontSize: 16), 335 | ), 336 | BubbleSpecialThree( 337 | text: "bubble special three without tail", 338 | color: Color(0xFFE8E8EE), 339 | tail: false, 340 | isSender: false, 341 | ), 342 | BubbleSpecialThree( 343 | text: "bubble special three with tail", 344 | color: Color(0xFFE8E8EE), 345 | tail: true, 346 | isSender: false, 347 | ), 348 | SizedBox( 349 | height: 100, 350 | ) 351 | ], 352 | ), 353 | ), 354 | MessageBar( 355 | onSend: (_) => print(_), 356 | actions: [ 357 | InkWell( 358 | child: Icon( 359 | Icons.add, 360 | color: Colors.black, 361 | size: 24, 362 | ), 363 | onTap: () {}, 364 | ), 365 | Padding( 366 | padding: EdgeInsets.only(left: 8, right: 8), 367 | child: InkWell( 368 | child: Icon( 369 | Icons.camera_alt, 370 | color: Colors.green, 371 | size: 24, 372 | ), 373 | onTap: () {}, 374 | ), 375 | ), 376 | ], 377 | ), 378 | ], 379 | ), 380 | // This trailing comma makes auto-formatting nicer for build methods. 381 | ); 382 | } 383 | ``` 384 | 385 | ## Issues 386 | 387 | Please feel free to [let me know any issue](https://github.com/prahack/chat_bubbles/issues) regarding to this plugin. 388 | -------------------------------------------------------------------------------- /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 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | /build/ 32 | 33 | # Web related 34 | lib/generated_plugin_registrant.dart 35 | 36 | # Exceptions to above rules. 37 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 38 | -------------------------------------------------------------------------------- /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: 0b8abb4724aa590dd0f429683339b1e045a1594d 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # chat_bubble_example 2 | 3 | chat bubble examples 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/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | 16 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 17 | if (flutterVersionCode == null) { 18 | flutterVersionCode = '1' 19 | } 20 | 21 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 22 | if (flutterVersionName == null) { 23 | flutterVersionName = '1.0' 24 | } 25 | 26 | android { 27 | compileSdkVersion 34 28 | 29 | lintOptions { 30 | disable 'InvalidPackage' 31 | } 32 | 33 | defaultConfig { 34 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 35 | applicationId "com.prabhanu.chat_bubble_example" 36 | minSdkVersion flutter.minSdkVersion 37 | targetSdkVersion 28 38 | versionCode flutterVersionCode.toInteger() 39 | versionName flutterVersionName 40 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 41 | } 42 | 43 | buildTypes { 44 | release { 45 | // TODO: Add your own signing config for the release build. 46 | // Signing with the debug keys for now, so `flutter run --release` works. 47 | signingConfig signingConfigs.debug 48 | } 49 | } 50 | } 51 | 52 | flutter { 53 | source '../..' 54 | } 55 | 56 | dependencies { 57 | testImplementation 'junit:junit:4.12' 58 | androidTestImplementation 'androidx.test:runner:1.1.1' 59 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 60 | } 61 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/prabhanu/chat_bubble_example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.prabhanu.chat_bubble_example; 2 | 3 | import androidx.annotation.NonNull; 4 | import io.flutter.embedding.android.FlutterActivity; 5 | import io.flutter.embedding.engine.FlutterEngine; 6 | import io.flutter.plugins.GeneratedPluginRegistrant; 7 | 8 | public class MainActivity extends FlutterActivity { 9 | @Override 10 | public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { 11 | GeneratedPluginRegistrant.registerWith(flutterEngine); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /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/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | } 7 | 8 | rootProject.buildDir = '../build' 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(':app') 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M --add-exports=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /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-7.5-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | } 9 | settings.ext.flutterSdkPath = flutterSdkPath() 10 | 11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") 12 | 13 | repositories { 14 | google() 15 | mavenCentral() 16 | gradlePluginPortal() 17 | } 18 | 19 | buildscript { 20 | repositories { 21 | mavenCentral() 22 | maven { 23 | url = uri("https://storage.googleapis.com/r8-releases/raw") 24 | } 25 | } 26 | dependencies { 27 | classpath("com.android.tools:r8:8.2.26") 28 | } 29 | } 30 | } 31 | 32 | plugins { 33 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 34 | id "com.android.application" version "7.3.0" apply false 35 | id "org.jetbrains.kotlin.android" version "2.0.0" apply false 36 | } 37 | 38 | include ":app" -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /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/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '12.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 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 32 | end 33 | 34 | post_install do |installer| 35 | installer.pods_project.targets.each do |target| 36 | flutter_additional_ios_build_settings(target) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - audioplayers_darwin (0.0.1): 3 | - Flutter 4 | - Flutter (1.0.0) 5 | - path_provider_foundation (0.0.1): 6 | - Flutter 7 | - FlutterMacOS 8 | - sqflite_darwin (0.0.4): 9 | - Flutter 10 | - FlutterMacOS 11 | 12 | DEPENDENCIES: 13 | - audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/ios`) 14 | - Flutter (from `Flutter`) 15 | - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) 16 | - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) 17 | 18 | EXTERNAL SOURCES: 19 | audioplayers_darwin: 20 | :path: ".symlinks/plugins/audioplayers_darwin/ios" 21 | Flutter: 22 | :path: Flutter 23 | path_provider_foundation: 24 | :path: ".symlinks/plugins/path_provider_foundation/darwin" 25 | sqflite_darwin: 26 | :path: ".symlinks/plugins/sqflite_darwin/darwin" 27 | 28 | SPEC CHECKSUMS: 29 | audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40 30 | Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 31 | path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 32 | sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d 33 | 34 | PODFILE CHECKSUM: 1a782344d33c12ced0182eeab11e8668d253eb48 35 | 36 | COCOAPODS: 1.13.0 37 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3635C394DD52B7F88710476A /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40FB2E746EE1135799038E55 /* libPods-Runner.a */; }; 12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 13 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 14 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 15 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 16 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 17 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXCopyFilesBuildPhase section */ 21 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 22 | isa = PBXCopyFilesBuildPhase; 23 | buildActionMask = 2147483647; 24 | dstPath = ""; 25 | dstSubfolderSpec = 10; 26 | files = ( 27 | ); 28 | name = "Embed Frameworks"; 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXCopyFilesBuildPhase section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 128C4749CE4F17176847E2AD /* 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 = ""; }; 35 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 36 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 37 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 38 | 40FB2E746EE1135799038E55 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 40 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 41 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 42 | 8C78227CEC68A03505925008 /* 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 = ""; }; 43 | 9305F75D2236A25616BED326 /* 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 = ""; }; 44 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 45 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 46 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 48 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 49 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 50 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 51 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | /* End PBXFileReference section */ 53 | 54 | /* Begin PBXFrameworksBuildPhase section */ 55 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 56 | isa = PBXFrameworksBuildPhase; 57 | buildActionMask = 2147483647; 58 | files = ( 59 | 3635C394DD52B7F88710476A /* libPods-Runner.a in Frameworks */, 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXFrameworksBuildPhase section */ 64 | 65 | /* Begin PBXGroup section */ 66 | 642EBD50A28B166EE1D8CA7F /* Pods */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 8C78227CEC68A03505925008 /* Pods-Runner.debug.xcconfig */, 70 | 9305F75D2236A25616BED326 /* Pods-Runner.release.xcconfig */, 71 | 128C4749CE4F17176847E2AD /* Pods-Runner.profile.xcconfig */, 72 | ); 73 | name = Pods; 74 | path = Pods; 75 | sourceTree = ""; 76 | }; 77 | 9740EEB11CF90186004384FC /* Flutter */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 81 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 82 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 83 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 84 | ); 85 | name = Flutter; 86 | sourceTree = ""; 87 | }; 88 | 97C146E51CF9000F007C117D = { 89 | isa = PBXGroup; 90 | children = ( 91 | 9740EEB11CF90186004384FC /* Flutter */, 92 | 97C146F01CF9000F007C117D /* Runner */, 93 | 97C146EF1CF9000F007C117D /* Products */, 94 | 642EBD50A28B166EE1D8CA7F /* Pods */, 95 | F27ED85905AD2CC441C2A838 /* Frameworks */, 96 | ); 97 | sourceTree = ""; 98 | }; 99 | 97C146EF1CF9000F007C117D /* Products */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 97C146EE1CF9000F007C117D /* Runner.app */, 103 | ); 104 | name = Products; 105 | sourceTree = ""; 106 | }; 107 | 97C146F01CF9000F007C117D /* Runner */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 111 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 112 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 113 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 114 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 115 | 97C147021CF9000F007C117D /* Info.plist */, 116 | 97C146F11CF9000F007C117D /* Supporting Files */, 117 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 118 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 119 | ); 120 | path = Runner; 121 | sourceTree = ""; 122 | }; 123 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | 97C146F21CF9000F007C117D /* main.m */, 127 | ); 128 | name = "Supporting Files"; 129 | sourceTree = ""; 130 | }; 131 | F27ED85905AD2CC441C2A838 /* Frameworks */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 40FB2E746EE1135799038E55 /* libPods-Runner.a */, 135 | ); 136 | name = Frameworks; 137 | sourceTree = ""; 138 | }; 139 | /* End PBXGroup section */ 140 | 141 | /* Begin PBXNativeTarget section */ 142 | 97C146ED1CF9000F007C117D /* Runner */ = { 143 | isa = PBXNativeTarget; 144 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 145 | buildPhases = ( 146 | C3E45C31DFCF632DE2DCC88F /* [CP] Check Pods Manifest.lock */, 147 | 9740EEB61CF901F6004384FC /* Run Script */, 148 | 97C146EA1CF9000F007C117D /* Sources */, 149 | 97C146EB1CF9000F007C117D /* Frameworks */, 150 | 97C146EC1CF9000F007C117D /* Resources */, 151 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 152 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 153 | BDDD013E7BF67F0A202D413A /* [CP] Copy Pods Resources */, 154 | ); 155 | buildRules = ( 156 | ); 157 | dependencies = ( 158 | ); 159 | name = Runner; 160 | productName = Runner; 161 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 162 | productType = "com.apple.product-type.application"; 163 | }; 164 | /* End PBXNativeTarget section */ 165 | 166 | /* Begin PBXProject section */ 167 | 97C146E61CF9000F007C117D /* Project object */ = { 168 | isa = PBXProject; 169 | attributes = { 170 | LastUpgradeCheck = 1510; 171 | ORGANIZATIONNAME = "The Chromium Authors"; 172 | TargetAttributes = { 173 | 97C146ED1CF9000F007C117D = { 174 | CreatedOnToolsVersion = 7.3.1; 175 | }; 176 | }; 177 | }; 178 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 179 | compatibilityVersion = "Xcode 3.2"; 180 | developmentRegion = en; 181 | hasScannedForEncodings = 0; 182 | knownRegions = ( 183 | en, 184 | Base, 185 | ); 186 | mainGroup = 97C146E51CF9000F007C117D; 187 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 188 | projectDirPath = ""; 189 | projectRoot = ""; 190 | targets = ( 191 | 97C146ED1CF9000F007C117D /* Runner */, 192 | ); 193 | }; 194 | /* End PBXProject section */ 195 | 196 | /* Begin PBXResourcesBuildPhase section */ 197 | 97C146EC1CF9000F007C117D /* Resources */ = { 198 | isa = PBXResourcesBuildPhase; 199 | buildActionMask = 2147483647; 200 | files = ( 201 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 202 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 203 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 204 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | /* End PBXResourcesBuildPhase section */ 209 | 210 | /* Begin PBXShellScriptBuildPhase section */ 211 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 212 | isa = PBXShellScriptBuildPhase; 213 | alwaysOutOfDate = 1; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | ); 217 | inputPaths = ( 218 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", 219 | ); 220 | name = "Thin Binary"; 221 | outputPaths = ( 222 | ); 223 | runOnlyForDeploymentPostprocessing = 0; 224 | shellPath = /bin/sh; 225 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 226 | }; 227 | 9740EEB61CF901F6004384FC /* Run Script */ = { 228 | isa = PBXShellScriptBuildPhase; 229 | alwaysOutOfDate = 1; 230 | buildActionMask = 2147483647; 231 | files = ( 232 | ); 233 | inputPaths = ( 234 | ); 235 | name = "Run Script"; 236 | outputPaths = ( 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | shellPath = /bin/sh; 240 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 241 | }; 242 | BDDD013E7BF67F0A202D413A /* [CP] Copy Pods Resources */ = { 243 | isa = PBXShellScriptBuildPhase; 244 | buildActionMask = 2147483647; 245 | files = ( 246 | ); 247 | inputPaths = ( 248 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", 249 | "${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation/path_provider_foundation_privacy.bundle", 250 | "${PODS_CONFIGURATION_BUILD_DIR}/sqflite_darwin/sqflite_darwin_privacy.bundle", 251 | ); 252 | name = "[CP] Copy Pods Resources"; 253 | outputPaths = ( 254 | "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/path_provider_foundation_privacy.bundle", 255 | "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/sqflite_darwin_privacy.bundle", 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | shellPath = /bin/sh; 259 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; 260 | showEnvVarsInLog = 0; 261 | }; 262 | C3E45C31DFCF632DE2DCC88F /* [CP] Check Pods Manifest.lock */ = { 263 | isa = PBXShellScriptBuildPhase; 264 | buildActionMask = 2147483647; 265 | files = ( 266 | ); 267 | inputFileListPaths = ( 268 | ); 269 | inputPaths = ( 270 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 271 | "${PODS_ROOT}/Manifest.lock", 272 | ); 273 | name = "[CP] Check Pods Manifest.lock"; 274 | outputFileListPaths = ( 275 | ); 276 | outputPaths = ( 277 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | shellPath = /bin/sh; 281 | 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"; 282 | showEnvVarsInLog = 0; 283 | }; 284 | /* End PBXShellScriptBuildPhase section */ 285 | 286 | /* Begin PBXSourcesBuildPhase section */ 287 | 97C146EA1CF9000F007C117D /* Sources */ = { 288 | isa = PBXSourcesBuildPhase; 289 | buildActionMask = 2147483647; 290 | files = ( 291 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 292 | 97C146F31CF9000F007C117D /* main.m in Sources */, 293 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 294 | ); 295 | runOnlyForDeploymentPostprocessing = 0; 296 | }; 297 | /* End PBXSourcesBuildPhase section */ 298 | 299 | /* Begin PBXVariantGroup section */ 300 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 301 | isa = PBXVariantGroup; 302 | children = ( 303 | 97C146FB1CF9000F007C117D /* Base */, 304 | ); 305 | name = Main.storyboard; 306 | sourceTree = ""; 307 | }; 308 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 309 | isa = PBXVariantGroup; 310 | children = ( 311 | 97C147001CF9000F007C117D /* Base */, 312 | ); 313 | name = LaunchScreen.storyboard; 314 | sourceTree = ""; 315 | }; 316 | /* End PBXVariantGroup section */ 317 | 318 | /* Begin XCBuildConfiguration section */ 319 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 320 | isa = XCBuildConfiguration; 321 | buildSettings = { 322 | ALWAYS_SEARCH_USER_PATHS = NO; 323 | CLANG_ANALYZER_NONNULL = YES; 324 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 325 | CLANG_CXX_LIBRARY = "libc++"; 326 | CLANG_ENABLE_MODULES = YES; 327 | CLANG_ENABLE_OBJC_ARC = YES; 328 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 329 | CLANG_WARN_BOOL_CONVERSION = YES; 330 | CLANG_WARN_COMMA = YES; 331 | CLANG_WARN_CONSTANT_CONVERSION = YES; 332 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 333 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 334 | CLANG_WARN_EMPTY_BODY = YES; 335 | CLANG_WARN_ENUM_CONVERSION = YES; 336 | CLANG_WARN_INFINITE_RECURSION = YES; 337 | CLANG_WARN_INT_CONVERSION = YES; 338 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 339 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 340 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 341 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 342 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 343 | CLANG_WARN_STRICT_PROTOTYPES = YES; 344 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 345 | CLANG_WARN_UNREACHABLE_CODE = YES; 346 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 347 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 348 | COPY_PHASE_STRIP = NO; 349 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 350 | ENABLE_NS_ASSERTIONS = NO; 351 | ENABLE_STRICT_OBJC_MSGSEND = YES; 352 | GCC_C_LANGUAGE_STANDARD = gnu99; 353 | GCC_NO_COMMON_BLOCKS = YES; 354 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 355 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 356 | GCC_WARN_UNDECLARED_SELECTOR = YES; 357 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 358 | GCC_WARN_UNUSED_FUNCTION = YES; 359 | GCC_WARN_UNUSED_VARIABLE = YES; 360 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 361 | MTL_ENABLE_DEBUG_INFO = NO; 362 | SDKROOT = iphoneos; 363 | SUPPORTED_PLATFORMS = iphoneos; 364 | TARGETED_DEVICE_FAMILY = "1,2"; 365 | VALIDATE_PRODUCT = YES; 366 | }; 367 | name = Profile; 368 | }; 369 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 370 | isa = XCBuildConfiguration; 371 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 372 | buildSettings = { 373 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 374 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 375 | ENABLE_BITCODE = NO; 376 | FRAMEWORK_SEARCH_PATHS = ( 377 | "$(inherited)", 378 | "$(PROJECT_DIR)/Flutter", 379 | ); 380 | INFOPLIST_FILE = Runner/Info.plist; 381 | LD_RUNPATH_SEARCH_PATHS = ( 382 | "$(inherited)", 383 | "@executable_path/Frameworks", 384 | ); 385 | LIBRARY_SEARCH_PATHS = ( 386 | "$(inherited)", 387 | "$(PROJECT_DIR)/Flutter", 388 | ); 389 | PRODUCT_BUNDLE_IDENTIFIER = com.prabhanu.chatBubbleExample; 390 | PRODUCT_NAME = "$(TARGET_NAME)"; 391 | VERSIONING_SYSTEM = "apple-generic"; 392 | }; 393 | name = Profile; 394 | }; 395 | 97C147031CF9000F007C117D /* Debug */ = { 396 | isa = XCBuildConfiguration; 397 | buildSettings = { 398 | ALWAYS_SEARCH_USER_PATHS = NO; 399 | CLANG_ANALYZER_NONNULL = YES; 400 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 401 | CLANG_CXX_LIBRARY = "libc++"; 402 | CLANG_ENABLE_MODULES = YES; 403 | CLANG_ENABLE_OBJC_ARC = YES; 404 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 405 | CLANG_WARN_BOOL_CONVERSION = YES; 406 | CLANG_WARN_COMMA = YES; 407 | CLANG_WARN_CONSTANT_CONVERSION = YES; 408 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 409 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 410 | CLANG_WARN_EMPTY_BODY = YES; 411 | CLANG_WARN_ENUM_CONVERSION = YES; 412 | CLANG_WARN_INFINITE_RECURSION = YES; 413 | CLANG_WARN_INT_CONVERSION = YES; 414 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 415 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 416 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 417 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 418 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 419 | CLANG_WARN_STRICT_PROTOTYPES = YES; 420 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 421 | CLANG_WARN_UNREACHABLE_CODE = YES; 422 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 423 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 424 | COPY_PHASE_STRIP = NO; 425 | DEBUG_INFORMATION_FORMAT = dwarf; 426 | ENABLE_STRICT_OBJC_MSGSEND = YES; 427 | ENABLE_TESTABILITY = YES; 428 | GCC_C_LANGUAGE_STANDARD = gnu99; 429 | GCC_DYNAMIC_NO_PIC = NO; 430 | GCC_NO_COMMON_BLOCKS = YES; 431 | GCC_OPTIMIZATION_LEVEL = 0; 432 | GCC_PREPROCESSOR_DEFINITIONS = ( 433 | "DEBUG=1", 434 | "$(inherited)", 435 | ); 436 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 437 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 438 | GCC_WARN_UNDECLARED_SELECTOR = YES; 439 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 440 | GCC_WARN_UNUSED_FUNCTION = YES; 441 | GCC_WARN_UNUSED_VARIABLE = YES; 442 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 443 | MTL_ENABLE_DEBUG_INFO = YES; 444 | ONLY_ACTIVE_ARCH = YES; 445 | SDKROOT = iphoneos; 446 | TARGETED_DEVICE_FAMILY = "1,2"; 447 | }; 448 | name = Debug; 449 | }; 450 | 97C147041CF9000F007C117D /* Release */ = { 451 | isa = XCBuildConfiguration; 452 | buildSettings = { 453 | ALWAYS_SEARCH_USER_PATHS = NO; 454 | CLANG_ANALYZER_NONNULL = YES; 455 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 456 | CLANG_CXX_LIBRARY = "libc++"; 457 | CLANG_ENABLE_MODULES = YES; 458 | CLANG_ENABLE_OBJC_ARC = YES; 459 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 460 | CLANG_WARN_BOOL_CONVERSION = YES; 461 | CLANG_WARN_COMMA = YES; 462 | CLANG_WARN_CONSTANT_CONVERSION = YES; 463 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 464 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 465 | CLANG_WARN_EMPTY_BODY = YES; 466 | CLANG_WARN_ENUM_CONVERSION = YES; 467 | CLANG_WARN_INFINITE_RECURSION = YES; 468 | CLANG_WARN_INT_CONVERSION = YES; 469 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 470 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 471 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 472 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 473 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 474 | CLANG_WARN_STRICT_PROTOTYPES = YES; 475 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 476 | CLANG_WARN_UNREACHABLE_CODE = YES; 477 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 478 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 479 | COPY_PHASE_STRIP = NO; 480 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 481 | ENABLE_NS_ASSERTIONS = NO; 482 | ENABLE_STRICT_OBJC_MSGSEND = YES; 483 | GCC_C_LANGUAGE_STANDARD = gnu99; 484 | GCC_NO_COMMON_BLOCKS = YES; 485 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 486 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 487 | GCC_WARN_UNDECLARED_SELECTOR = YES; 488 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 489 | GCC_WARN_UNUSED_FUNCTION = YES; 490 | GCC_WARN_UNUSED_VARIABLE = YES; 491 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 492 | MTL_ENABLE_DEBUG_INFO = NO; 493 | SDKROOT = iphoneos; 494 | SUPPORTED_PLATFORMS = iphoneos; 495 | TARGETED_DEVICE_FAMILY = "1,2"; 496 | VALIDATE_PRODUCT = YES; 497 | }; 498 | name = Release; 499 | }; 500 | 97C147061CF9000F007C117D /* Debug */ = { 501 | isa = XCBuildConfiguration; 502 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 503 | buildSettings = { 504 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 505 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 506 | ENABLE_BITCODE = NO; 507 | FRAMEWORK_SEARCH_PATHS = ( 508 | "$(inherited)", 509 | "$(PROJECT_DIR)/Flutter", 510 | ); 511 | INFOPLIST_FILE = Runner/Info.plist; 512 | LD_RUNPATH_SEARCH_PATHS = ( 513 | "$(inherited)", 514 | "@executable_path/Frameworks", 515 | ); 516 | LIBRARY_SEARCH_PATHS = ( 517 | "$(inherited)", 518 | "$(PROJECT_DIR)/Flutter", 519 | ); 520 | PRODUCT_BUNDLE_IDENTIFIER = com.prabhanu.chatBubbleExample; 521 | PRODUCT_NAME = "$(TARGET_NAME)"; 522 | VERSIONING_SYSTEM = "apple-generic"; 523 | }; 524 | name = Debug; 525 | }; 526 | 97C147071CF9000F007C117D /* Release */ = { 527 | isa = XCBuildConfiguration; 528 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 529 | buildSettings = { 530 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 531 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 532 | ENABLE_BITCODE = NO; 533 | FRAMEWORK_SEARCH_PATHS = ( 534 | "$(inherited)", 535 | "$(PROJECT_DIR)/Flutter", 536 | ); 537 | INFOPLIST_FILE = Runner/Info.plist; 538 | LD_RUNPATH_SEARCH_PATHS = ( 539 | "$(inherited)", 540 | "@executable_path/Frameworks", 541 | ); 542 | LIBRARY_SEARCH_PATHS = ( 543 | "$(inherited)", 544 | "$(PROJECT_DIR)/Flutter", 545 | ); 546 | PRODUCT_BUNDLE_IDENTIFIER = com.prabhanu.chatBubbleExample; 547 | PRODUCT_NAME = "$(TARGET_NAME)"; 548 | VERSIONING_SYSTEM = "apple-generic"; 549 | }; 550 | name = Release; 551 | }; 552 | /* End XCBuildConfiguration section */ 553 | 554 | /* Begin XCConfigurationList section */ 555 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 556 | isa = XCConfigurationList; 557 | buildConfigurations = ( 558 | 97C147031CF9000F007C117D /* Debug */, 559 | 97C147041CF9000F007C117D /* Release */, 560 | 249021D3217E4FDB00AE95B9 /* Profile */, 561 | ); 562 | defaultConfigurationIsVisible = 0; 563 | defaultConfigurationName = Release; 564 | }; 565 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 566 | isa = XCConfigurationList; 567 | buildConfigurations = ( 568 | 97C147061CF9000F007C117D /* Debug */, 569 | 97C147071CF9000F007C117D /* Release */, 570 | 249021D4217E4FDB00AE95B9 /* Profile */, 571 | ); 572 | defaultConfigurationIsVisible = 0; 573 | defaultConfigurationName = Release; 574 | }; 575 | /* End XCConfigurationList section */ 576 | }; 577 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 578 | } 579 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/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/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /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/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/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 | chat_bubble_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 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:chat_bubbles/chat_bubbles.dart'; 5 | import 'package:audioplayers/audioplayers.dart'; 6 | import "package:cached_network_image/cached_network_image.dart"; 7 | 8 | void main() => runApp(MyApp()); 9 | 10 | class MyApp extends StatelessWidget { 11 | @override 12 | Widget build(BuildContext context) { 13 | return MaterialApp( 14 | title: 'chat bubble example', 15 | theme: ThemeData( 16 | primarySwatch: Colors.blue, 17 | ), 18 | home: MyHomePage(title: 'chat bubble example'), 19 | ); 20 | } 21 | } 22 | 23 | class MyHomePage extends StatefulWidget { 24 | final String title; 25 | MyHomePage({Key? key, required this.title}) : super(key: key); 26 | 27 | @override 28 | _MyHomePageState createState() => _MyHomePageState(); 29 | } 30 | 31 | class _MyHomePageState extends State { 32 | AudioPlayer audioPlayer = new AudioPlayer(); 33 | Duration? duration = new Duration(); 34 | Duration? position = new Duration(); 35 | bool isPlaying = false; 36 | bool isLoading = false; 37 | bool isPause = false; 38 | 39 | @override 40 | void initState() { 41 | super.initState(); 42 | audioPlayer.onDurationChanged.listen((Duration d) { 43 | setState(() { 44 | duration = d; 45 | isLoading = false; 46 | }); 47 | }); 48 | audioPlayer.onPositionChanged.listen((Duration p) { 49 | if (isPlaying) { 50 | setState(() { 51 | position = p; 52 | }); 53 | } 54 | }); 55 | audioPlayer.onPlayerComplete.listen((event) { 56 | setState(() { 57 | isPlaying = false; 58 | duration = new Duration(); 59 | position = new Duration(); 60 | }); 61 | }); 62 | } 63 | 64 | @override 65 | Widget build(BuildContext context) { 66 | final now = new DateTime.now(); 67 | return Scaffold( 68 | appBar: AppBar( 69 | title: Text(widget.title), 70 | ), 71 | body: Stack( 72 | children: [ 73 | SingleChildScrollView( 74 | child: Column( 75 | children: [ 76 | BubbleNormalImage( 77 | id: 'id001', 78 | image: _image(), 79 | color: Colors.purpleAccent, 80 | tail: true, 81 | delivered: true, 82 | ), 83 | BubbleNormalAudio( 84 | color: Color(0xFFE8E8EE), 85 | duration: 86 | duration == null ? 0.0 : duration!.inSeconds.toDouble(), 87 | position: 88 | position == null ? 0.0 : position!.inSeconds.toDouble(), 89 | isPlaying: isPlaying, 90 | isLoading: isLoading, 91 | isPause: isPause, 92 | onSeekChanged: _changeSeek, 93 | onPlayPauseButtonClick: _playAudio, 94 | sent: true, 95 | ), 96 | BubbleNormal( 97 | text: 'bubble normal with tail', 98 | isSender: false, 99 | color: Color(0xFF1B97F3), 100 | tail: true, 101 | textStyle: TextStyle( 102 | fontSize: 20, 103 | color: Colors.white, 104 | ), 105 | ), 106 | BubbleNormal( 107 | text: 'bubble normal with tail', 108 | isSender: true, 109 | color: Color(0xFFE8E8EE), 110 | tail: true, 111 | sent: true, 112 | ), 113 | DateChip( 114 | date: new DateTime(now.year, now.month, now.day - 2), 115 | ), 116 | BubbleNormal( 117 | text: 'bubble normal without tail', 118 | isSender: false, 119 | color: Color(0xFF1B97F3), 120 | tail: false, 121 | textStyle: TextStyle( 122 | fontSize: 20, 123 | color: Colors.white, 124 | ), 125 | ), 126 | BubbleNormal( 127 | text: 'bubble normal without tail', 128 | color: Color(0xFFE8E8EE), 129 | tail: false, 130 | sent: true, 131 | seen: true, 132 | delivered: true, 133 | ), 134 | BubbleSpecialOne( 135 | text: 'bubble special one with tail', 136 | isSender: false, 137 | color: Color(0xFF1B97F3), 138 | textStyle: TextStyle( 139 | fontSize: 20, 140 | color: Colors.white, 141 | ), 142 | ), 143 | DateChip( 144 | date: new DateTime(now.year, now.month, now.day - 1), 145 | ), 146 | BubbleSpecialOne( 147 | text: 'bubble special one with tail', 148 | color: Color(0xFFE8E8EE), 149 | seen: true, 150 | ), 151 | BubbleSpecialOne( 152 | text: 'bubble special one without tail', 153 | isSender: false, 154 | tail: false, 155 | color: Color(0xFF1B97F3), 156 | textStyle: TextStyle( 157 | fontSize: 20, 158 | color: Colors.black, 159 | ), 160 | ), 161 | BubbleSpecialOne( 162 | text: 'bubble special one without tail', 163 | tail: false, 164 | color: Color(0xFFE8E8EE), 165 | sent: true, 166 | ), 167 | BubbleSpecialTwo( 168 | text: 'bubble special tow with tail', 169 | isSender: false, 170 | color: Color(0xFF1B97F3), 171 | textStyle: TextStyle( 172 | fontSize: 20, 173 | color: Colors.black, 174 | ), 175 | ), 176 | DateChip( 177 | date: now, 178 | ), 179 | BubbleSpecialTwo( 180 | text: 'bubble special tow with tail', 181 | isSender: true, 182 | color: Color(0xFFE8E8EE), 183 | sent: true, 184 | ), 185 | BubbleSpecialTwo( 186 | text: 'bubble special tow without tail', 187 | isSender: false, 188 | tail: false, 189 | color: Color(0xFF1B97F3), 190 | textStyle: TextStyle( 191 | fontSize: 20, 192 | color: Colors.black, 193 | ), 194 | ), 195 | BubbleSpecialTwo( 196 | text: 'bubble special tow without tail', 197 | tail: false, 198 | color: Color(0xFFE8E8EE), 199 | delivered: true, 200 | ), 201 | BubbleSpecialThree( 202 | text: 'bubble special three without tail', 203 | color: Color(0xFF1B97F3), 204 | tail: false, 205 | textStyle: TextStyle(color: Colors.white, fontSize: 16), 206 | ), 207 | BubbleSpecialThree( 208 | text: 'bubble special three with tail', 209 | color: Color(0xFF1B97F3), 210 | tail: true, 211 | textStyle: TextStyle(color: Colors.white, fontSize: 16), 212 | ), 213 | BubbleSpecialThree( 214 | text: "bubble special three without tail", 215 | color: Color(0xFFE8E8EE), 216 | tail: false, 217 | isSender: false, 218 | ), 219 | BubbleSpecialThree( 220 | text: "bubble special three with tail", 221 | color: Color(0xFFE8E8EE), 222 | tail: true, 223 | isSender: false, 224 | ), 225 | SizedBox( 226 | height: 100, 227 | ) 228 | ], 229 | ), 230 | ), 231 | MessageBar( 232 | onSend: (_) => print(_), 233 | actions: [ 234 | InkWell( 235 | child: Icon( 236 | Icons.add, 237 | color: Colors.black, 238 | size: 24, 239 | ), 240 | onTap: () {}, 241 | ), 242 | Padding( 243 | padding: EdgeInsets.only(left: 8, right: 8), 244 | child: InkWell( 245 | child: Icon( 246 | Icons.camera_alt, 247 | color: Colors.green, 248 | size: 24, 249 | ), 250 | onTap: () {}, 251 | ), 252 | ), 253 | ], 254 | ), 255 | ], 256 | ), 257 | // This trailing comma makes auto-formatting nicer for build methods. 258 | ); 259 | } 260 | 261 | Widget _image() { 262 | return Container( 263 | constraints: BoxConstraints( 264 | minHeight: 20.0, 265 | minWidth: 20.0, 266 | ), 267 | child: CachedNetworkImage( 268 | imageUrl: 'https://i.ibb.co/JCyT1kT/Asset-1.png', 269 | progressIndicatorBuilder: (context, url, downloadProgress) => 270 | CircularProgressIndicator(value: downloadProgress.progress), 271 | errorWidget: (context, url, error) => const Icon(Icons.error), 272 | ), 273 | ); 274 | } 275 | 276 | void _changeSeek(double value) { 277 | setState(() { 278 | audioPlayer.seek(new Duration(seconds: value.toInt())); 279 | }); 280 | } 281 | 282 | void _playAudio() async { 283 | final url = 'https://download.samplelib.com/mp3/sample-15s.mp3'; 284 | if (isPause) { 285 | await audioPlayer.resume(); 286 | setState(() { 287 | isPlaying = true; 288 | isPause = false; 289 | }); 290 | } else if (isPlaying) { 291 | await audioPlayer.pause(); 292 | setState(() { 293 | isPlaying = false; 294 | isPause = true; 295 | }); 296 | } else { 297 | log('play: loading'); 298 | setState(() { 299 | isLoading = true; 300 | }); 301 | await audioPlayer.play(UrlSource(url)); 302 | log('play: loaded'); 303 | setState(() { 304 | audioPlayer.getDuration().then( 305 | (value) => setState(() { 306 | log('init duration: $value'); 307 | duration = value; 308 | isLoading = false; 309 | }), 310 | ); 311 | audioPlayer.getCurrentPosition().then( 312 | (value) => setState(() { 313 | log('init position: $value'); 314 | position = value; 315 | }), 316 | ); 317 | isPlaying = true; 318 | }); 319 | } 320 | } 321 | } 322 | -------------------------------------------------------------------------------- /example/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 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.11.0" 12 | audioplayers: 13 | dependency: "direct dev" 14 | description: 15 | name: audioplayers 16 | sha256: c346ba5a39dc208f1bab55fc239855f573d69b0e832402114bf0b793622adc4d 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "6.1.0" 20 | audioplayers_android: 21 | dependency: transitive 22 | description: 23 | name: audioplayers_android 24 | sha256: de576b890befe27175c2f511ba8b742bec83765fa97c3ce4282bba46212f58e4 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "5.0.0" 28 | audioplayers_darwin: 29 | dependency: transitive 30 | description: 31 | name: audioplayers_darwin 32 | sha256: e507887f3ff18d8e5a10a668d7bedc28206b12e10b98347797257c6ae1019c3b 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "6.0.0" 36 | audioplayers_linux: 37 | dependency: transitive 38 | description: 39 | name: audioplayers_linux 40 | sha256: "3d3d244c90436115417f170426ce768856d8fe4dfc5ed66a049d2890acfa82f9" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "4.0.0" 44 | audioplayers_platform_interface: 45 | dependency: transitive 46 | description: 47 | name: audioplayers_platform_interface 48 | sha256: "6834dd48dfb7bc6c2404998ebdd161f79cd3774a7e6779e1348d54a3bfdcfaa5" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "7.0.0" 52 | audioplayers_web: 53 | dependency: transitive 54 | description: 55 | name: audioplayers_web 56 | sha256: "3609bdf0e05e66a3d9750ee40b1e37f2a622c4edb796cc600b53a90a30a2ace4" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "5.0.1" 60 | audioplayers_windows: 61 | dependency: transitive 62 | description: 63 | name: audioplayers_windows 64 | sha256: "8605762dddba992138d476f6a0c3afd9df30ac5b96039929063eceed416795c2" 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "4.0.0" 68 | boolean_selector: 69 | dependency: transitive 70 | description: 71 | name: boolean_selector 72 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 73 | url: "https://pub.dev" 74 | source: hosted 75 | version: "2.1.1" 76 | cached_network_image: 77 | dependency: "direct dev" 78 | description: 79 | name: cached_network_image 80 | sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916" 81 | url: "https://pub.dev" 82 | source: hosted 83 | version: "3.4.1" 84 | cached_network_image_platform_interface: 85 | dependency: transitive 86 | description: 87 | name: cached_network_image_platform_interface 88 | sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829" 89 | url: "https://pub.dev" 90 | source: hosted 91 | version: "4.1.1" 92 | cached_network_image_web: 93 | dependency: transitive 94 | description: 95 | name: cached_network_image_web 96 | sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062" 97 | url: "https://pub.dev" 98 | source: hosted 99 | version: "1.3.1" 100 | characters: 101 | dependency: transitive 102 | description: 103 | name: characters 104 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 105 | url: "https://pub.dev" 106 | source: hosted 107 | version: "1.3.0" 108 | chat_bubbles: 109 | dependency: "direct dev" 110 | description: 111 | path: ".." 112 | relative: true 113 | source: path 114 | version: "1.6.0" 115 | clock: 116 | dependency: transitive 117 | description: 118 | name: clock 119 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 120 | url: "https://pub.dev" 121 | source: hosted 122 | version: "1.1.1" 123 | collection: 124 | dependency: transitive 125 | description: 126 | name: collection 127 | sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf 128 | url: "https://pub.dev" 129 | source: hosted 130 | version: "1.19.0" 131 | crypto: 132 | dependency: transitive 133 | description: 134 | name: crypto 135 | sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" 136 | url: "https://pub.dev" 137 | source: hosted 138 | version: "3.0.6" 139 | cupertino_icons: 140 | dependency: "direct main" 141 | description: 142 | name: cupertino_icons 143 | sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 144 | url: "https://pub.dev" 145 | source: hosted 146 | version: "1.0.8" 147 | fake_async: 148 | dependency: transitive 149 | description: 150 | name: fake_async 151 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 152 | url: "https://pub.dev" 153 | source: hosted 154 | version: "1.3.1" 155 | ffi: 156 | dependency: transitive 157 | description: 158 | name: ffi 159 | sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "2.1.3" 163 | file: 164 | dependency: transitive 165 | description: 166 | name: file 167 | sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "7.0.1" 171 | fixnum: 172 | dependency: transitive 173 | description: 174 | name: fixnum 175 | sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "1.1.1" 179 | flutter: 180 | dependency: "direct main" 181 | description: flutter 182 | source: sdk 183 | version: "0.0.0" 184 | flutter_cache_manager: 185 | dependency: transitive 186 | description: 187 | name: flutter_cache_manager 188 | sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" 189 | url: "https://pub.dev" 190 | source: hosted 191 | version: "3.4.1" 192 | flutter_test: 193 | dependency: "direct dev" 194 | description: flutter 195 | source: sdk 196 | version: "0.0.0" 197 | flutter_web_plugins: 198 | dependency: transitive 199 | description: flutter 200 | source: sdk 201 | version: "0.0.0" 202 | http: 203 | dependency: transitive 204 | description: 205 | name: http 206 | sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 207 | url: "https://pub.dev" 208 | source: hosted 209 | version: "1.2.2" 210 | http_parser: 211 | dependency: transitive 212 | description: 213 | name: http_parser 214 | sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" 215 | url: "https://pub.dev" 216 | source: hosted 217 | version: "4.1.2" 218 | intl: 219 | dependency: transitive 220 | description: 221 | name: intl 222 | sha256: "00f33b908655e606b86d2ade4710a231b802eec6f11e87e4ea3783fd72077a50" 223 | url: "https://pub.dev" 224 | source: hosted 225 | version: "0.20.1" 226 | leak_tracker: 227 | dependency: transitive 228 | description: 229 | name: leak_tracker 230 | sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" 231 | url: "https://pub.dev" 232 | source: hosted 233 | version: "10.0.7" 234 | leak_tracker_flutter_testing: 235 | dependency: transitive 236 | description: 237 | name: leak_tracker_flutter_testing 238 | sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" 239 | url: "https://pub.dev" 240 | source: hosted 241 | version: "3.0.8" 242 | leak_tracker_testing: 243 | dependency: transitive 244 | description: 245 | name: leak_tracker_testing 246 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 247 | url: "https://pub.dev" 248 | source: hosted 249 | version: "3.0.1" 250 | matcher: 251 | dependency: transitive 252 | description: 253 | name: matcher 254 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb 255 | url: "https://pub.dev" 256 | source: hosted 257 | version: "0.12.16+1" 258 | material_color_utilities: 259 | dependency: transitive 260 | description: 261 | name: material_color_utilities 262 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 263 | url: "https://pub.dev" 264 | source: hosted 265 | version: "0.11.1" 266 | meta: 267 | dependency: transitive 268 | description: 269 | name: meta 270 | sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 271 | url: "https://pub.dev" 272 | source: hosted 273 | version: "1.15.0" 274 | octo_image: 275 | dependency: transitive 276 | description: 277 | name: octo_image 278 | sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" 279 | url: "https://pub.dev" 280 | source: hosted 281 | version: "2.1.0" 282 | path: 283 | dependency: transitive 284 | description: 285 | name: path 286 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" 287 | url: "https://pub.dev" 288 | source: hosted 289 | version: "1.9.0" 290 | path_provider: 291 | dependency: transitive 292 | description: 293 | name: path_provider 294 | sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" 295 | url: "https://pub.dev" 296 | source: hosted 297 | version: "2.1.5" 298 | path_provider_android: 299 | dependency: transitive 300 | description: 301 | name: path_provider_android 302 | sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" 303 | url: "https://pub.dev" 304 | source: hosted 305 | version: "2.2.15" 306 | path_provider_foundation: 307 | dependency: transitive 308 | description: 309 | name: path_provider_foundation 310 | sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" 311 | url: "https://pub.dev" 312 | source: hosted 313 | version: "2.4.1" 314 | path_provider_linux: 315 | dependency: transitive 316 | description: 317 | name: path_provider_linux 318 | sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 319 | url: "https://pub.dev" 320 | source: hosted 321 | version: "2.2.1" 322 | path_provider_platform_interface: 323 | dependency: transitive 324 | description: 325 | name: path_provider_platform_interface 326 | sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" 327 | url: "https://pub.dev" 328 | source: hosted 329 | version: "2.1.2" 330 | path_provider_windows: 331 | dependency: transitive 332 | description: 333 | name: path_provider_windows 334 | sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 335 | url: "https://pub.dev" 336 | source: hosted 337 | version: "2.3.0" 338 | platform: 339 | dependency: transitive 340 | description: 341 | name: platform 342 | sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" 343 | url: "https://pub.dev" 344 | source: hosted 345 | version: "3.1.6" 346 | plugin_platform_interface: 347 | dependency: transitive 348 | description: 349 | name: plugin_platform_interface 350 | sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" 351 | url: "https://pub.dev" 352 | source: hosted 353 | version: "2.1.8" 354 | rxdart: 355 | dependency: transitive 356 | description: 357 | name: rxdart 358 | sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" 359 | url: "https://pub.dev" 360 | source: hosted 361 | version: "0.28.0" 362 | sky_engine: 363 | dependency: transitive 364 | description: flutter 365 | source: sdk 366 | version: "0.0.0" 367 | source_span: 368 | dependency: transitive 369 | description: 370 | name: source_span 371 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 372 | url: "https://pub.dev" 373 | source: hosted 374 | version: "1.10.0" 375 | sprintf: 376 | dependency: transitive 377 | description: 378 | name: sprintf 379 | sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" 380 | url: "https://pub.dev" 381 | source: hosted 382 | version: "7.0.0" 383 | sqflite: 384 | dependency: transitive 385 | description: 386 | name: sqflite 387 | sha256: "2d7299468485dca85efeeadf5d38986909c5eb0cd71fd3db2c2f000e6c9454bb" 388 | url: "https://pub.dev" 389 | source: hosted 390 | version: "2.4.1" 391 | sqflite_android: 392 | dependency: transitive 393 | description: 394 | name: sqflite_android 395 | sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3" 396 | url: "https://pub.dev" 397 | source: hosted 398 | version: "2.4.0" 399 | sqflite_common: 400 | dependency: transitive 401 | description: 402 | name: sqflite_common 403 | sha256: "761b9740ecbd4d3e66b8916d784e581861fd3c3553eda85e167bc49fdb68f709" 404 | url: "https://pub.dev" 405 | source: hosted 406 | version: "2.5.4+6" 407 | sqflite_darwin: 408 | dependency: transitive 409 | description: 410 | name: sqflite_darwin 411 | sha256: "22adfd9a2c7d634041e96d6241e6e1c8138ca6817018afc5d443fef91dcefa9c" 412 | url: "https://pub.dev" 413 | source: hosted 414 | version: "2.4.1+1" 415 | sqflite_platform_interface: 416 | dependency: transitive 417 | description: 418 | name: sqflite_platform_interface 419 | sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" 420 | url: "https://pub.dev" 421 | source: hosted 422 | version: "2.4.0" 423 | stack_trace: 424 | dependency: transitive 425 | description: 426 | name: stack_trace 427 | sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" 428 | url: "https://pub.dev" 429 | source: hosted 430 | version: "1.12.0" 431 | stream_channel: 432 | dependency: transitive 433 | description: 434 | name: stream_channel 435 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 436 | url: "https://pub.dev" 437 | source: hosted 438 | version: "2.1.2" 439 | string_scanner: 440 | dependency: transitive 441 | description: 442 | name: string_scanner 443 | sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" 444 | url: "https://pub.dev" 445 | source: hosted 446 | version: "1.3.0" 447 | synchronized: 448 | dependency: transitive 449 | description: 450 | name: synchronized 451 | sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" 452 | url: "https://pub.dev" 453 | source: hosted 454 | version: "3.3.0+3" 455 | term_glyph: 456 | dependency: transitive 457 | description: 458 | name: term_glyph 459 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 460 | url: "https://pub.dev" 461 | source: hosted 462 | version: "1.2.1" 463 | test_api: 464 | dependency: transitive 465 | description: 466 | name: test_api 467 | sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" 468 | url: "https://pub.dev" 469 | source: hosted 470 | version: "0.7.3" 471 | typed_data: 472 | dependency: transitive 473 | description: 474 | name: typed_data 475 | sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 476 | url: "https://pub.dev" 477 | source: hosted 478 | version: "1.4.0" 479 | uuid: 480 | dependency: transitive 481 | description: 482 | name: uuid 483 | sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff 484 | url: "https://pub.dev" 485 | source: hosted 486 | version: "4.5.1" 487 | vector_math: 488 | dependency: transitive 489 | description: 490 | name: vector_math 491 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 492 | url: "https://pub.dev" 493 | source: hosted 494 | version: "2.1.4" 495 | vm_service: 496 | dependency: transitive 497 | description: 498 | name: vm_service 499 | sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b 500 | url: "https://pub.dev" 501 | source: hosted 502 | version: "14.3.0" 503 | web: 504 | dependency: transitive 505 | description: 506 | name: web 507 | sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb 508 | url: "https://pub.dev" 509 | source: hosted 510 | version: "1.1.0" 511 | xdg_directories: 512 | dependency: transitive 513 | description: 514 | name: xdg_directories 515 | sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" 516 | url: "https://pub.dev" 517 | source: hosted 518 | version: "1.1.0" 519 | sdks: 520 | dart: ">=3.5.0 <4.0.0" 521 | flutter: ">=3.24.0" 522 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: chat_bubble_example 2 | description: chat bubble examples 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 1.0.0+1 15 | 16 | environment: 17 | sdk: ">=2.12.0-0 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 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.2 26 | 27 | dev_dependencies: 28 | flutter_test: 29 | sdk: flutter 30 | chat_bubbles: 31 | path: ../ 32 | audioplayers: ^6.0.0 33 | cached_network_image: ^3.4.0 34 | 35 | 36 | # For information on the generic Dart part of this file, see the 37 | # following page: https://dart.dev/tools/pub/pubspec 38 | 39 | # The following section is specific to Flutter. 40 | flutter: 41 | 42 | # The following line ensures that the Material Icons font is 43 | # included with your application, so that you can use the icons in 44 | # the material Icons class. 45 | uses-material-design: true 46 | 47 | # To add assets to your application, add an assets section, like this: 48 | # assets: 49 | # - images/a_dot_burr.jpeg 50 | # - images/a_dot_ham.jpeg 51 | 52 | # An image asset can refer to one or more resolution-specific "variants", see 53 | # https://flutter.dev/assets-and-images/#resolution-aware. 54 | 55 | # For details regarding adding assets from package dependencies, see 56 | # https://flutter.dev/assets-and-images/#from-packages 57 | 58 | # To add custom fonts to your application, add a fonts section here, 59 | # in this "flutter" section. Each entry in this list should have a 60 | # "family" key with the font family name, and a "fonts" key with a 61 | # list giving the asset and other descriptors for the font. For 62 | # example: 63 | # fonts: 64 | # - family: Schyler 65 | # fonts: 66 | # - asset: fonts/Schyler-Regular.ttf 67 | # - asset: fonts/Schyler-Italic.ttf 68 | # style: italic 69 | # - family: Trajan Pro 70 | # fonts: 71 | # - asset: fonts/TrajanPro.ttf 72 | # - asset: fonts/TrajanPro_Bold.ttf 73 | # weight: 700 74 | # 75 | # For details regarding fonts from package dependencies, 76 | # see https://flutter.dev/custom-fonts/#from-packages 77 | -------------------------------------------------------------------------------- /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:chat_bubble_example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /images/logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/logo/logo.png -------------------------------------------------------------------------------- /images/messages/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/messages/img1.png -------------------------------------------------------------------------------- /images/screenshots/2022_12_29_main1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/2022_12_29_main1.jpg -------------------------------------------------------------------------------- /images/screenshots/2022_12_29_main2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/2022_12_29_main2.jpg -------------------------------------------------------------------------------- /images/screenshots/2022_2_4_main1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/2022_2_4_main1.png -------------------------------------------------------------------------------- /images/screenshots/2022_2_4_main2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/2022_2_4_main2.png -------------------------------------------------------------------------------- /images/screenshots/2022_7_3_main1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/2022_7_3_main1.png -------------------------------------------------------------------------------- /images/screenshots/2022_7_3_main2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/2022_7_3_main2.png -------------------------------------------------------------------------------- /images/screenshots/audio_bubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/audio_bubble.png -------------------------------------------------------------------------------- /images/screenshots/datechip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/datechip.png -------------------------------------------------------------------------------- /images/screenshots/image_bubble.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/image_bubble.jpg -------------------------------------------------------------------------------- /images/screenshots/imsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/imsg.png -------------------------------------------------------------------------------- /images/screenshots/imsg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/imsg1.png -------------------------------------------------------------------------------- /images/screenshots/messagebar.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/messagebar.jpeg -------------------------------------------------------------------------------- /images/screenshots/screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/screenshot_1.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_1_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/screenshot_1_old.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/screenshot_2.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_2_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/screenshot_2_old.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_3_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/screenshot_3_old.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_4_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/screenshot_4_old.png -------------------------------------------------------------------------------- /images/screenshots/single_bubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prahack/chat_bubbles/413fcc8cef607fe1137fb23f3522c4817e3cca91/images/screenshots/single_bubble.png -------------------------------------------------------------------------------- /lib/algo/algo.dart: -------------------------------------------------------------------------------- 1 | import 'package:chat_bubbles/date_chips/date_chip.dart'; 2 | 3 | import './date_chip_text.dart'; 4 | 5 | ///all the algorithms of the plugin 6 | ///[dateChipText] to get the text which is need to show on the [DateChip] 7 | abstract class Algo { 8 | Algo._(); 9 | 10 | static String dateChipText(final DateTime date) { 11 | final dateChipText = new DateChipText(date); 12 | return dateChipText.getText(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/algo/date_chip_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:intl/intl.dart'; 2 | 3 | ///initial formatter to find the date txt 4 | final DateFormat _formatter = DateFormat('yyyy-MM-dd'); 5 | 6 | ///[DateChipText] class included with algorithms which are need to implement [DateChip] 7 | ///[date] parameter is required 8 | /// 9 | class DateChipText { 10 | final DateTime date; 11 | 12 | DateChipText(this.date); 13 | 14 | ///generate and return [DateChip] string 15 | /// 16 | /// 17 | String getText() { 18 | final now = new DateTime.now(); 19 | if (_formatter.format(now) == _formatter.format(date)) { 20 | return 'Today'; 21 | } else if (_formatter 22 | .format(new DateTime(now.year, now.month, now.day - 1)) == 23 | _formatter.format(date)) { 24 | return 'Yesterday'; 25 | } else { 26 | return '${DateFormat('d').format(date)} ${DateFormat('MMMM').format(date)} ${DateFormat('y').format(date)}'; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/bubbles/bubble_normal.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const double BUBBLE_RADIUS = 16; 4 | 5 | /// Basic chat bubble 6 | /// 7 | /// The [BorderRadius] can be customized using [bubbleRadius] 8 | /// 9 | /// [margin] and [padding] can be used to add space around or within 10 | /// the bubble respectively. 11 | /// 12 | /// Default [margin] value is [EdgeInsets.zero] and 13 | /// default padding value is [EdgeInsets.symmetric(horizontal: 16, vertical: 2)] 14 | /// 15 | /// Color can be customized using [color] 16 | /// 17 | /// [tail] boolean is used to add or remove a tail according to the sender type 18 | /// 19 | /// Display message can be changed using [text] 20 | /// 21 | /// [text] is the only required parameter 22 | /// 23 | /// [text] is now selectable 24 | /// 25 | /// Message sender can be changed using [isSender] 26 | /// 27 | /// [sent], [delivered] and [seen] can be used to display the message state 28 | /// 29 | /// The [TextStyle] can be customized using [textStyle] 30 | /// 31 | /// [leading] is the widget that's infront of the bubble when [isSender] 32 | /// is false. 33 | /// 34 | /// [trailing] is the widget that's at the end of the bubble when [isSender] 35 | /// is true. 36 | /// 37 | /// [onTap], [onDoubleTap], [onLongPress] are callbacks used to register tap gestures 38 | 39 | class BubbleNormal extends StatelessWidget { 40 | final double bubbleRadius; 41 | final bool isSender; 42 | final Color color; 43 | final String text; 44 | final bool tail; 45 | final bool sent; 46 | final bool delivered; 47 | final bool seen; 48 | final TextStyle textStyle; 49 | final BoxConstraints? constraints; 50 | final Widget? leading; 51 | final Widget? trailing; 52 | final EdgeInsets margin; 53 | final EdgeInsets padding; 54 | final VoidCallback? onTap; 55 | final VoidCallback? onDoubleTap; 56 | final VoidCallback? onLongPress; 57 | 58 | BubbleNormal({ 59 | Key? key, 60 | required this.text, 61 | this.constraints, 62 | this.margin = EdgeInsets.zero, 63 | this.padding = const EdgeInsets.symmetric(horizontal: 16, vertical: 2), 64 | this.bubbleRadius = BUBBLE_RADIUS, 65 | this.isSender = true, 66 | this.color = Colors.white70, 67 | this.tail = true, 68 | this.sent = false, 69 | this.delivered = false, 70 | this.seen = false, 71 | this.onTap, 72 | this.onDoubleTap, 73 | this.onLongPress, 74 | this.leading, 75 | this.trailing, 76 | this.textStyle = const TextStyle( 77 | color: Colors.black87, 78 | fontSize: 16, 79 | ), 80 | }) : super(key: key); 81 | 82 | ///chat bubble builder method 83 | @override 84 | Widget build(BuildContext context) { 85 | bool stateTick = false; 86 | Icon? stateIcon; 87 | if (sent) { 88 | stateTick = true; 89 | stateIcon = Icon( 90 | Icons.done, 91 | size: 18, 92 | color: Color(0xFF97AD8E), 93 | ); 94 | } 95 | if (delivered) { 96 | stateTick = true; 97 | stateIcon = Icon( 98 | Icons.done_all, 99 | size: 18, 100 | color: Color(0xFF97AD8E), 101 | ); 102 | } 103 | if (seen) { 104 | stateTick = true; 105 | stateIcon = Icon( 106 | Icons.done_all, 107 | size: 18, 108 | color: Color(0xFF92DEDA), 109 | ); 110 | } 111 | 112 | return Row( 113 | children: [ 114 | isSender 115 | ? Expanded( 116 | child: SizedBox( 117 | width: 5, 118 | ), 119 | ) 120 | : leading ?? Container(), 121 | Container( 122 | color: Colors.transparent, 123 | constraints: constraints ?? 124 | BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .8), 125 | margin: margin, 126 | padding: padding, 127 | child: GestureDetector( 128 | onTap: onTap, 129 | onDoubleTap: onDoubleTap, 130 | onLongPress: onLongPress, 131 | child: Container( 132 | decoration: BoxDecoration( 133 | color: color, 134 | borderRadius: BorderRadius.only( 135 | topLeft: Radius.circular(bubbleRadius), 136 | topRight: Radius.circular(bubbleRadius), 137 | bottomLeft: Radius.circular(tail 138 | ? isSender 139 | ? bubbleRadius 140 | : 0 141 | : BUBBLE_RADIUS), 142 | bottomRight: Radius.circular(tail 143 | ? isSender 144 | ? 0 145 | : bubbleRadius 146 | : BUBBLE_RADIUS), 147 | ), 148 | ), 149 | child: Stack( 150 | children: [ 151 | Padding( 152 | padding: stateTick 153 | ? EdgeInsets.fromLTRB(12, 6, 28, 6) 154 | : EdgeInsets.symmetric(vertical: 6, horizontal: 12), 155 | child: SelectableText( 156 | text, 157 | style: textStyle, 158 | textAlign: TextAlign.left, 159 | ), 160 | ), 161 | stateIcon != null && stateTick 162 | ? Positioned( 163 | bottom: 4, 164 | right: 6, 165 | child: stateIcon, 166 | ) 167 | : SizedBox( 168 | width: 1, 169 | ), 170 | ], 171 | ), 172 | ), 173 | ), 174 | ), 175 | if (isSender && trailing != null) SizedBox.shrink(), 176 | ], 177 | ); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /lib/bubbles/bubble_normal_audio.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const double BUBBLE_RADIUS_AUDIO = 16; 4 | 5 | ///basic chat bubble type audio message widget 6 | /// 7 | /// [onSeekChanged] double pass function to take actions on seek changes 8 | /// 9 | /// [onPlayPauseButtonClick] void function to handle play pause button click 10 | /// 11 | /// [isPlaying],[isPause] parameters to handle playing state 12 | /// 13 | ///[duration] is the duration of the audio message in seconds 14 | /// 15 | ///[position] is the current position of the audio message playing in seconds 16 | /// 17 | ///[isLoading] is the loading state of the audio 18 | /// 19 | ///ex:- fetching from internet or loading from local storage 20 | /// 21 | ///chat bubble [BorderRadius] can be customized using [bubbleRadius] 22 | /// 23 | ///chat bubble color can be customized using [color] 24 | /// 25 | ///chat bubble tail can be customized using [tail] 26 | /// 27 | ///message sender can be changed using [isSender] 28 | /// 29 | ///[sent],[delivered] and [seen] can be used to display the message state 30 | /// 31 | ///chat bubble [TextStyle] can be customized using [textStyle] 32 | 33 | class BubbleNormalAudio extends StatelessWidget { 34 | final void Function(double value) onSeekChanged; 35 | final void Function() onPlayPauseButtonClick; 36 | final bool isPlaying; 37 | final bool isPause; 38 | final double? duration; 39 | final double? position; 40 | final bool isLoading; 41 | final double bubbleRadius; 42 | final bool isSender; 43 | final Color color; 44 | final bool tail; 45 | final bool sent; 46 | final bool delivered; 47 | final bool seen; 48 | final TextStyle textStyle; 49 | final BoxConstraints? constraints; 50 | 51 | BubbleNormalAudio({ 52 | Key? key, 53 | required this.onSeekChanged, 54 | required this.onPlayPauseButtonClick, 55 | this.isPlaying = false, 56 | this.constraints, 57 | this.isPause = false, 58 | this.duration, 59 | this.position, 60 | this.isLoading = true, 61 | this.bubbleRadius = BUBBLE_RADIUS_AUDIO, 62 | this.isSender = true, 63 | this.color = Colors.white70, 64 | this.tail = true, 65 | this.sent = false, 66 | this.delivered = false, 67 | this.seen = false, 68 | this.textStyle = const TextStyle( 69 | color: Colors.black87, 70 | fontSize: 12, 71 | ), 72 | }) : super(key: key); 73 | 74 | ///chat bubble builder method 75 | @override 76 | Widget build(BuildContext context) { 77 | bool stateTick = false; 78 | Icon? stateIcon; 79 | if (sent) { 80 | stateTick = true; 81 | stateIcon = Icon( 82 | Icons.done, 83 | size: 18, 84 | color: Color(0xFF97AD8E), 85 | ); 86 | } 87 | if (delivered) { 88 | stateTick = true; 89 | stateIcon = Icon( 90 | Icons.done_all, 91 | size: 18, 92 | color: Color(0xFF97AD8E), 93 | ); 94 | } 95 | if (seen) { 96 | stateTick = true; 97 | stateIcon = Icon( 98 | Icons.done_all, 99 | size: 18, 100 | color: Color(0xFF92DEDA), 101 | ); 102 | } 103 | 104 | return Row( 105 | children: [ 106 | isSender 107 | ? Expanded( 108 | child: SizedBox( 109 | width: 5, 110 | ), 111 | ) 112 | : Container(), 113 | Container( 114 | color: Colors.transparent, 115 | constraints: constraints ?? 116 | BoxConstraints( 117 | maxWidth: MediaQuery.of(context).size.width * .8, 118 | maxHeight: 70), 119 | child: Padding( 120 | padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 2), 121 | child: Container( 122 | decoration: BoxDecoration( 123 | color: color, 124 | borderRadius: BorderRadius.only( 125 | topLeft: Radius.circular(bubbleRadius), 126 | topRight: Radius.circular(bubbleRadius), 127 | bottomLeft: Radius.circular(tail 128 | ? isSender 129 | ? bubbleRadius 130 | : 0 131 | : BUBBLE_RADIUS_AUDIO), 132 | bottomRight: Radius.circular(tail 133 | ? isSender 134 | ? 0 135 | : bubbleRadius 136 | : BUBBLE_RADIUS_AUDIO), 137 | ), 138 | ), 139 | child: Stack( 140 | children: [ 141 | Row( 142 | children: [ 143 | RawMaterialButton( 144 | onPressed: onPlayPauseButtonClick, 145 | elevation: 1.0, 146 | fillColor: Colors.white, 147 | child: !isPlaying 148 | ? Icon( 149 | Icons.play_arrow, 150 | size: 30.0, 151 | ) 152 | : isLoading 153 | ? CircularProgressIndicator() 154 | : isPause 155 | ? Icon( 156 | Icons.play_arrow, 157 | size: 30.0, 158 | ) 159 | : Icon( 160 | Icons.pause, 161 | size: 30.0, 162 | ), 163 | padding: EdgeInsets.all(0.0), 164 | shape: CircleBorder(), 165 | ), 166 | Expanded( 167 | child: Slider( 168 | min: 0.0, 169 | max: duration ?? 0.0, 170 | value: position ?? 0.0, 171 | onChanged: onSeekChanged, 172 | ), 173 | ), 174 | ], 175 | ), 176 | Positioned( 177 | bottom: 8, 178 | right: 25, 179 | child: Text( 180 | '${audioTimer(duration ?? 0.0, position ?? 0.0)}', 181 | style: textStyle, 182 | ), 183 | ), 184 | stateIcon != null && stateTick 185 | ? Positioned( 186 | bottom: 4, 187 | right: 6, 188 | child: stateIcon, 189 | ) 190 | : SizedBox( 191 | width: 1, 192 | ), 193 | ], 194 | ), 195 | ), 196 | ), 197 | ), 198 | ], 199 | ); 200 | } 201 | 202 | String audioTimer(double duration, double position) { 203 | return '${(duration ~/ 60).toInt()}:${(duration % 60).toInt().toString().padLeft(2, '0')}/${position ~/ 60}:${(position % 60).toInt().toString().padLeft(2, '0')}'; 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /lib/bubbles/bubble_normal_image.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const double BUBBLE_RADIUS_IMAGE = 16; 4 | 5 | /// Basic image bubble 6 | /// 7 | /// Image bubble should have [id] to work with Hero animations 8 | /// [id] must be a unique value and is also required 9 | /// 10 | /// The [BorderRadius] can be customized using [bubbleRadius] 11 | /// 12 | /// [margin] and [padding] can be used to add space around or within 13 | /// the bubble respectively 14 | /// 15 | /// Color can be customized using [color] 16 | /// 17 | /// [tail] boolean is used to add or remove a tail accoring to the sender type 18 | /// 19 | /// Display image can be changed using [image] 20 | /// 21 | /// [image] is a required parameter 22 | /// 23 | /// Message sender can be changed using [isSender] 24 | /// 25 | /// [sent], [delivered] and [seen] can be used to display the message state 26 | /// 27 | /// The [TextStyle] can be customized using [textStyle] 28 | /// 29 | /// [leading] is the widget that's infront of the bubble when [isSender] 30 | /// is false. 31 | /// 32 | /// [trailing] is the widget that's at the end of the bubble when [isSender] 33 | /// is true. 34 | /// 35 | /// [onTap], [onLongPress] are callbacks used to register tap gestures 36 | 37 | class BubbleNormalImage extends StatelessWidget { 38 | static const loadingWidget = Center( 39 | child: CircularProgressIndicator(), 40 | ); 41 | 42 | final String id; 43 | final Widget image; 44 | final double bubbleRadius; 45 | final bool isSender; 46 | final Color color; 47 | final bool tail; 48 | final bool sent; 49 | final bool delivered; 50 | final bool seen; 51 | final VoidCallback? onTap; 52 | final VoidCallback? onLongPress; 53 | final Widget? leading; 54 | final Widget? trailing; 55 | final EdgeInsets? margin; 56 | final EdgeInsets? padding; 57 | 58 | const BubbleNormalImage({ 59 | Key? key, 60 | required this.id, 61 | required this.image, 62 | this.bubbleRadius = BUBBLE_RADIUS_IMAGE, 63 | this.margin = EdgeInsets.zero, 64 | this.padding = const EdgeInsets.fromLTRB(16, 8, 16, 8), 65 | this.leading, 66 | this.trailing, 67 | this.isSender = true, 68 | this.color = Colors.white70, 69 | this.tail = true, 70 | this.sent = false, 71 | this.delivered = false, 72 | this.seen = false, 73 | this.onTap, 74 | this.onLongPress, 75 | }) : super(key: key); 76 | 77 | /// image bubble builder method 78 | @override 79 | Widget build(BuildContext context) { 80 | bool stateTick = false; 81 | Icon? stateIcon; 82 | if (sent) { 83 | stateTick = true; 84 | stateIcon = Icon( 85 | Icons.done, 86 | size: 18, 87 | color: Color(0xFF97AD8E), 88 | ); 89 | } 90 | if (delivered) { 91 | stateTick = true; 92 | stateIcon = Icon( 93 | Icons.done_all, 94 | size: 18, 95 | color: Color(0xFF97AD8E), 96 | ); 97 | } 98 | if (seen) { 99 | stateTick = true; 100 | stateIcon = Icon( 101 | Icons.done_all, 102 | size: 18, 103 | color: Color(0xFF92DEDA), 104 | ); 105 | } 106 | 107 | return Row( 108 | children: [ 109 | isSender 110 | ? const Expanded( 111 | child: SizedBox( 112 | width: 5, 113 | ), 114 | ) 115 | : leading ?? Container(), 116 | Container( 117 | padding: padding, 118 | margin: margin, 119 | constraints: BoxConstraints( 120 | maxWidth: MediaQuery.of(context).size.width * .5, 121 | maxHeight: MediaQuery.of(context).size.width * .5, 122 | ), 123 | child: GestureDetector( 124 | child: Hero( 125 | tag: id, 126 | child: Stack( 127 | children: [ 128 | Container( 129 | decoration: BoxDecoration( 130 | color: color, 131 | borderRadius: BorderRadius.only( 132 | topLeft: Radius.circular(bubbleRadius), 133 | topRight: Radius.circular(bubbleRadius), 134 | bottomLeft: Radius.circular(tail 135 | ? isSender 136 | ? bubbleRadius 137 | : 0 138 | : BUBBLE_RADIUS_IMAGE), 139 | bottomRight: Radius.circular(tail 140 | ? isSender 141 | ? 0 142 | : bubbleRadius 143 | : BUBBLE_RADIUS_IMAGE), 144 | ), 145 | ), 146 | child: Padding( 147 | padding: const EdgeInsets.all(4.0), 148 | child: ClipRRect( 149 | borderRadius: BorderRadius.circular(bubbleRadius), 150 | child: image, 151 | ), 152 | ), 153 | ), 154 | stateIcon != null && stateTick 155 | ? Positioned( 156 | bottom: 4, 157 | right: 6, 158 | child: stateIcon, 159 | ) 160 | : SizedBox( 161 | width: 1, 162 | ), 163 | ], 164 | ), 165 | ), 166 | onLongPress: onLongPress, 167 | onTap: onTap ?? 168 | () { 169 | Navigator.push(context, MaterialPageRoute(builder: (_) { 170 | return _DetailScreen( 171 | tag: id, 172 | image: image, 173 | ); 174 | })); 175 | }), 176 | ), 177 | if (isSender && trailing != null) SizedBox.shrink(), 178 | ], 179 | ); 180 | } 181 | } 182 | 183 | /// detail screen of the image, display when tap on the image bubble 184 | class _DetailScreen extends StatefulWidget { 185 | final String tag; 186 | final Widget image; 187 | 188 | const _DetailScreen({Key? key, required this.tag, required this.image}) 189 | : super(key: key); 190 | 191 | @override 192 | _DetailScreenState createState() => _DetailScreenState(); 193 | } 194 | 195 | /// created using the Hero Widget 196 | class _DetailScreenState extends State<_DetailScreen> { 197 | @override 198 | initState() { 199 | super.initState(); 200 | } 201 | 202 | @override 203 | void dispose() { 204 | super.dispose(); 205 | } 206 | 207 | @override 208 | Widget build(BuildContext context) { 209 | return GestureDetector( 210 | child: Scaffold( 211 | body: Center( 212 | child: Hero( 213 | tag: widget.tag, 214 | child: widget.image, 215 | ), 216 | ), 217 | ), 218 | onTap: () { 219 | Navigator.pop(context); 220 | }, 221 | ); 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /lib/bubbles/bubble_special_one.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | ///WhatsApp's chat bubble type 4 | /// 5 | ///chat bubble color can be customized using [color] 6 | ///chat bubble tail can be customized using [tail] 7 | ///chat bubble display message can be changed using [text] 8 | ///[text] is the only required parameter 9 | ///message sender can be changed using [isSender] 10 | ///chat bubble [TextStyle] can be customized using [textStyle] 11 | 12 | class BubbleSpecialOne extends StatelessWidget { 13 | final bool isSender; 14 | final String text; 15 | final bool tail; 16 | final Color color; 17 | final bool sent; 18 | final bool delivered; 19 | final bool seen; 20 | final TextStyle textStyle; 21 | final BoxConstraints? constraints; 22 | 23 | const BubbleSpecialOne({ 24 | Key? key, 25 | this.isSender = true, 26 | this.constraints, 27 | required this.text, 28 | this.color = Colors.white70, 29 | this.tail = true, 30 | this.sent = false, 31 | this.delivered = false, 32 | this.seen = false, 33 | this.textStyle = const TextStyle( 34 | color: Colors.black87, 35 | fontSize: 16, 36 | ), 37 | }) : super(key: key); 38 | 39 | ///chat bubble builder method 40 | @override 41 | Widget build(BuildContext context) { 42 | bool stateTick = false; 43 | Icon? stateIcon; 44 | if (sent) { 45 | stateTick = true; 46 | stateIcon = Icon( 47 | Icons.done, 48 | size: 18, 49 | color: Color(0xFF97AD8E), 50 | ); 51 | } 52 | if (delivered) { 53 | stateTick = true; 54 | stateIcon = Icon( 55 | Icons.done_all, 56 | size: 18, 57 | color: Color(0xFF97AD8E), 58 | ); 59 | } 60 | if (seen) { 61 | stateTick = true; 62 | stateIcon = Icon( 63 | Icons.done_all, 64 | size: 18, 65 | color: Color(0xFF92DEDA), 66 | ); 67 | } 68 | 69 | return Align( 70 | alignment: isSender ? Alignment.topRight : Alignment.topLeft, 71 | child: Padding( 72 | padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), 73 | child: CustomPaint( 74 | painter: _SpecialChatBubbleOne( 75 | color: color, 76 | alignment: isSender ? Alignment.topRight : Alignment.topLeft, 77 | tail: tail), 78 | child: Container( 79 | constraints: constraints ?? 80 | BoxConstraints( 81 | maxWidth: MediaQuery.of(context).size.width * .7, 82 | ), 83 | margin: isSender 84 | ? stateTick 85 | ? EdgeInsets.fromLTRB(7, 7, 14, 7) 86 | : EdgeInsets.fromLTRB(7, 7, 17, 7) 87 | : EdgeInsets.fromLTRB(17, 7, 7, 7), 88 | child: Stack( 89 | children: [ 90 | Padding( 91 | padding: stateTick 92 | ? EdgeInsets.only(right: 20) 93 | : EdgeInsets.symmetric(vertical: 0, horizontal: 0), 94 | child: Text( 95 | text, 96 | style: textStyle, 97 | textAlign: TextAlign.left, 98 | ), 99 | ), 100 | stateIcon != null && stateTick 101 | ? Positioned( 102 | bottom: 0, 103 | right: 0, 104 | child: stateIcon, 105 | ) 106 | : SizedBox( 107 | width: 1, 108 | ), 109 | ], 110 | ), 111 | ), 112 | ), 113 | ), 114 | ); 115 | } 116 | } 117 | 118 | ///custom painter use to create the shape of the chat bubble 119 | /// 120 | /// [color],[alignment] and [tail] can be changed 121 | 122 | class _SpecialChatBubbleOne extends CustomPainter { 123 | final Color color; 124 | final Alignment alignment; 125 | final bool tail; 126 | 127 | _SpecialChatBubbleOne({ 128 | required this.color, 129 | required this.alignment, 130 | required this.tail, 131 | }); 132 | 133 | double _radius = 10.0; 134 | double _x = 10.0; 135 | 136 | @override 137 | void paint(Canvas canvas, Size size) { 138 | if (alignment == Alignment.topRight) { 139 | if (tail) { 140 | canvas.drawRRect( 141 | RRect.fromLTRBAndCorners( 142 | 0, 143 | 0, 144 | size.width - _x, 145 | size.height, 146 | bottomLeft: Radius.circular(_radius), 147 | bottomRight: Radius.circular(_radius), 148 | topLeft: Radius.circular(_radius), 149 | ), 150 | Paint() 151 | ..color = this.color 152 | ..style = PaintingStyle.fill); 153 | var path = new Path(); 154 | path.moveTo(size.width - _x, 0); 155 | path.lineTo(size.width - _x, 10); 156 | path.lineTo(size.width, 0); 157 | canvas.clipPath(path); 158 | canvas.drawRRect( 159 | RRect.fromLTRBAndCorners( 160 | size.width - _x, 161 | 0.0, 162 | size.width, 163 | size.height, 164 | topRight: Radius.circular(3), 165 | ), 166 | Paint() 167 | ..color = this.color 168 | ..style = PaintingStyle.fill); 169 | } else { 170 | canvas.drawRRect( 171 | RRect.fromLTRBAndCorners( 172 | 0, 173 | 0, 174 | size.width - _x, 175 | size.height, 176 | bottomLeft: Radius.circular(_radius), 177 | bottomRight: Radius.circular(_radius), 178 | topLeft: Radius.circular(_radius), 179 | topRight: Radius.circular(_radius), 180 | ), 181 | Paint() 182 | ..color = this.color 183 | ..style = PaintingStyle.fill); 184 | } 185 | } else { 186 | if (tail) { 187 | canvas.drawRRect( 188 | RRect.fromLTRBAndCorners( 189 | _x, 190 | 0, 191 | size.width, 192 | size.height, 193 | bottomRight: Radius.circular(_radius), 194 | topRight: Radius.circular(_radius), 195 | bottomLeft: Radius.circular(_radius), 196 | ), 197 | Paint() 198 | ..color = this.color 199 | ..style = PaintingStyle.fill); 200 | var path = new Path(); 201 | path.moveTo(_x, 0); 202 | path.lineTo(_x, 10); 203 | path.lineTo(0, 0); 204 | canvas.clipPath(path); 205 | canvas.drawRRect( 206 | RRect.fromLTRBAndCorners( 207 | 0, 208 | 0.0, 209 | _x, 210 | size.height, 211 | topLeft: Radius.circular(3), 212 | ), 213 | Paint() 214 | ..color = this.color 215 | ..style = PaintingStyle.fill); 216 | } else { 217 | canvas.drawRRect( 218 | RRect.fromLTRBAndCorners( 219 | _x, 220 | 0, 221 | size.width, 222 | size.height, 223 | bottomRight: Radius.circular(_radius), 224 | topRight: Radius.circular(_radius), 225 | bottomLeft: Radius.circular(_radius), 226 | topLeft: Radius.circular(_radius), 227 | ), 228 | Paint() 229 | ..color = this.color 230 | ..style = PaintingStyle.fill); 231 | } 232 | } 233 | } 234 | 235 | @override 236 | bool shouldRepaint(CustomPainter oldDelegate) { 237 | return true; 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /lib/bubbles/bubble_special_three.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | ///iMessage's chat bubble type 4 | /// 5 | ///chat bubble color can be customized using [color] 6 | ///chat bubble tail can be customized using [tail] 7 | ///chat bubble display message can be changed using [text] 8 | ///[text] is the only required parameter 9 | ///message sender can be changed using [isSender] 10 | ///chat bubble [TextStyle] can be customized using [textStyle] 11 | 12 | class BubbleSpecialThree extends StatelessWidget { 13 | final bool isSender; 14 | final String text; 15 | final bool tail; 16 | final Color color; 17 | final bool sent; 18 | final bool delivered; 19 | final bool seen; 20 | final TextStyle textStyle; 21 | final BoxConstraints? constraints; 22 | 23 | const BubbleSpecialThree({ 24 | Key? key, 25 | this.isSender = true, 26 | this.constraints, 27 | required this.text, 28 | this.color = Colors.white70, 29 | this.tail = true, 30 | this.sent = false, 31 | this.delivered = false, 32 | this.seen = false, 33 | this.textStyle = const TextStyle( 34 | color: Colors.black87, 35 | fontSize: 16, 36 | ), 37 | }) : super(key: key); 38 | 39 | ///chat bubble builder method 40 | @override 41 | Widget build(BuildContext context) { 42 | bool stateTick = false; 43 | Icon? stateIcon; 44 | if (sent) { 45 | stateTick = true; 46 | stateIcon = const Icon( 47 | Icons.done, 48 | size: 18, 49 | color: Color(0xFF97AD8E), 50 | ); 51 | } 52 | if (delivered) { 53 | stateTick = true; 54 | stateIcon = const Icon( 55 | Icons.done_all, 56 | size: 18, 57 | color: Color(0xFF97AD8E), 58 | ); 59 | } 60 | if (seen) { 61 | stateTick = true; 62 | stateIcon = const Icon( 63 | Icons.done_all, 64 | size: 18, 65 | color: Color(0xFF92DEDA), 66 | ); 67 | } 68 | 69 | return Align( 70 | alignment: isSender ? Alignment.topRight : Alignment.topLeft, 71 | child: Padding( 72 | padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), 73 | child: CustomPaint( 74 | painter: _SpecialChatBubbleThree( 75 | color: color, 76 | alignment: isSender ? Alignment.topRight : Alignment.topLeft, 77 | tail: tail), 78 | child: Container( 79 | constraints: constraints ?? 80 | BoxConstraints( 81 | maxWidth: MediaQuery.of(context).size.width * .7, 82 | ), 83 | margin: isSender 84 | ? stateTick 85 | ? const EdgeInsets.fromLTRB(7, 7, 14, 7) 86 | : const EdgeInsets.fromLTRB(7, 7, 17, 7) 87 | : const EdgeInsets.fromLTRB(17, 7, 7, 7), 88 | child: Stack( 89 | children: [ 90 | Padding( 91 | padding: stateTick 92 | ? const EdgeInsets.only(left: 4, right: 20) 93 | : const EdgeInsets.only(left: 4, right: 4), 94 | child: Text( 95 | text, 96 | style: textStyle, 97 | textAlign: TextAlign.left, 98 | ), 99 | ), 100 | stateIcon != null && stateTick 101 | ? Positioned( 102 | bottom: 0, 103 | right: 0, 104 | child: stateIcon, 105 | ) 106 | : const SizedBox( 107 | width: 1, 108 | ), 109 | ], 110 | ), 111 | ), 112 | ), 113 | ), 114 | ); 115 | } 116 | } 117 | 118 | ///custom painter use to create the shape of the chat bubble 119 | /// 120 | /// [color],[alignment] and [tail] can be changed 121 | 122 | class _SpecialChatBubbleThree extends CustomPainter { 123 | final Color color; 124 | final Alignment alignment; 125 | final bool tail; 126 | 127 | _SpecialChatBubbleThree({ 128 | required this.color, 129 | required this.alignment, 130 | required this.tail, 131 | }); 132 | 133 | final double _radius = 10.0; 134 | 135 | @override 136 | void paint(Canvas canvas, Size size) { 137 | var h = size.height; 138 | var w = size.width; 139 | if (alignment == Alignment.topRight) { 140 | if (tail) { 141 | var path = Path(); 142 | 143 | /// starting point 144 | path.moveTo(_radius * 2, 0); 145 | 146 | /// top-left corner 147 | path.quadraticBezierTo(0, 0, 0, _radius * 1.5); 148 | 149 | /// left line 150 | path.lineTo(0, h - _radius * 1.5); 151 | 152 | /// bottom-left corner 153 | path.quadraticBezierTo(0, h, _radius * 2, h); 154 | 155 | /// bottom line 156 | path.lineTo(w - _radius * 3, h); 157 | 158 | /// bottom-right bubble curve 159 | path.quadraticBezierTo( 160 | w - _radius * 1.5, h, w - _radius * 1.5, h - _radius * 0.6); 161 | 162 | /// bottom-right tail curve 1 163 | path.quadraticBezierTo(w - _radius * 1, h, w, h); 164 | 165 | /// bottom-right tail curve 2 166 | path.quadraticBezierTo( 167 | w - _radius * 0.8, h, w - _radius, h - _radius * 1.5); 168 | 169 | /// right line 170 | path.lineTo(w - _radius, _radius * 1.5); 171 | 172 | /// top-right curve 173 | path.quadraticBezierTo(w - _radius, 0, w - _radius * 3, 0); 174 | 175 | canvas.clipPath(path); 176 | canvas.drawRRect( 177 | RRect.fromLTRBR(0, 0, w, h, Radius.zero), 178 | Paint() 179 | ..color = color 180 | ..style = PaintingStyle.fill); 181 | } else { 182 | var path = Path(); 183 | 184 | /// starting point 185 | path.moveTo(_radius * 2, 0); 186 | 187 | /// top-left corner 188 | path.quadraticBezierTo(0, 0, 0, _radius * 1.5); 189 | 190 | /// left line 191 | path.lineTo(0, h - _radius * 1.5); 192 | 193 | /// bottom-left corner 194 | path.quadraticBezierTo(0, h, _radius * 2, h); 195 | 196 | /// bottom line 197 | path.lineTo(w - _radius * 3, h); 198 | 199 | /// bottom-right curve 200 | path.quadraticBezierTo(w - _radius, h, w - _radius, h - _radius * 1.5); 201 | 202 | /// right line 203 | path.lineTo(w - _radius, _radius * 1.5); 204 | 205 | /// top-right curve 206 | path.quadraticBezierTo(w - _radius, 0, w - _radius * 3, 0); 207 | 208 | canvas.clipPath(path); 209 | canvas.drawRRect( 210 | RRect.fromLTRBR(0, 0, w, h, Radius.zero), 211 | Paint() 212 | ..color = color 213 | ..style = PaintingStyle.fill); 214 | } 215 | } else { 216 | if (tail) { 217 | var path = Path(); 218 | 219 | /// starting point 220 | path.moveTo(_radius * 3, 0); 221 | 222 | /// top-left corner 223 | path.quadraticBezierTo(_radius, 0, _radius, _radius * 1.5); 224 | 225 | /// left line 226 | path.lineTo(_radius, h - _radius * 1.5); 227 | // bottom-right tail curve 1 228 | path.quadraticBezierTo(_radius * .8, h, 0, h); 229 | 230 | /// bottom-right tail curve 2 231 | path.quadraticBezierTo( 232 | _radius * 1, h, _radius * 1.5, h - _radius * 0.6); 233 | 234 | /// bottom-left bubble curve 235 | path.quadraticBezierTo(_radius * 1.5, h, _radius * 3, h); 236 | 237 | /// bottom line 238 | path.lineTo(w - _radius * 2, h); 239 | 240 | /// bottom-right curve 241 | path.quadraticBezierTo(w, h, w, h - _radius * 1.5); 242 | 243 | /// right line 244 | path.lineTo(w, _radius * 1.5); 245 | 246 | /// top-right curve 247 | path.quadraticBezierTo(w, 0, w - _radius * 2, 0); 248 | canvas.clipPath(path); 249 | canvas.drawRRect( 250 | RRect.fromLTRBR(0, 0, w, h, Radius.zero), 251 | Paint() 252 | ..color = color 253 | ..style = PaintingStyle.fill); 254 | } else { 255 | var path = Path(); 256 | 257 | /// starting point 258 | path.moveTo(_radius * 3, 0); 259 | 260 | /// top-left corner 261 | path.quadraticBezierTo(_radius, 0, _radius, _radius * 1.5); 262 | 263 | /// left line 264 | path.lineTo(_radius, h - _radius * 1.5); 265 | 266 | /// bottom-left curve 267 | path.quadraticBezierTo(_radius, h, _radius * 3, h); 268 | 269 | /// bottom line 270 | path.lineTo(w - _radius * 2, h); 271 | 272 | /// bottom-right curve 273 | path.quadraticBezierTo(w, h, w, h - _radius * 1.5); 274 | 275 | /// right line 276 | path.lineTo(w, _radius * 1.5); 277 | 278 | /// top-right curve 279 | path.quadraticBezierTo(w, 0, w - _radius * 2, 0); 280 | canvas.clipPath(path); 281 | canvas.drawRRect( 282 | RRect.fromLTRBR(0, 0, w, h, Radius.zero), 283 | Paint() 284 | ..color = color 285 | ..style = PaintingStyle.fill); 286 | } 287 | } 288 | } 289 | 290 | @override 291 | bool shouldRepaint(CustomPainter oldDelegate) { 292 | return true; 293 | } 294 | } 295 | -------------------------------------------------------------------------------- /lib/bubbles/bubble_special_two.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | ///New special chat bubble type 4 | /// 5 | ///chat bubble color can be customized using [color] 6 | ///chat bubble tail can be customized using [tail] 7 | ///chat bubble display message can be changed using [text] 8 | ///[text] is the only required parameter 9 | ///message sender can be changed using [isSender] 10 | ///chat bubble [TextStyle] can be customized using [textStyle] 11 | 12 | class BubbleSpecialTwo extends StatelessWidget { 13 | final bool isSender; 14 | final String text; 15 | final bool tail; 16 | final Color color; 17 | final bool sent; 18 | final bool delivered; 19 | final bool seen; 20 | final TextStyle textStyle; 21 | final BoxConstraints? constraints; 22 | 23 | const BubbleSpecialTwo({ 24 | Key? key, 25 | this.isSender = true, 26 | this.constraints, 27 | required this.text, 28 | this.color = Colors.white70, 29 | this.tail = true, 30 | this.sent = false, 31 | this.delivered = false, 32 | this.seen = false, 33 | this.textStyle = const TextStyle( 34 | color: Colors.black87, 35 | fontSize: 16, 36 | ), 37 | }) : super(key: key); 38 | 39 | ///chat bubble builder method 40 | @override 41 | Widget build(BuildContext context) { 42 | bool stateTick = false; 43 | Icon? stateIcon; 44 | if (sent) { 45 | stateTick = true; 46 | stateIcon = Icon( 47 | Icons.done, 48 | size: 18, 49 | color: Color(0xFF97AD8E), 50 | ); 51 | } 52 | if (delivered) { 53 | stateTick = true; 54 | stateIcon = Icon( 55 | Icons.done_all, 56 | size: 18, 57 | color: Color(0xFF97AD8E), 58 | ); 59 | } 60 | if (seen) { 61 | stateTick = true; 62 | stateIcon = Icon( 63 | Icons.done_all, 64 | size: 18, 65 | color: Color(0xFF92DEDA), 66 | ); 67 | } 68 | 69 | return Align( 70 | alignment: isSender ? Alignment.topRight : Alignment.topLeft, 71 | child: Padding( 72 | padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), 73 | child: CustomPaint( 74 | painter: _SpecialChatBubbleTwo( 75 | color: color, 76 | alignment: isSender ? Alignment.topRight : Alignment.topLeft, 77 | tail: tail), 78 | child: Container( 79 | constraints: constraints ?? 80 | BoxConstraints( 81 | maxWidth: MediaQuery.of(context).size.width * .8, 82 | ), 83 | margin: isSender 84 | ? stateTick 85 | ? EdgeInsets.fromLTRB(7, 7, 14, 7) 86 | : EdgeInsets.fromLTRB(7, 7, 17, 7) 87 | : EdgeInsets.fromLTRB(17, 7, 7, 7), 88 | child: Stack( 89 | children: [ 90 | Padding( 91 | padding: stateTick 92 | ? EdgeInsets.only(right: 20) 93 | : EdgeInsets.symmetric(vertical: 0, horizontal: 0), 94 | child: Text( 95 | text, 96 | style: textStyle, 97 | textAlign: TextAlign.left, 98 | ), 99 | ), 100 | stateIcon != null && stateTick 101 | ? Positioned( 102 | bottom: 0, 103 | right: 0, 104 | child: stateIcon, 105 | ) 106 | : SizedBox( 107 | width: 1, 108 | ), 109 | ], 110 | ), 111 | ), 112 | ), 113 | ), 114 | ); 115 | } 116 | } 117 | 118 | ///custom painter use to create the shape of the chat bubble 119 | /// 120 | /// [color],[alignment] and [tail] can be changed 121 | 122 | class _SpecialChatBubbleTwo extends CustomPainter { 123 | final Color color; 124 | final Alignment alignment; 125 | final bool tail; 126 | 127 | _SpecialChatBubbleTwo({ 128 | required this.color, 129 | required this.alignment, 130 | required this.tail, 131 | }); 132 | 133 | double _radius = 10.0; 134 | double _x = 10.0; 135 | 136 | @override 137 | void paint(Canvas canvas, Size size) { 138 | if (alignment == Alignment.topRight) { 139 | if (tail) { 140 | canvas.drawRRect( 141 | RRect.fromLTRBAndCorners( 142 | 0, 143 | 0, 144 | size.width - 8, 145 | size.height, 146 | bottomLeft: Radius.circular(_radius), 147 | topRight: Radius.circular(_radius), 148 | topLeft: Radius.circular(_radius), 149 | bottomRight: Radius.circular(_radius), 150 | ), 151 | Paint() 152 | ..color = this.color 153 | ..style = PaintingStyle.fill); 154 | var path = new Path(); 155 | path.moveTo(size.width - _x, 4); 156 | path.lineTo(size.width - _x, size.height - 5); 157 | path.lineTo(size.width, size.height); 158 | canvas.clipPath(path); 159 | canvas.drawRRect( 160 | RRect.fromLTRBAndCorners( 161 | size.width - _x, 162 | 0.0, 163 | size.width, 164 | size.height, 165 | ), 166 | Paint() 167 | ..color = this.color 168 | ..style = PaintingStyle.fill); 169 | } else { 170 | canvas.drawRRect( 171 | RRect.fromLTRBAndCorners( 172 | 0, 173 | 0, 174 | size.width - 8, 175 | size.height, 176 | bottomLeft: Radius.circular(_radius), 177 | topRight: Radius.circular(_radius), 178 | topLeft: Radius.circular(_radius), 179 | bottomRight: Radius.circular(_radius), 180 | ), 181 | Paint() 182 | ..color = this.color 183 | ..style = PaintingStyle.fill); 184 | } 185 | } else { 186 | if (tail) { 187 | canvas.drawRRect( 188 | RRect.fromLTRBAndCorners( 189 | 8, 190 | 0, 191 | size.width, 192 | size.height, 193 | bottomRight: Radius.circular(_radius), 194 | topRight: Radius.circular(_radius), 195 | topLeft: Radius.circular(_radius), 196 | bottomLeft: Radius.circular(_radius), 197 | ), 198 | Paint() 199 | ..color = this.color 200 | ..style = PaintingStyle.fill); 201 | var path = new Path(); 202 | path.moveTo(_x, 4); 203 | path.lineTo(0, size.height); 204 | path.lineTo(_x, size.height - 5); 205 | canvas.clipPath(path); 206 | canvas.drawRRect( 207 | RRect.fromLTRBAndCorners( 208 | 0, 209 | 0.0, 210 | _x, 211 | size.height, 212 | topRight: Radius.circular(_radius), 213 | ), 214 | Paint() 215 | ..color = this.color 216 | ..style = PaintingStyle.fill); 217 | } else { 218 | canvas.drawRRect( 219 | RRect.fromLTRBAndCorners( 220 | 8, 221 | 0, 222 | size.width, 223 | size.height, 224 | bottomRight: Radius.circular(_radius), 225 | topRight: Radius.circular(_radius), 226 | topLeft: Radius.circular(_radius), 227 | bottomLeft: Radius.circular(_radius), 228 | ), 229 | Paint() 230 | ..color = this.color 231 | ..style = PaintingStyle.fill); 232 | } 233 | } 234 | } 235 | 236 | @override 237 | bool shouldRepaint(CustomPainter oldDelegate) { 238 | return true; 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /lib/chat_bubbles.dart: -------------------------------------------------------------------------------- 1 | library chat_bubbles; 2 | 3 | /// 4 | /// all the widgets of the package export here 5 | /// CHAT BUBBLES 6 | /// [BubbleNormal] 7 | /// [BubbleSpecialOne] 8 | /// [BubbleSpecialTwo] 9 | /// [BubbleNormalAudio] 10 | /// [BubbleSpecialThree] 11 | /// [BubbleNormalImage] 12 | /// 13 | /// DATE CHIPS 14 | /// [DateChip] 15 | /// 16 | /// MESSAGE BARS 17 | /// [MessageBar] 18 | /// widgets UI components are currently available 19 | /// 20 | /// 21 | /// 22 | export 'bubbles/bubble_normal.dart'; 23 | export 'bubbles/bubble_special_one.dart'; 24 | export 'bubbles/bubble_special_two.dart'; 25 | export 'bubbles/bubble_normal_audio.dart'; 26 | export 'bubbles/bubble_special_three.dart'; 27 | export 'date_chips/date_chip.dart'; 28 | export 'message_bars/message_bar.dart'; 29 | export 'bubbles/bubble_normal_image.dart'; 30 | -------------------------------------------------------------------------------- /lib/date_chips/date_chip.dart: -------------------------------------------------------------------------------- 1 | import 'package:chat_bubbles/algo/algo.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | ///[DateChip] use to show the date breakers on the chat view 5 | ///[date] parameter is required 6 | ///[color] parameter is optional default color code `8AD3D5` 7 | /// 8 | /// 9 | class DateChip extends StatelessWidget { 10 | final DateTime date; 11 | final Color color; 12 | 13 | /// 14 | /// 15 | /// 16 | const DateChip({ 17 | Key? key, 18 | required this.date, 19 | this.color = const Color(0x558AD3D5), 20 | }) : super(key: key); 21 | @override 22 | Widget build(BuildContext context) { 23 | return Center( 24 | child: Padding( 25 | padding: const EdgeInsets.only( 26 | top: 7, 27 | bottom: 7, 28 | ), 29 | child: Container( 30 | decoration: BoxDecoration( 31 | borderRadius: BorderRadius.all(Radius.circular(6)), 32 | color: color, 33 | ), 34 | child: Padding( 35 | padding: const EdgeInsets.all(5.0), 36 | child: Text( 37 | Algo.dateChipText(date), 38 | ), 39 | ), 40 | ), 41 | ), 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/message_bars/message_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | ///Normal Message bar with more actions 4 | /// 5 | /// following attributes can be modified 6 | /// 7 | /// 8 | /// # BOOLEANS 9 | /// [replying] is the additional reply widget top of the message bar 10 | /// 11 | /// # STRINGS 12 | /// [replyingTo] is the string to tag the replying message 13 | /// [messageBarHitText] is the string to show as message bar hint 14 | /// 15 | /// # WIDGETS 16 | /// [actions] are the additional leading action buttons like camera 17 | /// and file select 18 | /// 19 | /// # COLORS 20 | /// [replyWidgetColor] is the reply widget color 21 | /// [replyIconColor] is the reply icon color on the left side of reply widget 22 | /// [replyCloseColor] is the close icon color on the right side of the reply 23 | /// widget 24 | /// [messageBarColor] is the color of the message bar 25 | /// [sendButtonColor] is the color of the send button 26 | /// [messageBarHintStyle] is the style of the message bar hint 27 | /// 28 | /// # METHODS 29 | /// [onTextChanged] is the function which triggers after text every text change 30 | /// [onSend] is the send button action 31 | /// [onTapCloseReply] is the close button action of the close button on the 32 | /// reply widget usually change [replying] attribute to `false` 33 | 34 | class MessageBar extends StatelessWidget { 35 | final bool replying; 36 | final String replyingTo; 37 | final List actions; 38 | final TextEditingController _textController = TextEditingController(); 39 | final Color replyWidgetColor; 40 | final Color replyIconColor; 41 | final Color replyCloseColor; 42 | final Color messageBarColor; 43 | final String messageBarHintText; 44 | final TextStyle messageBarHintStyle; 45 | final TextStyle textFieldTextStyle; 46 | final Color sendButtonColor; 47 | final void Function(String)? onTextChanged; 48 | final void Function(String)? onSend; 49 | final void Function()? onTapCloseReply; 50 | 51 | /// [MessageBar] constructor 52 | /// 53 | /// 54 | MessageBar({ 55 | this.replying = false, 56 | this.replyingTo = "", 57 | this.actions = const [], 58 | this.replyWidgetColor = const Color(0xffF4F4F5), 59 | this.replyIconColor = Colors.blue, 60 | this.replyCloseColor = Colors.black12, 61 | this.messageBarColor = const Color(0xffF4F4F5), 62 | this.sendButtonColor = Colors.blue, 63 | this.messageBarHintText = "Type your message here", 64 | this.messageBarHintStyle = const TextStyle(fontSize: 16), 65 | this.textFieldTextStyle = const TextStyle(color: Colors.black), 66 | this.onTextChanged, 67 | this.onSend, 68 | this.onTapCloseReply, 69 | }); 70 | 71 | /// [MessageBar] builder method 72 | /// 73 | @override 74 | Widget build(BuildContext context) { 75 | return Align( 76 | alignment: Alignment.bottomCenter, 77 | child: Container( 78 | child: Column( 79 | mainAxisAlignment: MainAxisAlignment.end, 80 | children: [ 81 | replying 82 | ? Container( 83 | color: replyWidgetColor, 84 | padding: const EdgeInsets.symmetric( 85 | vertical: 8, 86 | horizontal: 16, 87 | ), 88 | child: Row( 89 | children: [ 90 | Icon( 91 | Icons.reply, 92 | color: replyIconColor, 93 | size: 24, 94 | ), 95 | Expanded( 96 | child: Container( 97 | child: Text( 98 | 'Re : ' + replyingTo, 99 | overflow: TextOverflow.ellipsis, 100 | ), 101 | ), 102 | ), 103 | InkWell( 104 | onTap: onTapCloseReply, 105 | child: Icon( 106 | Icons.close, 107 | color: replyCloseColor, 108 | size: 24, 109 | ), 110 | ), 111 | ], 112 | )) 113 | : Container(), 114 | replying 115 | ? Container( 116 | height: 1, 117 | color: Colors.grey.shade300, 118 | ) 119 | : Container(), 120 | Container( 121 | color: messageBarColor, 122 | padding: const EdgeInsets.symmetric( 123 | vertical: 8, 124 | horizontal: 16, 125 | ), 126 | child: Row( 127 | children: [ 128 | ...actions, 129 | Expanded( 130 | child: Container( 131 | child: TextField( 132 | controller: _textController, 133 | keyboardType: TextInputType.multiline, 134 | textCapitalization: TextCapitalization.sentences, 135 | minLines: 1, 136 | maxLines: 3, 137 | onChanged: onTextChanged, 138 | style: textFieldTextStyle, 139 | decoration: InputDecoration( 140 | hintText: messageBarHintText, 141 | hintMaxLines: 1, 142 | contentPadding: const EdgeInsets.symmetric( 143 | horizontal: 8.0, vertical: 10), 144 | hintStyle: messageBarHintStyle, 145 | fillColor: Colors.white, 146 | filled: true, 147 | enabledBorder: OutlineInputBorder( 148 | borderRadius: BorderRadius.circular(30.0), 149 | borderSide: const BorderSide( 150 | color: Colors.white, 151 | width: 0.2, 152 | ), 153 | ), 154 | focusedBorder: OutlineInputBorder( 155 | borderRadius: BorderRadius.circular(30.0), 156 | borderSide: const BorderSide( 157 | color: Colors.black26, 158 | width: 0.2, 159 | ), 160 | ), 161 | ), 162 | ), 163 | ), 164 | ), 165 | Padding( 166 | padding: const EdgeInsets.only(left: 16), 167 | child: InkWell( 168 | child: Icon( 169 | Icons.send, 170 | color: sendButtonColor, 171 | size: 24, 172 | ), 173 | onTap: () { 174 | if (_textController.text.trim() != '') { 175 | if (onSend != null) { 176 | onSend!(_textController.text.trim()); 177 | } 178 | _textController.text = ''; 179 | } 180 | }, 181 | ), 182 | ), 183 | ], 184 | ), 185 | ), 186 | ], 187 | ), 188 | ), 189 | ); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /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 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.11.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.1" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.3.0" 28 | clock: 29 | dependency: transitive 30 | description: 31 | name: clock 32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.1.1" 36 | collection: 37 | dependency: transitive 38 | description: 39 | name: collection 40 | sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.19.0" 44 | fake_async: 45 | dependency: transitive 46 | description: 47 | name: fake_async 48 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.3.1" 52 | flutter: 53 | dependency: "direct main" 54 | description: flutter 55 | source: sdk 56 | version: "0.0.0" 57 | flutter_test: 58 | dependency: "direct dev" 59 | description: flutter 60 | source: sdk 61 | version: "0.0.0" 62 | http: 63 | dependency: transitive 64 | description: 65 | name: http 66 | sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 67 | url: "https://pub.dev" 68 | source: hosted 69 | version: "1.2.2" 70 | http_parser: 71 | dependency: transitive 72 | description: 73 | name: http_parser 74 | sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" 75 | url: "https://pub.dev" 76 | source: hosted 77 | version: "4.1.2" 78 | intl: 79 | dependency: "direct main" 80 | description: 81 | name: intl 82 | sha256: "00f33b908655e606b86d2ade4710a231b802eec6f11e87e4ea3783fd72077a50" 83 | url: "https://pub.dev" 84 | source: hosted 85 | version: "0.20.1" 86 | leak_tracker: 87 | dependency: transitive 88 | description: 89 | name: leak_tracker 90 | sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" 91 | url: "https://pub.dev" 92 | source: hosted 93 | version: "10.0.7" 94 | leak_tracker_flutter_testing: 95 | dependency: transitive 96 | description: 97 | name: leak_tracker_flutter_testing 98 | sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" 99 | url: "https://pub.dev" 100 | source: hosted 101 | version: "3.0.8" 102 | leak_tracker_testing: 103 | dependency: transitive 104 | description: 105 | name: leak_tracker_testing 106 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 107 | url: "https://pub.dev" 108 | source: hosted 109 | version: "3.0.1" 110 | matcher: 111 | dependency: transitive 112 | description: 113 | name: matcher 114 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb 115 | url: "https://pub.dev" 116 | source: hosted 117 | version: "0.12.16+1" 118 | material_color_utilities: 119 | dependency: transitive 120 | description: 121 | name: material_color_utilities 122 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 123 | url: "https://pub.dev" 124 | source: hosted 125 | version: "0.11.1" 126 | meta: 127 | dependency: transitive 128 | description: 129 | name: meta 130 | sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 131 | url: "https://pub.dev" 132 | source: hosted 133 | version: "1.15.0" 134 | path: 135 | dependency: transitive 136 | description: 137 | name: path 138 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" 139 | url: "https://pub.dev" 140 | source: hosted 141 | version: "1.9.0" 142 | sky_engine: 143 | dependency: transitive 144 | description: flutter 145 | source: sdk 146 | version: "0.0.0" 147 | source_span: 148 | dependency: transitive 149 | description: 150 | name: source_span 151 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 152 | url: "https://pub.dev" 153 | source: hosted 154 | version: "1.10.0" 155 | stack_trace: 156 | dependency: transitive 157 | description: 158 | name: stack_trace 159 | sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "1.12.0" 163 | stream_channel: 164 | dependency: transitive 165 | description: 166 | name: stream_channel 167 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "2.1.2" 171 | string_scanner: 172 | dependency: transitive 173 | description: 174 | name: string_scanner 175 | sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "1.3.0" 179 | term_glyph: 180 | dependency: transitive 181 | description: 182 | name: term_glyph 183 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 184 | url: "https://pub.dev" 185 | source: hosted 186 | version: "1.2.1" 187 | test_api: 188 | dependency: transitive 189 | description: 190 | name: test_api 191 | sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "0.7.3" 195 | typed_data: 196 | dependency: transitive 197 | description: 198 | name: typed_data 199 | sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 200 | url: "https://pub.dev" 201 | source: hosted 202 | version: "1.4.0" 203 | vector_math: 204 | dependency: transitive 205 | description: 206 | name: vector_math 207 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 208 | url: "https://pub.dev" 209 | source: hosted 210 | version: "2.1.4" 211 | vm_service: 212 | dependency: transitive 213 | description: 214 | name: vm_service 215 | sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b 216 | url: "https://pub.dev" 217 | source: hosted 218 | version: "14.3.0" 219 | web: 220 | dependency: transitive 221 | description: 222 | name: web 223 | sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb 224 | url: "https://pub.dev" 225 | source: hosted 226 | version: "1.1.0" 227 | sdks: 228 | dart: ">=3.5.0 <4.0.0" 229 | flutter: ">=3.18.0-18.0.pre.54" 230 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: chat_bubbles 2 | description: Flutter chat bubble widgets, similar to Whatsapp and more shapes. Easy to use and implement 3 | chat bubbles. 4 | version: 1.7.0 5 | homepage: https://github.com/prahack/chat_bubbles 6 | 7 | environment: 8 | sdk: ">=2.12.0 <4.0.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | intl: ^0.20.1 14 | 15 | dev_dependencies: 16 | flutter_test: 17 | sdk: flutter 18 | 19 | screenshots: 20 | - description: The Flutter chat_bubbles package logo. 21 | path: images/logo/logo.png 22 | 23 | flutter: 24 | 25 | -------------------------------------------------------------------------------- /test/chatbubbles_test.dart: -------------------------------------------------------------------------------- 1 | void main() {} 2 | --------------------------------------------------------------------------------