From 6e9d3627cc615541adb365381a22efe60c2c04e3 Mon Sep 17 00:00:00 2001 From: krille-chan Date: Thu, 17 Aug 2023 19:16:12 +0200 Subject: [PATCH] feat: Improved mouse support for selecting events --- lib/pages/chat/chat.dart | 11 ++ lib/pages/chat/chat_view.dart | 11 +- lib/pages/chat/events/message.dart | 183 +++++++++++++++-------------- 3 files changed, 109 insertions(+), 96 deletions(-) diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 4ac9a8f00..cb501f240 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -816,6 +816,17 @@ class ChatController extends State { return true; } + bool get canPinSelectedEvents { + if (isArchived || + !room.canChangeStateEvent(EventTypes.RoomPinnedEvents) || + selectedEvents.length != 1 || + !selectedEvents.single.status.isSent) { + return false; + } + return currentRoomBundle + .any((cl) => selectedEvents.first.senderId == cl!.userID); + } + bool get canEditSelectedEvents { if (isArchived || selectedEvents.length != 1 || diff --git a/lib/pages/chat/chat_view.dart b/lib/pages/chat/chat_view.dart index 346451c62..87aa1e994 100644 --- a/lib/pages/chat/chat_view.dart +++ b/lib/pages/chat/chat_view.dart @@ -54,17 +54,18 @@ class ChatView extends StatelessWidget { onPressed: () => controller.saveSelectedEvent(context), ), ), + if (controller.canPinSelectedEvents) + IconButton( + icon: const Icon(Icons.push_pin_outlined), + onPressed: controller.pinEvent, + tooltip: L10n.of(context)!.pinMessage, + ), if (controller.canRedactSelectedEvents) IconButton( icon: const Icon(Icons.delete_outlined), tooltip: L10n.of(context)!.redactMessage, onPressed: controller.redactEventsAction, ), - IconButton( - icon: const Icon(Icons.push_pin_outlined), - onPressed: controller.pinEvent, - tooltip: L10n.of(context)!.pinMessage, - ), if (controller.selectedEvents.length == 1) PopupMenuButton<_EventContextAction>( onSelected: (action) { diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index c576c26a1..678b26ae5 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -117,83 +117,80 @@ class Message extends StatelessWidget { : Theme.of(context).colorScheme.primaryContainer; } - final rowChildren = [ - sameSender || ownMessage - ? SizedBox( - width: Avatar.defaultSize, - child: Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Center( - child: SizedBox( - width: 16, - height: 16, - child: event.status == EventStatus.sending - ? const CircularProgressIndicator.adaptive( - strokeWidth: 2, - ) - : event.status == EventStatus.error - ? const Icon(Icons.error, color: Colors.red) - : null, + final row = Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: rowMainAxisAlignment, + children: [ + sameSender || ownMessage + ? SizedBox( + width: Avatar.defaultSize, + child: Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Center( + child: SizedBox( + width: 16, + height: 16, + child: event.status == EventStatus.sending + ? const CircularProgressIndicator.adaptive( + strokeWidth: 2, + ) + : event.status == EventStatus.error + ? const Icon(Icons.error, color: Colors.red) + : null, + ), ), ), + ) + : FutureBuilder( + future: event.fetchSenderUser(), + builder: (context, snapshot) { + final user = + snapshot.data ?? event.senderFromMemoryOrFallback; + return Avatar( + mxContent: user.avatarUrl, + name: user.calcDisplayname(), + onTap: () => onAvatarTab!(event), + ); + }, ), - ) - : FutureBuilder( - future: event.fetchSenderUser(), - builder: (context, snapshot) { - final user = snapshot.data ?? event.senderFromMemoryOrFallback; - return Avatar( - mxContent: user.avatarUrl, - name: user.calcDisplayname(), - onTap: () => onAvatarTab!(event), - ); - }, - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - if (!sameSender) - Padding( - padding: const EdgeInsets.only(left: 8.0, bottom: 4), - child: ownMessage || event.room.isDirectChat - ? const SizedBox(height: 12) - : FutureBuilder( - future: event.fetchSenderUser(), - builder: (context, snapshot) { - final displayname = - snapshot.data?.calcDisplayname() ?? - event.senderFromMemoryOrFallback - .calcDisplayname(); - return Text( - displayname, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: (Theme.of(context).brightness == - Brightness.light - ? displayname.color - : displayname.lightColorText), - ), - ); - }, - ), - ), - Container( - alignment: alignment, - padding: const EdgeInsets.only(left: 8), - child: Material( - color: noBubble ? Colors.transparent : color, - borderRadius: borderRadius, - clipBehavior: Clip.antiAlias, - child: InkWell( - onHover: (b) => useMouse = true, - onTap: !useMouse && longPressSelect - ? () {} - : () => onSelect!(event), - onLongPress: !longPressSelect ? null : () => onSelect!(event), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + if (!sameSender) + Padding( + padding: const EdgeInsets.only(left: 8.0, bottom: 4), + child: ownMessage || event.room.isDirectChat + ? const SizedBox(height: 12) + : FutureBuilder( + future: event.fetchSenderUser(), + builder: (context, snapshot) { + final displayname = + snapshot.data?.calcDisplayname() ?? + event.senderFromMemoryOrFallback + .calcDisplayname(); + return Text( + displayname, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: (Theme.of(context).brightness == + Brightness.light + ? displayname.color + : displayname.lightColorText), + ), + ); + }, + ), + ), + Container( + alignment: alignment, + padding: const EdgeInsets.only(left: 8), + child: Material( + color: noBubble ? Colors.transparent : color, borderRadius: borderRadius, + clipBehavior: Clip.antiAlias, child: Container( decoration: BoxDecoration( borderRadius: @@ -292,15 +289,10 @@ class Message extends StatelessWidget { ), ), ), - ), - ], + ], + ), ), - ), - ]; - final row = Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: rowMainAxisAlignment, - children: rowChildren, + ], ); Widget container; if (event.hasAggregatedEvents(timeline, RelationshipTypes.reaction) || @@ -400,17 +392,26 @@ class Message extends StatelessWidget { direction: SwipeDirection.endToStart, onSwipe: onSwipe, child: Center( - child: Container( - color: selected - ? Theme.of(context).primaryColor.withAlpha(100) - : Theme.of(context).primaryColor.withAlpha(0), - constraints: - const BoxConstraints(maxWidth: FluffyThemes.columnWidth * 2.5), - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 4.0, + child: MouseRegion( + onEnter: (_) => useMouse = true, + onExit: (_) => useMouse = false, + child: InkWell( + onTap: longPressSelect || useMouse ? () => onSelect!(event) : null, + onLongPress: () => onSelect!(event), + child: Container( + color: selected + ? Theme.of(context).primaryColor.withAlpha(100) + : Theme.of(context).primaryColor.withAlpha(0), + constraints: const BoxConstraints( + maxWidth: FluffyThemes.columnWidth * 2.5, + ), + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 4.0, + ), + child: container, + ), ), - child: container, ), ), );