Merge pull request #721 from pangeachat/overlay-reactions
Overlay reactions
This commit is contained in:
commit
91c984103c
2 changed files with 64 additions and 13 deletions
|
|
@ -1251,7 +1251,14 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
)) {
|
||||
return;
|
||||
}
|
||||
return sendEmojiAction(emoji.emoji);
|
||||
// #Pangea
|
||||
// return sendEmojiAction(emoji.emoji);
|
||||
sendEmojiAction(emoji.emoji);
|
||||
|
||||
// don't need to clear these when sending while in select mode,
|
||||
// but do need to clear these when reacting from the large emoji picker
|
||||
setState(() => selectedEvents.clear());
|
||||
// Pangea#
|
||||
}
|
||||
|
||||
void typeEmoji(Emoji? emoji) {
|
||||
|
|
@ -1298,16 +1305,16 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
|
||||
void sendEmojiAction(String? emoji) async {
|
||||
final events = List<Event>.from(selectedEvents);
|
||||
setState(() => selectedEvents.clear());
|
||||
// #Pangea
|
||||
// keep this event selected in case the user wants to send another emoji
|
||||
// setState(() => selectedEvents.clear());
|
||||
// Pangea#
|
||||
for (final event in events) {
|
||||
await room.sendReaction(
|
||||
event.eventId,
|
||||
emoji!,
|
||||
);
|
||||
}
|
||||
// #Pangea
|
||||
clearSelectedEvents();
|
||||
// Pangea#
|
||||
}
|
||||
|
||||
// #Pangea
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pages/chat/chat.dart';
|
||||
import 'package:fluffychat/pages/chat/events/message_reactions.dart';
|
||||
import 'package:fluffychat/pangea/enum/message_mode_enum.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
|
||||
|
|
@ -48,6 +50,7 @@ class MessageSelectionOverlay extends StatefulWidget {
|
|||
class MessageOverlayController extends State<MessageSelectionOverlay>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _animationController;
|
||||
StreamSubscription? _reactionSubscription;
|
||||
Animation<double>? _overlayPositionAnimation;
|
||||
|
||||
MessageMode toolbarMode = MessageMode.translation;
|
||||
|
|
@ -72,6 +75,26 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
activitiesLeftToComplete = activitiesLeftToComplete -
|
||||
widget._pangeaMessageEvent.numberOfActivitiesCompleted;
|
||||
|
||||
_reactionSubscription =
|
||||
widget.chatController.room.client.onSync.stream.where(
|
||||
(update) {
|
||||
// check if this sync update has a reaction event or a
|
||||
// redaction (of a reaction event). If so, rebuild the overlay
|
||||
final room = widget.chatController.room;
|
||||
final timelineEvents = update.rooms?.join?[room.id]?.timeline?.events;
|
||||
if (timelineEvents == null) return false;
|
||||
|
||||
final eventID = widget._pangeaMessageEvent.event.eventId;
|
||||
return timelineEvents.any(
|
||||
(e) =>
|
||||
e.type == EventTypes.Redaction ||
|
||||
(e.type == EventTypes.Reaction &&
|
||||
Event.fromMatrixEvent(e, room).relationshipEventId ==
|
||||
eventID),
|
||||
);
|
||||
},
|
||||
).listen((_) => setState(() {}));
|
||||
|
||||
setInitialToolbarMode();
|
||||
}
|
||||
|
||||
|
|
@ -215,7 +238,17 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
|
||||
PangeaTokenText? get selectedSpan => _selectedSpan;
|
||||
|
||||
final int toolbarButtonsHeight = 50;
|
||||
bool get hasReactions {
|
||||
final reactionsEvents = widget._pangeaMessageEvent.event.aggregatedEvents(
|
||||
widget.chatController.timeline!,
|
||||
RelationshipTypes.reaction,
|
||||
);
|
||||
return reactionsEvents.where((e) => !e.redacted).isNotEmpty;
|
||||
}
|
||||
|
||||
final double toolbarButtonsHeight = 50;
|
||||
double get reactionsHeight => hasReactions ? 28 : 0;
|
||||
double get belowMessageHeight => toolbarButtonsHeight + reactionsHeight;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
|
|
@ -230,7 +263,7 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
final currentBottomOffset = screenHeight -
|
||||
messageOffset!.dy -
|
||||
messageSize!.height -
|
||||
toolbarButtonsHeight;
|
||||
belowMessageHeight;
|
||||
|
||||
final bool hasHeaderOverflow =
|
||||
messageOffset!.dy < (AppConfig.toolbarMaxHeight + headerHeight);
|
||||
|
|
@ -247,13 +280,12 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
// check if shifting the overlay up could cause a header overflow
|
||||
final bottomOffsetDifference = footerHeight - currentBottomOffset;
|
||||
final newTopOffset =
|
||||
messageOffset!.dy - bottomOffsetDifference - toolbarButtonsHeight;
|
||||
messageOffset!.dy - bottomOffsetDifference - belowMessageHeight;
|
||||
final bool upshiftCausesHeaderOverflow = hasFooterOverflow &&
|
||||
newTopOffset < (headerHeight + AppConfig.toolbarMaxHeight);
|
||||
|
||||
if (hasHeaderOverflow || upshiftCausesHeaderOverflow) {
|
||||
animationEndOffset =
|
||||
midpoint - messageSize!.height - toolbarButtonsHeight;
|
||||
animationEndOffset = midpoint - messageSize!.height - belowMessageHeight;
|
||||
final totalTopOffset =
|
||||
animationEndOffset + messageSize!.height + AppConfig.toolbarMaxHeight;
|
||||
final remainingSpace = screenHeight - totalTopOffset;
|
||||
|
|
@ -270,12 +302,12 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
// If, after ajusting the overlay position, the message still overflows the footer,
|
||||
// update the message height to fit the screen. The message is scrollable, so
|
||||
// this will make the both the toolbar box and the toolbar buttons visible.
|
||||
if (animationEndOffset < footerHeight + toolbarButtonsHeight) {
|
||||
if (animationEndOffset < footerHeight + belowMessageHeight) {
|
||||
final double remainingSpace = screenHeight -
|
||||
AppConfig.toolbarMaxHeight -
|
||||
headerHeight -
|
||||
footerHeight -
|
||||
toolbarButtonsHeight;
|
||||
belowMessageHeight;
|
||||
|
||||
if (remainingSpace < messageSize!.height) {
|
||||
adjustedMessageHeight = remainingSpace;
|
||||
|
|
@ -305,6 +337,7 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
@override
|
||||
void dispose() {
|
||||
_animationController.dispose();
|
||||
_reactionSubscription?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
@ -386,6 +419,17 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
messageHeight: messageSize!.height,
|
||||
),
|
||||
),
|
||||
if (hasReactions)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: SizedBox(
|
||||
height: reactionsHeight - 8,
|
||||
child: MessageReactions(
|
||||
widget._pangeaMessageEvent.event,
|
||||
widget.chatController.timeline!,
|
||||
),
|
||||
),
|
||||
),
|
||||
ToolbarButtons(
|
||||
overlayController: this,
|
||||
width: 250,
|
||||
|
|
@ -418,7 +462,7 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
bottom: screenHeight -
|
||||
messageOffset!.dy -
|
||||
messageSize!.height -
|
||||
toolbarButtonsHeight,
|
||||
belowMessageHeight,
|
||||
child: overlayMessage,
|
||||
)
|
||||
: AnimatedBuilder(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue