diff --git a/CHANGELOG.md b/CHANGELOG.md index f3d7f80..fe82d04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [1.3.0] - 03/07/2022 + +* Add `MessageBar` widget + ## [1.2.0] - 04/02/2022 * Add iMessage's chat bubble shape bubble widget (`BubbleSpecialThree`). diff --git a/README.md b/README.md index e050ebc..fcf6328 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Add this to your package's `pubspec.yaml` file: ```yaml dependencies: - chat_bubbles: ^1.2.0 + chat_bubbles: ^1.3.0 ``` ## Usage @@ -129,8 +129,39 @@ BubbleSpecialThree( ), ``` +### Massage bar example + + + +```dart +MessageBar( + onSend: (_) => print(_), + actions: [ + InkWell( + child: Icon( + Icons.add, + color: Colors.black, + size: 24, + ), + onTap: () {}, + ), + Padding( + padding: EdgeInsets.only(left: 8, right: 8), + child: InkWell( + child: Icon( + Icons.camera_alt, + color: Colors.green, + size: 24, + ), + onTap: () {}, + ), + ), + ], + ), +``` + ### Main example (Chat View) - + Checkout the plugin example to figure out more. @@ -148,154 +179,182 @@ Widget build(BuildContext context) { appBar: AppBar( title: Text(widget.title), ), - body: Center( - child: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - BubbleNormalAudio( - color: Color(0xFFE8E8EE), - duration: duration.inSeconds.toDouble(), - position: position.inSeconds.toDouble(), - isPlaying: isPlaying, - isLoading: isLoading, - isPause: isPause, - onSeekChanged: _changeSeek, - onPlayPauseButtonClick: _playAudio, - sent: true, - ), - BubbleNormal( - text: 'bubble normal with tail', - isSender: false, - color: Color(0xFF1B97F3), - tail: true, - textStyle: TextStyle( - fontSize: 20, - color: Colors.white, + body: Stack( + children: [ + SingleChildScrollView( + child: Column( + children: [ + BubbleNormalAudio( + color: Color(0xFFE8E8EE), + duration: duration.inSeconds.toDouble(), + position: position.inSeconds.toDouble(), + isPlaying: isPlaying, + isLoading: isLoading, + isPause: isPause, + onSeekChanged: _changeSeek, + onPlayPauseButtonClick: _playAudio, + sent: true, ), - ), - BubbleNormal( - text: 'bubble normal with tail', - isSender: true, - color: Color(0xFFE8E8EE), - tail: true, - sent: true, - ), - DateChip( - date: new DateTime(now.year, now.month, now.day - 2), - ), - BubbleNormal( - text: 'bubble normal without tail', - isSender: false, - color: Color(0xFF1B97F3), - tail: false, - textStyle: TextStyle( - fontSize: 20, - color: Colors.white, + BubbleNormal( + text: 'bubble normal with tail', + isSender: false, + color: Color(0xFF1B97F3), + tail: true, + textStyle: TextStyle( + fontSize: 20, + color: Colors.white, + ), ), - ), - BubbleNormal( - text: 'bubble normal without tail', - color: Color(0xFFE8E8EE), - tail: false, - sent: true, - seen: true, - delivered: true, - ), - BubbleSpecialOne( - text: 'bubble special one with tail', - isSender: false, - color: Color(0xFF1B97F3), - textStyle: TextStyle( - fontSize: 20, - color: Colors.white, + BubbleNormal( + text: 'bubble normal with tail', + isSender: true, + color: Color(0xFFE8E8EE), + tail: true, + sent: true, ), - ), - DateChip( - date: new DateTime(now.year, now.month, now.day - 1), - ), - BubbleSpecialOne( - text: 'bubble special one with tail', - color: Color(0xFFE8E8EE), - seen: true, - ), - BubbleSpecialOne( - text: 'bubble special one without tail', - isSender: false, - tail: false, - color: Color(0xFF1B97F3), - textStyle: TextStyle( - fontSize: 20, - color: Colors.black, + DateChip( + date: new DateTime(now.year, now.month, now.day - 2), ), - ), - BubbleSpecialOne( - text: 'bubble special one without tail', - tail: false, - color: Color(0xFFE8E8EE), - sent: true, - ), - BubbleSpecialTwo( - text: 'bubble special tow with tail', - isSender: false, - color: Color(0xFF1B97F3), - textStyle: TextStyle( - fontSize: 20, - color: Colors.black, + BubbleNormal( + text: 'bubble normal without tail', + isSender: false, + color: Color(0xFF1B97F3), + tail: false, + textStyle: TextStyle( + fontSize: 20, + color: Colors.white, + ), ), - ), - DateChip( - date: now, - ), - BubbleSpecialTwo( - text: 'bubble special tow with tail', - isSender: true, - color: Color(0xFFE8E8EE), - sent: true, - ), - BubbleSpecialTwo( - text: 'bubble special tow without tail', - isSender: false, - tail: false, - color: Color(0xFF1B97F3), - textStyle: TextStyle( - fontSize: 20, + BubbleNormal( + text: 'bubble normal without tail', + color: Color(0xFFE8E8EE), + tail: false, + sent: true, + seen: true, + delivered: true, + ), + BubbleSpecialOne( + text: 'bubble special one with tail', + isSender: false, + color: Color(0xFF1B97F3), + textStyle: TextStyle( + fontSize: 20, + color: Colors.white, + ), + ), + DateChip( + date: new DateTime(now.year, now.month, now.day - 1), + ), + BubbleSpecialOne( + text: 'bubble special one with tail', + color: Color(0xFFE8E8EE), + seen: true, + ), + BubbleSpecialOne( + text: 'bubble special one without tail', + isSender: false, + tail: false, + color: Color(0xFF1B97F3), + textStyle: TextStyle( + fontSize: 20, + color: Colors.black, + ), + ), + BubbleSpecialOne( + text: 'bubble special one without tail', + tail: false, + color: Color(0xFFE8E8EE), + sent: true, + ), + BubbleSpecialTwo( + text: 'bubble special tow with tail', + isSender: false, + color: Color(0xFF1B97F3), + textStyle: TextStyle( + fontSize: 20, + color: Colors.black, + ), + ), + DateChip( + date: now, + ), + BubbleSpecialTwo( + text: 'bubble special tow with tail', + isSender: true, + color: Color(0xFFE8E8EE), + sent: true, + ), + BubbleSpecialTwo( + text: 'bubble special tow without tail', + isSender: false, + tail: false, + color: Color(0xFF1B97F3), + textStyle: TextStyle( + fontSize: 20, + color: Colors.black, + ), + ), + BubbleSpecialTwo( + text: 'bubble special tow without tail', + tail: false, + color: Color(0xFFE8E8EE), + delivered: true, + ), + BubbleSpecialThree( + text: 'bubble special three without tail', + color: Color(0xFF1B97F3), + tail: false, + textStyle: TextStyle(color: Colors.white, fontSize: 16), + ), + BubbleSpecialThree( + text: 'bubble special three with tail', + color: Color(0xFF1B97F3), + tail: true, + textStyle: TextStyle(color: Colors.white, fontSize: 16), + ), + BubbleSpecialThree( + text: "bubble special three without tail", + color: Color(0xFFE8E8EE), + tail: false, + isSender: false, + ), + BubbleSpecialThree( + text: "bubble special three with tail", + color: Color(0xFFE8E8EE), + tail: true, + isSender: false, + ), + SizedBox( + height: 100, + ) + ], + ), + ), + MessageBar( + onSend: (_) => print(_), + actions: [ + InkWell( + child: Icon( + Icons.add, color: Colors.black, + size: 24, ), + onTap: () {}, ), - BubbleSpecialTwo( - text: 'bubble special tow without tail', - tail: false, - color: Color(0xFFE8E8EE), - delivered: true, - ), - BubbleSpecialThree( - text: 'bubble special three without tail', - color: Color(0xFF1B97F3), - tail: false, - textStyle: TextStyle(color: Colors.white, fontSize: 16), - ), - BubbleSpecialThree( - text: 'bubble special three with tail', - color: Color(0xFF1B97F3), - tail: true, - textStyle: TextStyle(color: Colors.white, fontSize: 16), - ), - BubbleSpecialThree( - text: "bubble special three without tail", - color: Color(0xFFE8E8EE), - tail: false, - isSender: false, - ), - BubbleSpecialThree( - text: "bubble special three with tail", - color: Color(0xFFE8E8EE), - tail: true, - isSender: false, + Padding( + padding: EdgeInsets.only(left: 8, right: 8), + child: InkWell( + child: Icon( + Icons.camera_alt, + color: Colors.green, + size: 24, + ), + onTap: () {}, + ), ), ], ), - ), + ], ), // This trailing comma makes auto-formatting nicer for build methods. ); diff --git a/example/lib/main.dart b/example/lib/main.dart index 8cdac16..f33a423 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -40,154 +40,182 @@ class _MyHomePageState extends State { appBar: AppBar( title: Text(widget.title), ), - body: Center( - child: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - BubbleNormalAudio( - color: Color(0xFFE8E8EE), - duration: duration.inSeconds.toDouble(), - position: position.inSeconds.toDouble(), - isPlaying: isPlaying, - isLoading: isLoading, - isPause: isPause, - onSeekChanged: _changeSeek, - onPlayPauseButtonClick: _playAudio, - sent: true, - ), - BubbleNormal( - text: 'bubble normal with tail', - isSender: false, - color: Color(0xFF1B97F3), - tail: true, - textStyle: TextStyle( - fontSize: 20, - color: Colors.white, + body: Stack( + children: [ + SingleChildScrollView( + child: Column( + children: [ + BubbleNormalAudio( + color: Color(0xFFE8E8EE), + duration: duration.inSeconds.toDouble(), + position: position.inSeconds.toDouble(), + isPlaying: isPlaying, + isLoading: isLoading, + isPause: isPause, + onSeekChanged: _changeSeek, + onPlayPauseButtonClick: _playAudio, + sent: true, ), - ), - BubbleNormal( - text: 'bubble normal with tail', - isSender: true, - color: Color(0xFFE8E8EE), - tail: true, - sent: true, - ), - DateChip( - date: new DateTime(now.year, now.month, now.day - 2), - ), - BubbleNormal( - text: 'bubble normal without tail', - isSender: false, - color: Color(0xFF1B97F3), - tail: false, - textStyle: TextStyle( - fontSize: 20, - color: Colors.white, + BubbleNormal( + text: 'bubble normal with tail', + isSender: false, + color: Color(0xFF1B97F3), + tail: true, + textStyle: TextStyle( + fontSize: 20, + color: Colors.white, + ), ), - ), - BubbleNormal( - text: 'bubble normal without tail', - color: Color(0xFFE8E8EE), - tail: false, - sent: true, - seen: true, - delivered: true, - ), - BubbleSpecialOne( - text: 'bubble special one with tail', - isSender: false, - color: Color(0xFF1B97F3), - textStyle: TextStyle( - fontSize: 20, - color: Colors.white, + BubbleNormal( + text: 'bubble normal with tail', + isSender: true, + color: Color(0xFFE8E8EE), + tail: true, + sent: true, ), - ), - DateChip( - date: new DateTime(now.year, now.month, now.day - 1), - ), - BubbleSpecialOne( - text: 'bubble special one with tail', - color: Color(0xFFE8E8EE), - seen: true, - ), - BubbleSpecialOne( - text: 'bubble special one without tail', - isSender: false, - tail: false, - color: Color(0xFF1B97F3), - textStyle: TextStyle( - fontSize: 20, - color: Colors.black, + DateChip( + date: new DateTime(now.year, now.month, now.day - 2), ), - ), - BubbleSpecialOne( - text: 'bubble special one without tail', - tail: false, - color: Color(0xFFE8E8EE), - sent: true, - ), - BubbleSpecialTwo( - text: 'bubble special tow with tail', - isSender: false, - color: Color(0xFF1B97F3), - textStyle: TextStyle( - fontSize: 20, - color: Colors.black, + BubbleNormal( + text: 'bubble normal without tail', + isSender: false, + color: Color(0xFF1B97F3), + tail: false, + textStyle: TextStyle( + fontSize: 20, + color: Colors.white, + ), ), - ), - DateChip( - date: now, - ), - BubbleSpecialTwo( - text: 'bubble special tow with tail', - isSender: true, - color: Color(0xFFE8E8EE), - sent: true, - ), - BubbleSpecialTwo( - text: 'bubble special tow without tail', - isSender: false, - tail: false, - color: Color(0xFF1B97F3), - textStyle: TextStyle( - fontSize: 20, + BubbleNormal( + text: 'bubble normal without tail', + color: Color(0xFFE8E8EE), + tail: false, + sent: true, + seen: true, + delivered: true, + ), + BubbleSpecialOne( + text: 'bubble special one with tail', + isSender: false, + color: Color(0xFF1B97F3), + textStyle: TextStyle( + fontSize: 20, + color: Colors.white, + ), + ), + DateChip( + date: new DateTime(now.year, now.month, now.day - 1), + ), + BubbleSpecialOne( + text: 'bubble special one with tail', + color: Color(0xFFE8E8EE), + seen: true, + ), + BubbleSpecialOne( + text: 'bubble special one without tail', + isSender: false, + tail: false, + color: Color(0xFF1B97F3), + textStyle: TextStyle( + fontSize: 20, + color: Colors.black, + ), + ), + BubbleSpecialOne( + text: 'bubble special one without tail', + tail: false, + color: Color(0xFFE8E8EE), + sent: true, + ), + BubbleSpecialTwo( + text: 'bubble special tow with tail', + isSender: false, + color: Color(0xFF1B97F3), + textStyle: TextStyle( + fontSize: 20, + color: Colors.black, + ), + ), + DateChip( + date: now, + ), + BubbleSpecialTwo( + text: 'bubble special tow with tail', + isSender: true, + color: Color(0xFFE8E8EE), + sent: true, + ), + BubbleSpecialTwo( + text: 'bubble special tow without tail', + isSender: false, + tail: false, + color: Color(0xFF1B97F3), + textStyle: TextStyle( + fontSize: 20, + color: Colors.black, + ), + ), + BubbleSpecialTwo( + text: 'bubble special tow without tail', + tail: false, + color: Color(0xFFE8E8EE), + delivered: true, + ), + BubbleSpecialThree( + text: 'bubble special three without tail', + color: Color(0xFF1B97F3), + tail: false, + textStyle: TextStyle(color: Colors.white, fontSize: 16), + ), + BubbleSpecialThree( + text: 'bubble special three with tail', + color: Color(0xFF1B97F3), + tail: true, + textStyle: TextStyle(color: Colors.white, fontSize: 16), + ), + BubbleSpecialThree( + text: "bubble special three without tail", + color: Color(0xFFE8E8EE), + tail: false, + isSender: false, + ), + BubbleSpecialThree( + text: "bubble special three with tail", + color: Color(0xFFE8E8EE), + tail: true, + isSender: false, + ), + SizedBox( + height: 100, + ) + ], + ), + ), + MessageBar( + onSend: (_) => print(_), + actions: [ + InkWell( + child: Icon( + Icons.add, color: Colors.black, + size: 24, ), + onTap: () {}, ), - BubbleSpecialTwo( - text: 'bubble special tow without tail', - tail: false, - color: Color(0xFFE8E8EE), - delivered: true, - ), - BubbleSpecialThree( - text: 'bubble special three without tail', - color: Color(0xFF1B97F3), - tail: false, - textStyle: TextStyle(color: Colors.white, fontSize: 16), - ), - BubbleSpecialThree( - text: 'bubble special three with tail', - color: Color(0xFF1B97F3), - tail: true, - textStyle: TextStyle(color: Colors.white, fontSize: 16), - ), - BubbleSpecialThree( - text: "bubble special three without tail", - color: Color(0xFFE8E8EE), - tail: false, - isSender: false, - ), - BubbleSpecialThree( - text: "bubble special three with tail", - color: Color(0xFFE8E8EE), - tail: true, - isSender: false, + Padding( + padding: EdgeInsets.only(left: 8, right: 8), + child: InkWell( + child: Icon( + Icons.camera_alt, + color: Colors.green, + size: 24, + ), + onTap: () {}, + ), ), ], ), - ), + ], ), // This trailing comma makes auto-formatting nicer for build methods. ); diff --git a/example/pubspec.lock b/example/pubspec.lock index 3decfd2..f84091b 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -42,7 +42,7 @@ packages: path: ".." relative: true source: path - version: "1.1.0" + version: "1.2.0" clock: dependency: transitive description: diff --git a/images/screenshots/2022_7_3_main1.png b/images/screenshots/2022_7_3_main1.png new file mode 100644 index 0000000..f2aa1d8 Binary files /dev/null and b/images/screenshots/2022_7_3_main1.png differ diff --git a/images/screenshots/2022_7_3_main2.png b/images/screenshots/2022_7_3_main2.png new file mode 100644 index 0000000..79521a8 Binary files /dev/null and b/images/screenshots/2022_7_3_main2.png differ diff --git a/images/screenshots/messagebar.jpeg b/images/screenshots/messagebar.jpeg new file mode 100644 index 0000000..a2da189 Binary files /dev/null and b/images/screenshots/messagebar.jpeg differ diff --git a/lib/chat_bubbles.dart b/lib/chat_bubbles.dart index 03343ec..e289840 100644 --- a/lib/chat_bubbles.dart +++ b/lib/chat_bubbles.dart @@ -2,12 +2,18 @@ library chat_bubbles; /// /// all the widgets of the package export here +/// CHAT BUBBLES /// [BubbleNormal] /// [BubbleSpecialOne] /// [BubbleSpecialTwo] -/// [DateChip] /// [BubbleNormalAudio] /// [BubbleSpecialThree] +/// +/// DATE CHIPS +/// [DateChip] +/// +/// MESSAGE BARS +/// [MessageBar] /// widgets UI components are currently available /// /// @@ -15,6 +21,7 @@ library chat_bubbles; export 'bubbles/bubble_normal.dart'; export 'bubbles/bubble_special_one.dart'; export 'bubbles/bubble_special_two.dart'; -export 'date_chips/date_chip.dart'; export 'bubbles/bubble_normal_audio.dart'; export 'bubbles/bubble_special_three.dart'; +export 'date_chips/date_chip.dart'; +export 'message_bars/message_bar.dart'; diff --git a/lib/message_bars/message_bar.dart b/lib/message_bars/message_bar.dart new file mode 100644 index 0000000..5452054 --- /dev/null +++ b/lib/message_bars/message_bar.dart @@ -0,0 +1,184 @@ +import 'package:flutter/material.dart'; + +///Normal Message bar with more actions +/// +/// following attributes can be modified +/// +/// +/// # BOOLEANS +/// [replying] is additional reply widget top of the message bar +/// +/// # STRINGS +/// [replyingTo] is a string to tag the replying message +/// +/// # WIDGETS +/// [actions] are the additional leading action buttons like camera +/// and file select +/// +/// # COLORS +/// [replyWidgetColor] is reply widget color +/// [replyIconColor] is the reply icon color on the left side of reply widget +/// [replyCloseColor] is the close icon color on the right side of the reply +/// widget +/// [messageBarColor] is the color of the message bar +/// [sendButtonColor] is the color of the send button +/// +/// # METHODS +/// [onTextChanged] is function which triggers after text every text change +/// [onSend] is send button action +/// [onTapCloseReply] is close button action of the close button on the +/// reply widget usually change [replying] attribute to `false` + +class MessageBar extends StatelessWidget { + final bool replying; + final String replyingTo; + final List actions; + final TextEditingController _textController = TextEditingController(); + final Color replyWidgetColor; + final Color replyIconColor; + final Color replyCloseColor; + final Color messageBarColor; + final Color sendButtonColor; + final void Function(String)? onTextChanged; + final void Function(String)? onSend; + final void Function()? onTapCloseReply; + + /// [MessageBar] constructor + /// + /// + MessageBar({ + this.replying = false, + this.replyingTo = "", + this.actions = const [], + this.replyWidgetColor = const Color(0xffF4F4F5), + this.replyIconColor = Colors.blue, + this.replyCloseColor = Colors.black12, + this.messageBarColor = const Color(0xffF4F4F5), + this.sendButtonColor = Colors.blue, + this.onTextChanged, + this.onSend, + this.onTapCloseReply, + }); + + /// [MessageBar] builder method + /// + @override + Widget build(BuildContext context) { + return Align( + alignment: Alignment.bottomCenter, + child: Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + replying + ? Container( + color: replyWidgetColor, + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 16, + ), + child: Row( + children: [ + Icon( + Icons.reply, + color: replyIconColor, + size: 24, + ), + Expanded( + child: Container( + child: Text( + 'Re : ' + replyingTo, + overflow: TextOverflow.ellipsis, + ), + ), + ), + InkWell( + onTap: onTapCloseReply, + child: Icon( + Icons.close, + color: replyCloseColor, + size: 24, + ), + ), + ], + )) + : Container(), + replying + ? Container( + height: 1, + color: Colors.grey.shade300, + ) + : Container(), + Container( + color: messageBarColor, + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 16, + ), + child: Row( + children: [ + ...actions, + Expanded( + child: Container( + child: TextField( + controller: _textController, + keyboardType: TextInputType.multiline, + textCapitalization: TextCapitalization.sentences, + minLines: 1, + maxLines: 3, + onChanged: onTextChanged, + decoration: InputDecoration( + hintText: "Type your message here", + hintMaxLines: 1, + contentPadding: const EdgeInsets.symmetric( + horizontal: 8.0, vertical: 10), + hintStyle: TextStyle( + fontSize: 16, + ), + fillColor: Colors.white, + filled: true, + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30.0), + borderSide: const BorderSide( + color: Colors.white, + width: 0.2, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30.0), + borderSide: const BorderSide( + color: Colors.black26, + width: 0.2, + ), + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 16), + child: InkWell( + child: Icon( + Icons.send, + color: sendButtonColor, + size: 24, + ), + onTap: () { + if (_textController.text.trim() != '') { + if (onSend != null) { + onSend!(_textController.text.trim()); + } + _textController.text = ''; + } + }, + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 8676813..7d3c28e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: chat_bubbles description: Flutter chat bubble widgets, similar to Whatsapp and more shapes. Easy to use and implement chat bubbles. -version: 1.2.0 +version: 1.3.0 homepage: https://github.com/prahack/chat_bubbles environment: