Skip to content

Commit 0e372b1

Browse files
committed
TW-2586: Send several images in the same message bubble
1 parent fe4c41d commit 0e372b1

File tree

13 files changed

+506
-27
lines changed

13 files changed

+506
-27
lines changed

lib/pages/chat/chat.dart

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import 'package:fluffychat/pages/chat/chat_report_message_additional_reason_dial
2121
import 'package:fluffychat/pages/chat/chat_view.dart';
2222
import 'package:fluffychat/pages/chat/context_item_chat_action.dart';
2323
import 'package:fluffychat/pages/chat/dialog_reject_invite_widget.dart';
24+
import 'package:fluffychat/presentation/mixins/grouped_events_mixin.dart';
2425
import 'package:fluffychat/pages/chat/events/message_content_mixin.dart';
2526
import 'package:fluffychat/pages/chat/input_bar/focus_suggestion_controller.dart';
2627
import 'package:fluffychat/presentation/enum/chat/right_column_type_enum.dart';
@@ -133,7 +134,8 @@ class ChatController extends State<Chat>
133134
LeaveChatMixin,
134135
DeleteEventMixin,
135136
UnblockUserMixin,
136-
AudioMixin {
137+
AudioMixin,
138+
EventGrouperMixin {
137139
final NetworkConnectionService networkConnectionService =
138140
getIt.get<NetworkConnectionService>();
139141

@@ -1108,17 +1110,22 @@ class ChatController extends State<Chat>
11081110
return eventIndex + addedHeadItemsInChat;
11091111
}
11101112

1113+
List<GroupedEvents> get groupedEvents => groupEvents(timeline?.events ?? []);
1114+
11111115
int _getEventIndex(String eventId) {
1112-
final foundEvent =
1113-
timeline!.events.firstWhereOrNull((event) => event.eventId == eventId);
1116+
// Find the group that contains the eventId (in main or additional events)
1117+
final foundGroup = groupedEvents.firstWhereOrNull(
1118+
(group) => group.allEvents.any((event) => event.eventId == eventId),
1119+
);
11141120

1115-
final eventIndex = foundEvent == null
1116-
? -1
1117-
: timeline!.events.indexWhere(
1118-
(event) => event.eventId == foundEvent.eventId,
1119-
);
1121+
if (foundGroup == null) {
1122+
return -1;
1123+
}
11201124

1121-
return eventIndex;
1125+
// Return the index of the main event in the original timeline
1126+
return timeline!.events.indexWhere(
1127+
(event) => event.eventId == foundGroup.mainEvent.eventId,
1128+
);
11221129
}
11231130

11241131
Future<void> scrollToEventId(String eventId, {bool highlight = true}) async {

lib/pages/chat/chat_event_list.dart

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,20 @@ class ChatEventList extends StatelessWidget {
2929
Widget build(BuildContext context) {
3030
final horizontalPadding = TwakeThemes.isColumnMode(context) ? 16.0 : 0.0;
3131

32-
final events = controller.timeline!.events;
33-
// create a map of eventId --> index to greatly improve performance of
32+
// Group consecutive image events
33+
final groupedEvents = controller.groupedEvents;
34+
35+
// create a map of eventId --> grouped index to greatly improve performance of
3436
// ListView's findChildIndexCallback
37+
// This maps all event IDs (including those in groups) to their group's index
3538
final thisEventsKeyMap = <String, int>{};
36-
for (var i = 0; i < events.length; i++) {
37-
thisEventsKeyMap[events[i].eventId] = i;
39+
for (var i = 0; i < groupedEvents.length; i++) {
40+
final group = groupedEvents[i];
41+
// Map the main event and all additional events to the same group index
42+
for (final event in group.allEvents) {
43+
// Add 1 to account for the first item (footer)
44+
thisEventsKeyMap[event.eventId] = i + 1;
45+
}
3846
}
3947

4048
if (controller.hasNoMessageEvents) {
@@ -117,7 +125,7 @@ class ChatEventList extends StatelessWidget {
117125
return const SizedBox.shrink();
118126
}
119127
// Request history button or progress indicator:
120-
if (index == events.length + 1) {
128+
if (index == groupedEvents.length + 1) {
121129
if (controller.timeline!.isRequestingHistory) {
122130
return const Center(
123131
child: CupertinoActivityIndicator(),
@@ -133,14 +141,18 @@ class ChatEventList extends StatelessWidget {
133141
}
134142
return const SizedBox.shrink();
135143
}
136-
final currentEventIndex = index - 1;
137-
final event = events[currentEventIndex];
138-
final previousEvent = currentEventIndex > 0
139-
? events[currentEventIndex - 1]
140-
: null;
141-
final nextEvent = index < events.length
142-
? events[currentEventIndex + 1]
144+
145+
final currentGroupIndex = index - 1;
146+
final group = groupedEvents[currentGroupIndex];
147+
final event = group.mainEvent;
148+
149+
final previousEvent = currentGroupIndex > 0
150+
? groupedEvents[currentGroupIndex - 1].mainEvent
143151
: null;
152+
final nextEvent =
153+
currentGroupIndex < groupedEvents.length - 1
154+
? groupedEvents[currentGroupIndex + 1].mainEvent
155+
: null;
144156
return event.isVisibleInGui
145157
? AutoScrollTag(
146158
key: ValueKey(event.eventId),
@@ -237,11 +249,12 @@ class ChatEventList extends StatelessWidget {
237249
.getRecentReactionsInteractor
238250
.execute(),
239251
onReport: controller.reportEventAction,
252+
groupedEvents: group.isGrouped ? group : null,
240253
),
241254
)
242255
: const SizedBox.shrink();
243256
},
244-
childCount: events.length + 2,
257+
childCount: groupedEvents.length + 2,
245258
findChildIndexCallback: (key) => controller
246259
.findChildIndexCallback(key, thisEventsKeyMap),
247260
),

lib/pages/chat/events/images_builder/message_content_image_builder.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@ class MessageImageBuilder extends StatelessWidget {
1717

1818
final double? maxWidth;
1919

20+
final bool rounded;
21+
2022
const MessageImageBuilder({
2123
super.key,
2224
required this.event,
2325
this.onTapPreview,
2426
this.onTapSelectMode,
2527
this.maxWidth,
28+
this.rounded = true,
2629
});
2730

2831
@override
@@ -44,6 +47,7 @@ class MessageImageBuilder extends StatelessWidget {
4447
event: event,
4548
onTapPreview: onTapPreview,
4649
displayImageInfo: displayImageInfo,
50+
rounded: rounded,
4751
);
4852
}
4953
displayImageInfo ??= DisplayImageInfo(
@@ -65,6 +69,7 @@ class MessageImageBuilder extends StatelessWidget {
6569
event: event,
6670
onTapPreview: onTapPreview,
6771
displayImageInfo: displayImageInfo,
72+
rounded: rounded,
6873
);
6974
}
7075
return ImageBubble(
@@ -76,6 +81,8 @@ class MessageImageBuilder extends StatelessWidget {
7681
onTapPreview: onTapPreview,
7782
animated: true,
7883
thumbnailOnly: true,
84+
thumbnailCacheKey: event.eventId,
85+
rounded: rounded,
7986
);
8087
}
8188
}

lib/pages/chat/events/images_builder/sending_image_info_widget.dart

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class SendingImageInfoWidget extends StatefulWidget {
2222
required this.event,
2323
required this.displayImageInfo,
2424
this.onTapPreview,
25+
this.rounded = true,
2526
});
2627

2728
final MatrixImageFile matrixFile;
@@ -32,6 +33,8 @@ class SendingImageInfoWidget extends StatefulWidget {
3233

3334
final DisplayImageInfo displayImageInfo;
3435

36+
final bool rounded;
37+
3538
@override
3639
State<SendingImageInfoWidget> createState() => _SendingImageInfoWidgetState();
3740
}
@@ -44,7 +47,6 @@ class _SendingImageInfoWidgetState extends State<SendingImageInfoWidget>
4447
@override
4548
void dispose() {
4649
sendingFileProgressNotifier.dispose();
47-
uploadFileStateNotifier.dispose();
4850
super.dispose();
4951
}
5052

@@ -112,11 +114,14 @@ class _SendingImageInfoWidgetState extends State<SendingImageInfoWidget>
112114
);
113115
},
114116
child: Material(
115-
borderRadius: MessageContentStyle.borderRadiusBubble,
117+
borderRadius:
118+
widget.rounded ? MessageContentStyle.borderRadiusBubble : null,
116119
child: InkWell(
117120
onTap: () => _onTap(context),
118121
child: ClipRRect(
119-
borderRadius: MessageContentStyle.borderRadiusBubble,
122+
borderRadius: widget.rounded
123+
? MessageContentStyle.borderRadiusBubble
124+
: BorderRadius.zero,
120125
child: Stack(
121126
alignment: Alignment.center,
122127
children: [

0 commit comments

Comments
 (0)