From 66cae6cc85eba74fba665acbb75d3bdb9f957587 Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Sat, 6 Nov 2021 11:18:32 +0100 Subject: [PATCH] design: Floating input bar --- lib/pages/views/chat_view.dart | 480 +++++++++++++++++---------------- 1 file changed, 248 insertions(+), 232 deletions(-) diff --git a/lib/pages/views/chat_view.dart b/lib/pages/views/chat_view.dart index f2a2169b..0b3ff880 100644 --- a/lib/pages/views/chat_view.dart +++ b/lib/pages/views/chat_view.dart @@ -1,5 +1,6 @@ import 'dart:ui'; +import 'package:fluffychat/config/themes.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -505,254 +506,269 @@ class ChatView extends StatelessWidget { ), ), ), - const Divider(height: 1), + if (controller.showScrollDownButton) + const Divider( + height: 1, + ), if (controller.room.canSendDefaultMessages && controller.room.membership == Membership.join && !controller.showEmojiPicker) - Container( - decoration: BoxDecoration( + Padding( + padding: EdgeInsets.all( + FluffyThemes.isColumnMode(context) ? 16.0 : 8.0), + child: Material( + borderRadius: + BorderRadius.circular(AppConfig.borderRadius), + elevation: 4, color: Theme.of(context).scaffoldBackgroundColor, - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: controller.selectMode - ? [ - SizedBox( - height: 56, - child: TextButton( - onPressed: controller.forwardEventsAction, - child: Row( - children: [ - const Icon(Icons - .keyboard_arrow_left_outlined), - Text(L10n.of(context).forward), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: controller.selectMode + ? [ + SizedBox( + height: 56, + child: TextButton( + onPressed: + controller.forwardEventsAction, + child: Row( + children: [ + const Icon(Icons + .keyboard_arrow_left_outlined), + Text(L10n.of(context).forward), + ], + ), + ), + ), + controller.selectedEvents.length == 1 + ? controller.selectedEvents.first + .getDisplayEvent( + controller.timeline) + .status + .isSent + ? SizedBox( + height: 56, + child: TextButton( + onPressed: + controller.replyAction, + child: Row( + children: [ + Text(L10n.of(context) + .reply), + const Icon(Icons + .keyboard_arrow_right), + ], + ), + ), + ) + : SizedBox( + height: 56, + child: TextButton( + onPressed: controller + .sendAgainAction, + child: Row( + children: [ + Text(L10n.of(context) + .tryToSendAgain), + const SizedBox(width: 4), + const Icon( + Icons.send_outlined, + size: 16), + ], + ), + ), + ) + : Container(), + ] + : [ + AnimatedContainer( + duration: + const Duration(milliseconds: 200), + height: 56, + width: + controller.inputText.isEmpty ? 56 : 0, + alignment: Alignment.center, + clipBehavior: Clip.hardEdge, + decoration: const BoxDecoration(), + child: PopupMenuButton( + icon: const Icon(Icons.add_outlined), + onSelected: controller + .onAddPopupMenuButtonSelected, + itemBuilder: (BuildContext context) => + >[ + PopupMenuItem( + value: 'file', + child: ListTile( + leading: const CircleAvatar( + backgroundColor: Colors.green, + foregroundColor: Colors.white, + child: Icon( + Icons.attachment_outlined), + ), + title: Text( + L10n.of(context).sendFile), + contentPadding: + const EdgeInsets.all(0), + ), + ), + PopupMenuItem( + value: 'image', + child: ListTile( + leading: const CircleAvatar( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + child: + Icon(Icons.image_outlined), + ), + title: Text( + L10n.of(context).sendImage), + contentPadding: + const EdgeInsets.all(0), + ), + ), + if (PlatformInfos.isMobile) + PopupMenuItem( + value: 'camera', + child: ListTile( + leading: const CircleAvatar( + backgroundColor: + Colors.purple, + foregroundColor: Colors.white, + child: Icon(Icons + .camera_alt_outlined), + ), + title: Text(L10n.of(context) + .openCamera), + contentPadding: + const EdgeInsets.all(0), + ), + ), + if (controller.room + .getImagePacks( + ImagePackUsage.sticker) + .isNotEmpty) + PopupMenuItem( + value: 'sticker', + child: ListTile( + leading: const CircleAvatar( + backgroundColor: + Colors.orange, + foregroundColor: Colors.white, + child: Icon(Icons + .emoji_emotions_outlined), + ), + title: Text(L10n.of(context) + .sendSticker), + contentPadding: + const EdgeInsets.all(0), + ), + ), + if (PlatformInfos.isMobile) + PopupMenuItem( + value: 'voice', + child: ListTile( + leading: const CircleAvatar( + backgroundColor: Colors.red, + foregroundColor: Colors.white, + child: Icon( + Icons.mic_none_outlined), + ), + title: Text(L10n.of(context) + .voiceMessage), + contentPadding: + const EdgeInsets.all(0), + ), + ), + if (PlatformInfos.isMobile) + PopupMenuItem( + value: 'location', + child: ListTile( + leading: const CircleAvatar( + backgroundColor: Colors.brown, + foregroundColor: Colors.white, + child: Icon( + Icons.gps_fixed_outlined), + ), + title: Text(L10n.of(context) + .shareLocation), + contentPadding: + const EdgeInsets.all(0), + ), + ), ], ), ), - ), - controller.selectedEvents.length == 1 - ? controller.selectedEvents.first - .getDisplayEvent( - controller.timeline) - .status - .isSent - ? SizedBox( - height: 56, - child: TextButton( - onPressed: - controller.replyAction, - child: Row( - children: [ - Text( - L10n.of(context).reply), - const Icon(Icons - .keyboard_arrow_right), - ], - ), - ), - ) - : SizedBox( - height: 56, - child: TextButton( - onPressed: - controller.sendAgainAction, - child: Row( - children: [ - Text(L10n.of(context) - .tryToSendAgain), - const SizedBox(width: 4), - const Icon( - Icons.send_outlined, - size: 16), - ], - ), - ), - ) - : Container(), - ] - : [ - AnimatedContainer( - duration: const Duration(milliseconds: 200), - height: 56, - width: - controller.inputText.isEmpty ? 56 : 0, - alignment: Alignment.center, - clipBehavior: Clip.hardEdge, - decoration: const BoxDecoration(), - child: PopupMenuButton( - icon: const Icon(Icons.add_outlined), - onSelected: controller - .onAddPopupMenuButtonSelected, - itemBuilder: (BuildContext context) => - >[ - PopupMenuItem( - value: 'file', - child: ListTile( - leading: const CircleAvatar( - backgroundColor: Colors.green, - foregroundColor: Colors.white, - child: Icon( - Icons.attachment_outlined), - ), - title: - Text(L10n.of(context).sendFile), - contentPadding: - const EdgeInsets.all(0), - ), - ), - PopupMenuItem( - value: 'image', - child: ListTile( - leading: const CircleAvatar( - backgroundColor: Colors.blue, - foregroundColor: Colors.white, - child: Icon(Icons.image_outlined), - ), - title: Text( - L10n.of(context).sendImage), - contentPadding: - const EdgeInsets.all(0), - ), - ), - if (PlatformInfos.isMobile) - PopupMenuItem( - value: 'camera', - child: ListTile( - leading: const CircleAvatar( - backgroundColor: Colors.purple, - foregroundColor: Colors.white, - child: Icon( - Icons.camera_alt_outlined), - ), - title: Text( - L10n.of(context).openCamera), - contentPadding: - const EdgeInsets.all(0), - ), - ), - if (controller.room - .getImagePacks( - ImagePackUsage.sticker) - .isNotEmpty) - PopupMenuItem( - value: 'sticker', - child: ListTile( - leading: const CircleAvatar( - backgroundColor: Colors.orange, - foregroundColor: Colors.white, - child: Icon(Icons - .emoji_emotions_outlined), - ), - title: Text( - L10n.of(context).sendSticker), - contentPadding: - const EdgeInsets.all(0), - ), - ), - if (PlatformInfos.isMobile) - PopupMenuItem( - value: 'voice', - child: ListTile( - leading: const CircleAvatar( - backgroundColor: Colors.red, - foregroundColor: Colors.white, - child: Icon( - Icons.mic_none_outlined), - ), - title: Text(L10n.of(context) - .voiceMessage), - contentPadding: - const EdgeInsets.all(0), - ), - ), - if (PlatformInfos.isMobile) - PopupMenuItem( - value: 'location', - child: ListTile( - leading: const CircleAvatar( - backgroundColor: Colors.brown, - foregroundColor: Colors.white, - child: Icon( - Icons.gps_fixed_outlined), - ), - title: Text(L10n.of(context) - .shareLocation), - contentPadding: - const EdgeInsets.all(0), - ), - ), - ], - ), - ), - Container( - height: 56, - alignment: Alignment.center, - child: EncryptionButton(controller.room), - ), - if (controller.matrix.isMultiAccount && - controller.matrix.hasComplexBundles && - controller.matrix.currentBundle.length > - 1) Container( height: 56, alignment: Alignment.center, - child: _ChatAccountPicker(controller), + child: EncryptionButton(controller.room), ), - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 4.0), - child: InputBar( - room: controller.room, - minLines: 1, - maxLines: 8, - autofocus: !PlatformInfos.isMobile, - keyboardType: TextInputType.multiline, - textInputAction: AppConfig.sendOnEnter - ? TextInputAction.send - : null, - onSubmitted: - controller.onInputBarSubmitted, - focusNode: controller.inputFocus, - controller: controller.sendController, - decoration: InputDecoration( - hintText: - L10n.of(context).writeAMessage, - hintMaxLines: 1, - border: InputBorder.none, - enabledBorder: InputBorder.none, - filled: false, + if (controller.matrix.isMultiAccount && + controller.matrix.hasComplexBundles && + controller.matrix.currentBundle.length > + 1) + Container( + height: 56, + alignment: Alignment.center, + child: _ChatAccountPicker(controller), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 4.0), + child: InputBar( + room: controller.room, + minLines: 1, + maxLines: 8, + autofocus: !PlatformInfos.isMobile, + keyboardType: TextInputType.multiline, + textInputAction: AppConfig.sendOnEnter + ? TextInputAction.send + : null, + onSubmitted: + controller.onInputBarSubmitted, + focusNode: controller.inputFocus, + controller: controller.sendController, + decoration: InputDecoration( + hintText: + L10n.of(context).writeAMessage, + hintMaxLines: 1, + border: InputBorder.none, + enabledBorder: InputBorder.none, + filled: false, + ), + onChanged: + controller.onInputBarChanged, ), - onChanged: controller.onInputBarChanged, ), ), - ), - if (PlatformInfos.isMobile && - controller.inputText.isEmpty) - Container( - height: 56, - alignment: Alignment.center, - child: IconButton( - tooltip: L10n.of(context).voiceMessage, - icon: - const Icon(Icons.mic_none_outlined), - onPressed: - controller.voiceMessageAction, + if (PlatformInfos.isMobile && + controller.inputText.isEmpty) + Container( + height: 56, + alignment: Alignment.center, + child: IconButton( + tooltip: + L10n.of(context).voiceMessage, + icon: const Icon( + Icons.mic_none_outlined), + onPressed: + controller.voiceMessageAction, + ), ), - ), - if (!PlatformInfos.isMobile || - controller.inputText.isNotEmpty) - Container( - height: 56, - alignment: Alignment.center, - child: IconButton( - icon: const Icon(Icons.send_outlined), - onPressed: controller.send, - tooltip: L10n.of(context).send, + if (!PlatformInfos.isMobile || + controller.inputText.isNotEmpty) + Container( + height: 56, + alignment: Alignment.center, + child: IconButton( + icon: const Icon(Icons.send_outlined), + onPressed: controller.send, + tooltip: L10n.of(context).send, + ), ), - ), - ], + ], + ), ), ), AnimatedContainer(