dash_chat 1.1.13

  • Readme
  • Changelog
  • Example
  • Installing
  • 96

💬 Dash Chat

The most complete Chat UI for flutter

Inspired by react-native-gifted-chat. Highly customizable and helps developing chat UI faster.

Usage 💻 #

To use this package, add dash_chat as a dependency in your pubspec.yaml file.

Features 🔮 #

  • Fully customizable components
  • Copy messages to clipboard
  • Multi-line TextInput
  • Touchable links using flutter_parsed_text
  • Avatar as user's initials
  • Quick Reply messages
  • Load earlier messages
  • Scroll to bottom Widget
  • Composer actions (to attach photos, etc.) - WIP

Message object 📦 #

example, Chat Message

ChatMessage(
        text: "Hello",
        user: ChatUser(
          name: "Fayeed",
          uid: "123456789",
          avatar: "https://www.wrappixel.com/ampleadmin/assets/images/users/4.jpg",
        ),
        createdAt: DateTime.now(),
        image: "http://www.sclance.com/images/picture/Picture_753248.jpg",
    );

example, Chat Message with Quick Replies

ChatMessage(
        text: "This is a quick reply example.",
        user: ChatUser(),
        createdAt: DateTime.now(),
        quickReplies: QuickReplies(
          values: <Reply>[
            Reply(
              title: "😋 Yes",
              value: "Yes",
            ),
            Reply(
              title: "😞 Nope. What?",
              value: "no",
            ),
          ],
        ),
      ),

Parameters ⚙️ #

  • messageContainerFlex (int) - Flex value for the messeage container defaults to 1
  • height (double) - Height for the Dash chat Widget.
  • width (double) - Width for the Dash chat Widget.
  • messages (List
  • text (String) - [optional parameter] If provided will stop using the default controller.
  • onTextChange (Function(String)) - If the text parameter is passed then onTextChange must also be passed.
  • inputDecoration (InputDecoration) - Used to provide input decoration to the text.
  • messageIdGenerator (String Function) - Usually new message added by the user gets UUID v4 String generater by uuid.
  • user (ChatUser) - The current user object.
  DashChat(
    user: ChatUser(
      name: "Jhon Doe",
      uid: "xxxxxxxxx",
      avatar: "https://www.wrappixel.com/ampleadmin/assets/images/users/4.jpg",
    )
  );
  • onSend (Function(ChatMessage)) - Callback when sending a message.

  • alwaysShowSend (bool) - Should the send button be always active defaults to false.

  • avatarMaxSize (double) - Sets the default Avatar's max size, default is 30.0.

  • dateFormat (DateFormat) - Format to use for rendering date default is yyyy-MM-dd.

  • timeFormat (DateFormat) - Format to use for rendering time default is HH:mm:ss.

  • showUserAvatar (bool) - Should the user avatar be shown.

  • showAvatarForEveryMessage (bool) - Should the avatar be shown for every message defaults to false.

  • onPressAvatar (Function(ChatUser)) - Callback funtion when avatar is tapped on.

  • onLongPressAvatar (Function(ChatUser)) - Callback funtion when avatar is long pressed on.

  • onLongPressMessage (Function(ChatUser)) - Callback funtion when message is long pressed on.

  • inverted (bool) - Should the messages be shown in reversed order

  • avatarBuilder (Widget Function(ChatUser)) - Will override the the default avatar.

  • messageBuilder (Widget Function(ChatMessage)) - Will override the the default message widget.

  • messageTextBuilder (Widget Function(String)) - Will override the the default message text widget.

  • messageImageBuilder (Widget Function(String)) - Will override the the default message imaeg widget

  • messageTimeBuilder (Widget Function(String)) - Will override the the default message time widget.

  • dateBuilder (Widget Function(String)) - Will override the the default chat view date widget.

  • sendButtonBuilder (Widget Function(Function)) - Will override the the default send button widget.

  • chatFooterBuilder (Widget Function) - A Widget that will be shown below the MessageListView like you can a "tying..." Text Widget at the end.

  • inputFooterBuilder (Widget Function) - A Widget that will be shown below the ChatInputToolbar.

  • maxInputLength (int) - Main input length of the input text box defaulst to no limit.

  • parsePatterns (List

    DashChat(
      parsePatterns: <MatchText>[
        MatchText(
          type: "email",
          onTap: (String value) {}
        ),
        MatchText(
          pattern: r"\B#+([\w]+)\b",
          style: TextStyle(
            color: Colors.pink,
            fontSize: 24,
          ),
          onTap: (String value) {}
        ),
      ]
    );
    
  • messageContainerDecoration (BoxDecoration) - Provides a custom style to the message container.

  • leading (List<Widget>) - List of Widget to show before the TextField.

  • trailing (List<Widget>) - List of Widget to show after the TextField will remove the send button.

  • readOnly (bool) - Hides the input bar, defaults to false.

  • showTraillingBeforeSend - Should the trailling widgets be shown before the send button defaults to true.

  • inputTextStyle (TextStyle) - Style for the TextField.

  • inputContainerStyle (BoxDecoration) - TextField container style.

  • inputMaxLines (int) - Max length of the input lines default to 1.

  • showInputCursor (bool) - Should the input cursor be shown defaults to true.

  • inputCursorWidth (double) - Width of the text input defaults to 2.0.

  • inputCursorColor (Color) - Color of the input cursor defaults to theme.

  • scrollController (ScrollController) - ScrollController for the MessageListView.

  • messageContainerPadding (EdgeInsetsGeometry) - Padding for the MessageListView.

  • messagePadding (EdgeInsets) - Padding for the MessageContainer.

  • onQuickReply (Funtion(Reply)) - Callback method when the quickReply was tapped on.

  • quickReplyStyle (BoxDecoration) - Container style for the QuickReply Container.

  • quickReplyTextStyle (TextStyle) - QuickReply text style.

  • quickReplyBuilder (Widget Function(Reply)) - Will override the the default QuickReply Widget.

  • scrollToBottom (bool) - Should the scroll to bottom widget be shown defaults to true.

  • scrollToBottomStyle (ScrollToBottomStyle) - sets the style & position for the scrollToBottom widget.

  • scrollToBottomWidget (Widget Function()) - Overrides the default scrollToBottomWidget with a custom widget.

  • onScrollToBottomPress (Function) - override the default behaviour of the onScrollToBottom Widget.

  • shouldShowLoadEarlier (bool) - Should the LoadEarlier Floating widget be shown or use load as you scroll scheme whcih will call the onLoadEarlier defaults to false which is this scheme.

  • showLoadEarlierWidget (Widget Function()) - Override the default behaviour of the onScrollToBottom Widget.

  • onLoadEarlier (Function) - Override the default behaviour of the onLoadEarleir Widget or used as a callback when the listView reaches the top.

  • inputToolbarPadding (EdgeInsets) - Can be used to add padding to the input toolbar.

  • inputToolbarMargin (EdgeInsets) - Can be used to add margin to the input toolbar.

  • shouldStartMessagesFromTop (bool) - Can be used to align messages so that it starts from top to bottom instead of the default bottom to top.

  • textBeforeImage (bool) - Can be used to set the order of the text and the image inside a message defaults to true.

  • quickReplyScroll (bool) - Should the quick reply options be horizontally scrollable

  • quickReplyPadding (EdgeInsetsGeometry) - Padding for QuickReply

  • inputDisabled (bool) - Should the input TextField be disabled, defaults to false

Credits 👨🏻‍💻 #

Found this project useful? ❤️ #

If you found this project useful, then please consider giving it a ⭐️ on Github and sharing it with your friends via social media.

License ⚖️ #

API details 📝 #

See the dash_chat.dart for more API details

Issues and feedback 💭 #

If you have any suggestion for including a feature or if something doesn't work, feel free to open a Github issue for us to have a discussion on it.

[1.1.13] #

  • Fixed a bug from previous update.

[1.1.12] #

  • inputDisabled property added.

[1.1.11] #

  • Fixed a bug with previous version causing the widget to break.

[1.1.10] #

  • Add quick reply horizontal scroll and padding options

[1.1.9] #

  • Fixed issue #91, where setting the name was not handled properly

[1.1.8] #

  • Fixed issue #78, scrollToBottom widget not scrolling to maxExtent properly

[1.1.7] #

  • Fixed issue #30 where scrollToBottom widget was visible when the widget was dismounted.

[1.1.6] #

  • Added firstName & lastName property to User.
  • Added avatarMaxSize property to avatar Container.
  • Fix an issue with text Alignment when buttons are set in message container.

[1.1.5] #

  • Added a new property shouldStartMessagesFromTop to Dashchat.

[1.1.4] #

  • Fixed an issue with date builder and inverted list.
  • Replaced SizedBox with Opacity for User Avatar.
  • Custom Message padding property added.
  • Fixed an issue with avatar position when the list is inverted.
  • Added a new property customProperties to ChatUser model.

[1.1.3] #

  • A small bug fixed with inverted message list.

[1.1.2] #

  • Correct alignmnet to message buttons.
  • Added readonly mode to dashchat which hides the inputbar.
  • Fix avatar exception when username is null.

[1.1.1] #

  • Fixed an issue where an conversion toJson for class ChatUser was crashing the app.

[1.1.0] #

  • Ability to send message on Enter or input action keyboard.
  • MediaQuery replaced with LayoutBuilder.
  • Added optional paramter for ChatMessage
  • Ability to have action buttons in ChatMessages.
  • Change Avatar Boxfit.contain to Boxfit.cover.

[1.0.20] #

  • customProperties property added to ChatMessgae class.
  • Color serialization error fixed.

[1.0.19] #

  • Fixed issue #51
  • fix scroll to top when inverted and send

[1.0.18] #

  • inputTextDirection property added.

[1.0.17] #

  • Ability to set custom focus node for input.

  • Removed SingleChildScrollView from root.

  • Added WidgetsBinding.instance.addPostFrameCallback to prevent scrolling before the messages are built.

[1.0.16] #

  • removed unnecessary print from the message_listview

  • changed 'vedio' field to 'video'

  • nullpointer on parsing quick replies; more detailed error reporting for ChatMessage parsing

[1.0.15] #

  • If inverted is true, it will no longer scroll.

[1.0.14] #

  • textController property added.

[1.0.13] #

  • textCapitalization property null error.

[1.0.12] #

  • textCapitalization property added for Input Toolbar.

[1.0.11] #

  • Fixed an issue where dateFormat property was not working.
  • Fixed an issue where input value was not cleared.
  • Fixed an issue where the whole screen incluing the input was scrollable.
  • Few improvemnets to Bottom Scroll Button.

[1.0.10] #

  • Updated dependency intl to 0.16.0.

[1.0.9] #

  • ScrollController not attached issue fixed.

[1.0.8] #

  • Made the default avatar responsive for the current user.

[1.0.7] #

  • Made the default avatar responsive.
  • Two new property inputToolbarPadding & inputToolbarMargin added.

[1.0.6] #

  • Change the default message container size to fix the overflowing of text.
  • Added a new feature to close the keyboard if tap anywhere else on the screen.

[1.0.5] #

  • Fixed an issue where scrollToBottom widget was not disabled.
  • Fixed an issue where message container was not resized properly based on screen width.
  • Fixed a performance issue when scroll down.
  • Fixed an issue where onLoadEarlier was being called every time the listview moved.

[1.0.4] #

  • Models updated

[1.0.3] #

  • Small fixes to the InputToolbar and ChatMessage class

[1.0.2] #

  • ChatMessage serialization added

[1.0.1] #

  • Description updated and small fix

[1.0.0] #

  • Minor fixes and first release

[0.1.6] #

  • LoadEarlier Widget functionality added

[0.1.5] #

  • ScrollToBottom Widget functionality added

[0.1.4] #

  • showTraillingBeforeSend property added

[0.1.3] #

  • Quick Reply functionality added.

[0.1.2] #

  • Chat Bubble are more customizable now.

[0.1.1] #

  • User avatar now show user initials while loading & if not avatar is passed

[0.1.0] #

  • Initial Release

example/lib/main.dart

import 'dart:async';
import 'dart:io';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:intl/intl.dart';
import 'package:dash_chat/dash_chat.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.purple,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final GlobalKey<DashChatState> _chatViewKey = GlobalKey<DashChatState>();

  final ChatUser user = ChatUser(
    name: "Fayeed",
    firstName: "Fayeed",
    lastName: "Pawaskar",
    uid: "12345678",
    avatar: "https://www.wrappixel.com/ampleadmin/assets/images/users/4.jpg",
  );

  final ChatUser otherUser = ChatUser(
    name: "Mrfatty",
    uid: "25649654",
  );

  List<ChatMessage> messages = List<ChatMessage>();
  var m = List<ChatMessage>();

  var i = 0;

  @override
  void initState() {
    super.initState();
  }

  void systemMessage() {
    Timer(Duration(milliseconds: 300), () {
      if (i < 6) {
        setState(() {
          messages = [...messages, m[i]];
        });
        i++;
      }
      Timer(Duration(milliseconds: 300), () {
        _chatViewKey.currentState.scrollController
          ..animateTo(
            _chatViewKey.currentState.scrollController.position.maxScrollExtent,
            curve: Curves.easeOut,
            duration: const Duration(milliseconds: 300),
          );
      });
    });
  }

  void onSend(ChatMessage message) async {
    print(message.toJson());
    var documentReference = Firestore.instance
        .collection('messages')
        .document(DateTime.now().millisecondsSinceEpoch.toString());

    await Firestore.instance.runTransaction((transaction) async {
      await transaction.set(
        documentReference,
        message.toJson(),
      );
    });
    /* setState(() {
      messages = [...messages, message];
      print(messages.length);
    });

    if (i == 0) {
      systemMessage();
      Timer(Duration(milliseconds: 600), () {
        systemMessage();
      });
    } else {
      systemMessage();
    } */
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Chat App"),
      ),
      body: StreamBuilder(
          stream: Firestore.instance.collection('messages').snapshots(),
          builder: (context, snapshot) {
            if (!snapshot.hasData) {
              return Center(
                child: CircularProgressIndicator(
                  valueColor: AlwaysStoppedAnimation<Color>(
                    Theme.of(context).primaryColor,
                  ),
                ),
              );
            } else {
              List<DocumentSnapshot> items = snapshot.data.documents;
              var messages =
                  items.map((i) => ChatMessage.fromJson(i.data)).toList();
              return DashChat(
                key: _chatViewKey,
                inverted: false,
                onSend: onSend,
                sendOnEnter: true,
                textInputAction: TextInputAction.send,
                user: user,
                inputDecoration:
                    InputDecoration.collapsed(hintText: "Add message here..."),
                dateFormat: DateFormat('yyyy-MMM-dd'),
                timeFormat: DateFormat('HH:mm'),
                messages: messages,
                showUserAvatar: false,
                showAvatarForEveryMessage: false,
                scrollToBottom: true,
                onPressAvatar: (ChatUser user) {
                  print("OnPressAvatar: ${user.name}");
                },
                onLongPressAvatar: (ChatUser user) {
                  print("OnLongPressAvatar: ${user.name}");
                },
                inputMaxLines: 5,
                messageContainerPadding: EdgeInsets.only(left: 5.0, right: 5.0),
                alwaysShowSend: true,
                inputTextStyle: TextStyle(fontSize: 16.0),
                inputContainerStyle: BoxDecoration(
                  border: Border.all(width: 0.0),
                  color: Colors.white,
                ),
                onQuickReply: (Reply reply) {
                  setState(() {
                    messages.add(ChatMessage(
                        text: reply.value,
                        createdAt: DateTime.now(),
                        user: user));

                    messages = [...messages];
                  });

                  Timer(Duration(milliseconds: 300), () {
                    _chatViewKey.currentState.scrollController
                      ..animateTo(
                        _chatViewKey.currentState.scrollController.position
                            .maxScrollExtent,
                        curve: Curves.easeOut,
                        duration: const Duration(milliseconds: 300),
                      );

                    if (i == 0) {
                      systemMessage();
                      Timer(Duration(milliseconds: 600), () {
                        systemMessage();
                      });
                    } else {
                      systemMessage();
                    }
                  });
                },
                onLoadEarlier: () {
                  print("laoding...");
                },
                shouldShowLoadEarlier: false,
                showTraillingBeforeSend: true,
                trailing: <Widget>[
                  IconButton(
                    icon: Icon(Icons.photo),
                    onPressed: () async {
                      File result = await ImagePicker.pickImage(
                        source: ImageSource.gallery,
                        imageQuality: 80,
                        maxHeight: 400,
                        maxWidth: 400,
                      );

                      if (result != null) {
                        final StorageReference storageRef =
                            FirebaseStorage.instance.ref().child("chat_images");

                        StorageUploadTask uploadTask = storageRef.putFile(
                          result,
                          StorageMetadata(
                            contentType: 'image/jpg',
                          ),
                        );
                        StorageTaskSnapshot download =
                            await uploadTask.onComplete;

                        String url = await download.ref.getDownloadURL();

                        ChatMessage message =
                            ChatMessage(text: "", user: user, image: url);

                        var documentReference = Firestore.instance
                            .collection('messages')
                            .document(DateTime.now()
                                .millisecondsSinceEpoch
                                .toString());

                        Firestore.instance.runTransaction((transaction) async {
                          await transaction.set(
                            documentReference,
                            message.toJson(),
                          );
                        });
                      }
                    },
                  )
                ],
              );
            }
          }),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  dash_chat: ^1.1.13

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:dash_chat/dash_chat.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
93
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
96
Learn more about scoring.

We analyzed this package on Jul 14, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.15
  • Flutter: 1.17.5

Analysis suggestions

Package not compatible with SDK dart

Because:

  • dash_chat that is a package requiring null.

Health suggestions

Fix lib/src/chat_view.dart. (-0.50 points)

Analysis of lib/src/chat_view.dart reported 1 hint:

line 5 col 7: This class (or a class that this class inherits from) is marked as '@immutable', but one or more of its instance fields aren't final: DashChat.scrollToBottomStyle

Format lib/src/models/chat_message.dart.

Run flutter format to format lib/src/models/chat_message.dart.

Format lib/src/widgets/quick_reply.dart.

Run flutter format to format lib/src/widgets/quick_reply.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.2.2 <3.0.0
flutter 0.0.0
flutter_parsed_text ^1.1.0 1.2.4
intl ^0.16.0 0.16.1
transparent_image ^1.0.0 1.0.0
uuid ^2.0.1 2.2.0
Transitive dependencies
charcode 1.1.3
collection 1.14.12 1.14.13
convert 2.1.1
crypto 2.1.5
meta 1.1.8 1.2.2
path 1.7.0
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8 2.1.0-nullsafety
Dev dependencies
flutter_test