diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index f35800111c..4371438266 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -22,7 +22,6 @@ import 'package:fluffychat/pages/chat/chat_room_search_mixin.dart'; import 'package:fluffychat/pages/chat/chat_view.dart'; import 'package:fluffychat/pages/chat/context_item_chat_action.dart'; import 'package:fluffychat/pages/chat/dialog_accept_invite_widget.dart'; -import 'package:fluffychat/pages/chat/event_info_dialog.dart'; import 'package:fluffychat/pages/chat/recording_dialog.dart'; import 'package:fluffychat/pages/chat_details/chat_details_actions_enum.dart'; import 'package:fluffychat/presentation/mixins/common_media_picker_mixin.dart'; @@ -1318,9 +1317,6 @@ class ChatController extends State bool get isArchived => {Membership.leave, Membership.ban}.contains(room?.membership); - void showEventInfoAction([Event? event]) => - (event ?? selectedEvents.single).showInfoDialog(context); - void onPhoneButtonTap() async { // VoIP required Android SDK 21 if (PlatformInfos.isAndroid) { diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 36b02713ee..a4d848a99b 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -108,7 +108,6 @@ class ChatEventList extends StatelessWidget { event, onSwipe: (direction) => controller.replyAction(replyTo: event), - onInfoTab: controller.showEventInfoAction, onAvatarTab: (Event event) => showAdaptiveBottomSheet( context: context, builder: (c) => UserBottomSheet( diff --git a/lib/pages/chat/chat_view.dart b/lib/pages/chat/chat_view.dart index 5c55bb56b9..69b4ceac74 100644 --- a/lib/pages/chat/chat_view.dart +++ b/lib/pages/chat/chat_view.dart @@ -6,6 +6,7 @@ import 'package:fluffychat/pages/chat/chat_event_list.dart'; import 'package:fluffychat/pages/chat/chat_loading_view.dart'; import 'package:fluffychat/pages/chat/chat_search_bottom_view.dart'; import 'package:fluffychat/pages/chat/chat_view_style.dart'; +import 'package:fluffychat/pages/chat/events/message_content_mixin.dart'; import 'package:fluffychat/pages/chat/pinned_events.dart'; import 'package:fluffychat/pages/chat/reply_display.dart'; import 'package:fluffychat/pages/chat/tombstone_display.dart'; @@ -24,7 +25,7 @@ enum _EventContextAction { info, report } enum _RoomContextAction { search } -class ChatView extends StatelessWidget { +class ChatView extends StatelessWidget with MessageContentMixin { final ChatController controller; const ChatView(this.controller, {Key? key}) : super(key: key); @@ -59,7 +60,10 @@ class ChatView extends StatelessWidget { switch (action) { case _EventContextAction.info: controller.actionWithClearSelections( - controller.showEventInfoAction, + () => showEventInfo( + context, + controller.selectedEvents.single, + ), ); break; case _EventContextAction.report: diff --git a/lib/pages/chat/events/button_content.dart b/lib/pages/chat/events/button_content.dart new file mode 100644 index 0000000000..33dd298dcd --- /dev/null +++ b/lib/pages/chat/events/button_content.dart @@ -0,0 +1,61 @@ +import 'package:fluffychat/pages/chat/events/button_content_style.dart'; +import 'package:flutter/material.dart'; + +class ButtonContent extends StatelessWidget { + final Function onTap; + final IconData icon; + final String title; + + const ButtonContent({ + Key? key, + required this.onTap, + required this.icon, + required this.title, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: ButtonContentStyle.parentPadding, + child: InkWell( + onTap: () => onTap, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.onError, + shape: BoxShape.circle, + ), + padding: ButtonContentStyle.leadingIconPadding, + child: Icon( + icon, + color: Theme.of(context).colorScheme.primary, + size: ButtonContentStyle.leadingIconSize, + ), + ), + const SizedBox(width: ButtonContentStyle.leadingAndTextGap), + Container( + constraints: const BoxConstraints( + maxWidth: ButtonContentStyle.textMaxWidth, + ), + child: Text( + title, + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/chat/events/encrypted_content_style.dart b/lib/pages/chat/events/button_content_style.dart similarity index 66% rename from lib/pages/chat/events/encrypted_content_style.dart rename to lib/pages/chat/events/button_content_style.dart index cbde22376f..44c6ae8639 100644 --- a/lib/pages/chat/events/encrypted_content_style.dart +++ b/lib/pages/chat/events/button_content_style.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; -class EncryptedContentStyle { - static const EdgeInsets parentPadding = EdgeInsets.symmetric( - horizontal: 8, +class ButtonContentStyle { + static const EdgeInsets parentPadding = EdgeInsets.only( + left: 2, + right: 8, ); static const EdgeInsets leadingIconPadding = EdgeInsets.all(5); static const double leadingIconSize = 20; diff --git a/lib/pages/chat/events/call_invite_content.dart b/lib/pages/chat/events/call_invite_content.dart new file mode 100644 index 0000000000..3ef73870f1 --- /dev/null +++ b/lib/pages/chat/events/call_invite_content.dart @@ -0,0 +1,28 @@ +import 'package:fluffychat/pages/chat/events/button_content.dart'; +import 'package:fluffychat/pages/chat/events/message_content_mixin.dart'; +import 'package:flutter/material.dart'; +import 'package:matrix/matrix.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class CallInviteContent extends StatelessWidget with MessageContentMixin { + final Event event; + + const CallInviteContent({Key? key, required this.event}) : super(key: key); + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: event.fetchSenderUser(), + builder: (context, snapshot) { + return ButtonContent( + title: L10n.of(context)!.startedACall( + snapshot.data?.calcDisplayname() ?? + event.senderFromMemoryOrFallback.calcDisplayname(), + ), + icon: Icons.phone_outlined, + onTap: () => showEventInfo(context, event), + ); + }, + ); + } +} diff --git a/lib/pages/chat/events/encrypted_content.dart b/lib/pages/chat/events/encrypted_content.dart index dd8dfbaa3c..f8c636ccb3 100644 --- a/lib/pages/chat/events/encrypted_content.dart +++ b/lib/pages/chat/events/encrypted_content.dart @@ -1,4 +1,4 @@ -import 'package:fluffychat/pages/chat/events/encrypted_content_style.dart'; +import 'package:fluffychat/pages/chat/events/button_content.dart'; import 'package:fluffychat/pages/chat/events/encrypted_mixin.dart'; import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; @@ -11,46 +11,10 @@ class EncryptedContent extends StatelessWidget with EncryptedMixin { @override Widget build(BuildContext context) { - return Padding( - padding: EncryptedContentStyle.parentPadding, - child: InkWell( - onTap: () => verifyOrRequestKey(context, event), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.onError, - shape: BoxShape.circle, - ), - padding: EncryptedContentStyle.leadingIconPadding, - child: Icon( - Icons.lock, - color: Theme.of(context).colorScheme.primary, - size: EncryptedContentStyle.leadingIconSize, - ), - ), - const SizedBox(width: EncryptedContentStyle.leadingAndTextGap), - Container( - constraints: const BoxConstraints( - maxWidth: EncryptedContentStyle.textMaxWidth, - ), - child: Text( - maxLines: 2, - L10n.of(context)!.thisMessageHasBeenEncrypted, - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - color: Theme.of(context).colorScheme.onSurface, - ), - ), - ), - ], - ), - ], - ), - ), + return ButtonContent( + onTap: () => verifyOrRequestKey(context, event), + icon: Icons.lock, + title: L10n.of(context)!.thisMessageHasBeenEncrypted, ); } } diff --git a/lib/pages/chat/events/message/message.dart b/lib/pages/chat/events/message/message.dart index 49184d1d8a..a674954f96 100644 --- a/lib/pages/chat/events/message/message.dart +++ b/lib/pages/chat/events/message/message.dart @@ -31,7 +31,6 @@ class Message extends StatelessWidget { final Event? nextEvent; final void Function(Event)? onSelect; final void Function(Event)? onAvatarTab; - final void Function(Event)? onInfoTab; final void Function(String)? scrollToEventId; final void Function(SwipeDirection) onSwipe; final void Function(bool, Event)? onHover; @@ -49,7 +48,6 @@ class Message extends StatelessWidget { this.nextEvent, this.longPressSelect = false, this.onSelect, - this.onInfoTab, this.onAvatarTab, this.onHover, this.scrollToEventId, @@ -344,8 +342,6 @@ class Message extends StatelessWidget { displayEvent, textColor: textColor, - onInfoTab: - onInfoTab, endOfBubbleWidget: Padding( padding: diff --git a/lib/pages/chat/events/message_content.dart b/lib/pages/chat/events/message_content.dart index c87288ee85..be324278d3 100644 --- a/lib/pages/chat/events/message_content.dart +++ b/lib/pages/chat/events/message_content.dart @@ -2,10 +2,13 @@ import 'package:fluffychat/app_state/success.dart'; import 'package:fluffychat/domain/app_state/room/chat_room_search_state.dart'; import 'package:fluffychat/pages/chat/chat.dart'; import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pages/chat/events/call_invite_content.dart'; import 'package:fluffychat/pages/chat/events/encrypted_content.dart'; import 'package:fluffychat/pages/chat/events/message_content_style.dart'; +import 'package:fluffychat/pages/chat/events/redacted_content.dart'; import 'package:fluffychat/pages/chat/events/sending_image_info_widget.dart'; import 'package:fluffychat/pages/chat/events/sending_video_widget.dart'; +import 'package:fluffychat/pages/chat/events/unknown_content.dart'; import 'package:fluffychat/presentation/mixins/play_video_action_mixin.dart'; import 'package:fluffychat/presentation/model/file/display_image_info.dart'; import 'package:fluffychat/utils/extension/image_size_extension.dart'; @@ -22,7 +25,6 @@ import 'package:matrix/matrix.dart' hide Visibility; import 'package:fluffychat/pages/chat/events/event_video_player.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart'; -import 'package:fluffychat/widgets/matrix.dart'; import 'audio_player.dart'; import 'cute_events.dart'; import 'html_message.dart'; @@ -34,7 +36,6 @@ import 'sticker.dart'; class MessageContent extends StatelessWidget with PlayVideoActionMixin { final Event event; final Color textColor; - final void Function(Event)? onInfoTab; final Widget endOfBubbleWidget; final Color backgroundColor; final void Function()? onTapPreview; @@ -44,7 +45,6 @@ class MessageContent extends StatelessWidget with PlayVideoActionMixin { const MessageContent( this.event, { - this.onInfoTab, Key? key, required this.controller, required this.textColor, @@ -58,8 +58,6 @@ class MessageContent extends StatelessWidget with PlayVideoActionMixin { @override Widget build(BuildContext context) { final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor; - final buttonTextColor = - event.senderId == Matrix.of(context).client.userID ? textColor : null; switch (event.type) { case EventTypes.Encrypted: return EncryptedContent(event: event); @@ -220,20 +218,7 @@ class MessageContent extends StatelessWidget with PlayVideoActionMixin { textmessage: default: if (event.redacted) { - return FutureBuilder( - future: event.redactedBecause?.fetchSenderUser(), - builder: (context, snapshot) { - return _ButtonContent( - label: L10n.of(context)!.redactedAnEvent( - snapshot.data?.calcDisplayname() ?? - event.senderFromMemoryOrFallback.calcDisplayname(), - ), - icon: const Icon(Icons.delete_outlined), - textColor: buttonTextColor, - onPressed: () => onInfoTab!(event), - ); - }, - ); + return RedactedContent(event: event); } final bigEmotes = event.onlyEmotes && @@ -297,68 +282,13 @@ class MessageContent extends StatelessWidget with PlayVideoActionMixin { ); } case EventTypes.CallInvite: - return FutureBuilder( - future: event.fetchSenderUser(), - builder: (context, snapshot) { - return _ButtonContent( - label: L10n.of(context)!.startedACall( - snapshot.data?.calcDisplayname() ?? - event.senderFromMemoryOrFallback.calcDisplayname(), - ), - icon: const Icon(Icons.phone_outlined), - textColor: buttonTextColor, - onPressed: () => onInfoTab!(event), - ); - }, - ); + return CallInviteContent(event: event); default: - return FutureBuilder( - future: event.fetchSenderUser(), - builder: (context, snapshot) { - return _ButtonContent( - label: L10n.of(context)!.userSentUnknownEvent( - snapshot.data?.calcDisplayname() ?? - event.senderFromMemoryOrFallback.calcDisplayname(), - event.type, - ), - icon: const Icon(Icons.info_outlined), - textColor: buttonTextColor, - onPressed: () => onInfoTab!(event), - ); - }, - ); + return UnknownContent(event: event); } } } -class _ButtonContent extends StatelessWidget { - final void Function() onPressed; - final String label; - final Icon icon; - final Color? textColor; - - const _ButtonContent({ - required this.label, - required this.icon, - required this.textColor, - required this.onPressed, - Key? key, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return OutlinedButton.icon( - onPressed: onPressed, - icon: icon, - label: Text(label, overflow: TextOverflow.ellipsis), - style: OutlinedButton.styleFrom( - foregroundColor: textColor, - backgroundColor: MessageContentStyle.backgroundColorButton, - ), - ); - } -} - class _MessageImageBuilder extends StatelessWidget { final Event event; diff --git a/lib/pages/chat/events/message_content_mixin.dart b/lib/pages/chat/events/message_content_mixin.dart new file mode 100644 index 0000000000..2e0ed86d82 --- /dev/null +++ b/lib/pages/chat/events/message_content_mixin.dart @@ -0,0 +1,8 @@ +import 'package:fluffychat/pages/chat/event_info_dialog.dart'; +import 'package:flutter/material.dart'; +import 'package:matrix/matrix.dart'; + +mixin MessageContentMixin { + void showEventInfo(BuildContext context, Event event) => + event.showInfoDialog(context); +} diff --git a/lib/pages/chat/events/redacted_content.dart b/lib/pages/chat/events/redacted_content.dart new file mode 100644 index 0000000000..635665c537 --- /dev/null +++ b/lib/pages/chat/events/redacted_content.dart @@ -0,0 +1,25 @@ +import 'package:fluffychat/pages/chat/events/button_content.dart'; +import 'package:fluffychat/pages/chat/events/message_content_mixin.dart'; +import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; +import 'package:flutter/material.dart'; +import 'package:matrix/matrix.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class RedactedContent extends StatelessWidget with MessageContentMixin { + final Event event; + + const RedactedContent({Key? key, required this.event}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ButtonContent( + title: event.calcLocalizedBodyFallback( + MatrixLocals(L10n.of(context)!), + withSenderNamePrefix: false, + hideReply: true, + ), + icon: Icons.delete_outlined, + onTap: () => showEventInfo(context, event), + ); + } +} diff --git a/lib/pages/chat/events/unknown_content.dart b/lib/pages/chat/events/unknown_content.dart new file mode 100644 index 0000000000..8f0c6f0971 --- /dev/null +++ b/lib/pages/chat/events/unknown_content.dart @@ -0,0 +1,29 @@ +import 'package:fluffychat/pages/chat/events/button_content.dart'; +import 'package:fluffychat/pages/chat/events/message_content_mixin.dart'; +import 'package:flutter/material.dart'; +import 'package:matrix/matrix.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class UnknownContent extends StatelessWidget with MessageContentMixin { + final Event event; + + const UnknownContent({Key? key, required this.event}) : super(key: key); + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: event.fetchSenderUser(), + builder: (context, snapshot) { + return ButtonContent( + title: L10n.of(context)!.userSentUnknownEvent( + snapshot.data?.calcDisplayname() ?? + event.senderFromMemoryOrFallback.calcDisplayname(), + event.type, + ), + icon: Icons.info_outlined, + onTap: () => showEventInfo(context, event), + ); + }, + ); + } +}