Skip to content

Commit

Permalink
fix: simplify seen by indicator
Browse files Browse the repository at this point in the history
  • Loading branch information
Feichtmeier committed Jan 12, 2025
1 parent 17903aa commit 69e17a6
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 88 deletions.
6 changes: 6 additions & 0 deletions lib/chat/chat_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ class ChatModel extends SafeChangeNotifier {
/// The unfiltered onSync stream of the [Client]
Stream<SyncUpdate> get syncStream => _client.onSync.stream;

Stream<List<Receipt>> getRoomsReceipts(Event event) =>
getJoinedRoomUpdate(event.room.id).map((_) => event.receipts);

Future<List<User>> requestParticipants(Room room) async =>
room.requestParticipants();

Stream<List<User>> getUsersStreamOfJoinedRoom(
Room room, {
List<Membership> membershipFilter = const [
Expand Down
19 changes: 0 additions & 19 deletions lib/chat/room_x.dart
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
import 'package:matrix/matrix.dart';

extension RoomX on Room {
List<User> getSeenByUsers(List<Event> events, {String? eventId}) {
if (events.isEmpty) return [];
eventId ??= events.first.eventId;

final lastReceipts = <User>{};
for (final e in events) {
lastReceipts.addAll(
e.receipts.map((r) => r.user).where(
(u) => u.id != client.userID && u.id != events.first.senderId,
),
);
if (e.eventId == eventId) {
break;
}
}

return lastReceipts.toList();
}

bool get canEditAtleastSomething =>
ownPowerLevel == 100 ||
canKick ||
Expand Down
2 changes: 1 addition & 1 deletion lib/chat/timeline_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class TimelineModel extends SafeChangeNotifier {

Future<void> requestHistory(
Timeline timeline, {
int historyCount = 350,
int historyCount = 50,
StateFilter? filter,
bool notify = true,
}) async {
Expand Down
1 change: 0 additions & 1 deletion lib/chat/view/chat_room/chat_room_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ class _ChatRoomPageState extends State<ChatRoomPage> {
void initState() {
super.initState();
_timelineFuture = widget.room.getTimeline(
onUpdate: () => _roomListKey.currentState?.setState(() {}),
onNewEvent: () => _roomListKey.currentState?.setState(() {}),
onChange: (i) => _roomListKey.currentState?.setState(() {}),
onInsert: (i) => _roomListKey.currentState?.insertItem(i),
Expand Down
29 changes: 21 additions & 8 deletions lib/chat/view/chat_room/chat_room_timeline_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import '../../../common/view/theme.dart';
import '../../../common/view/ui_constants.dart';
import '../../timeline_model.dart';
import '../events/chat_event_column.dart';
import 'chat_seen_by_indicator.dart';
import 'chat_typing_indicator.dart';
import 'titlebar/chat_room_title_bar.dart';

Expand Down Expand Up @@ -83,14 +84,26 @@ class _ChatRoomTimelineListState extends State<ChatRoomTimelineList> {
key: ValueKey('${event.eventId}tag'),
child: FadeTransition(
opacity: animation,
child: ChatEventColumn(
key: ValueKey('${event.eventId}column'),
event: event,
maybePreviousEvent: maybePreviousEvent,
jump: _jump,
showSeenByIndicator: i == 0,
timeline: widget.timeline,
room: widget.room,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ChatEventColumn(
key: ValueKey('${event.eventId}column'),
event: event,
maybePreviousEvent: maybePreviousEvent,
jump: _jump,
showSeenByIndicator: i == 0,
timeline: widget.timeline,
room: widget.room,
),
if (i == 0)
ChatEventSeenByIndicator(
key: ValueKey(
'${event.eventId}${widget.timeline.events.length}',
),
event: event,
),
],
),
),
);
Expand Down
116 changes: 63 additions & 53 deletions lib/chat/view/chat_room/chat_seen_by_indicator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,42 @@ import 'package:watch_it/watch_it.dart';
import '../../../common/view/build_context_x.dart';
import '../../../common/view/ui_constants.dart';
import '../../chat_model.dart';
import '../../room_x.dart';
import '../../search_model.dart';
import '../chat_avatar.dart';
import '../chat_profile_dialog.dart';

class ChatSeenByIndicator extends StatefulWidget
with WatchItStatefulWidgetMixin {
const ChatSeenByIndicator({
class ChatEventSeenByIndicator extends StatelessWidget with WatchItMixin {
const ChatEventSeenByIndicator({
super.key,
required this.room,
required this.timeline,
required this.event,
});

final Room room;
final Timeline timeline;
final Event event;

static const maxAvatars = 7;

@override
State<ChatSeenByIndicator> createState() => _ChatSeenByIndicatorState();
}

class _ChatSeenByIndicatorState extends State<ChatSeenByIndicator> {
@override
void initState() {
super.initState();
widget.room.requestParticipants();
}

@override
Widget build(BuildContext context) {
final events = watchStream(
(ChatModel m) => m.getReadEventsFromSync(widget.room),
initialValue: widget.timeline.events,
).data;
final list = <Event>{...widget.timeline.events, ...?events}.toList();
final seenByUsers = widget.room.getSeenByUsers(list);
watchFuture(
(ChatModel m) => m.requestParticipants(event.room),
initialValue: event.room.getParticipants(),
);

final seenByUsers = watchStream(
(ChatModel m) => m.getRoomsReceipts(event),
initialValue: event.receipts,
)
.data
?.map((e) => e.user)
.where((e) => e.id != di<ChatModel>().myUserId)
.toList() ??
[];

return Container(
width: double.infinity,
alignment: widget.room.isDirectChat ||
di<ChatModel>().isUserEvent(list.first) &&
list.first.type != EventTypes.Reaction
alignment: event.room.isDirectChat ||
di<ChatModel>().isUserEvent(event) &&
event.type != EventTypes.Reaction
? Alignment.centerRight
: Alignment.centerLeft,
child: AnimatedContainer(
Expand All @@ -60,35 +53,19 @@ class _ChatSeenByIndicatorState extends State<ChatSeenByIndicator> {
child: Wrap(
spacing: kSmallPadding,
children: [
...(seenByUsers.length > ChatSeenByIndicator.maxAvatars
? seenByUsers.sublist(0, ChatSeenByIndicator.maxAvatars)
...(seenByUsers.length > maxAvatars
? seenByUsers.sublist(
0,
maxAvatars,
)
: seenByUsers)
.map(
(user) => Tooltip(
(user) => ChatEventSeenByAvatar(
key: ValueKey(user.id + user.avatarUrl.toString()),
message: user.displayName ?? user.id,
child: InkWell(
borderRadius: BorderRadius.circular(15),
onTap: () async {
final profile =
await di<SearchModel>().lookupProfile(user.id);
if (context.mounted) {
showDialog(
context: context,
builder: (context) =>
ChatProfileDialog(userId: profile.userId),
);
}
},
child: ChatAvatar(
avatarUri: user.avatarUrl,
fallBackIconSize: 10,
dimension: 15,
),
),
user: user,
),
),
if (seenByUsers.length > ChatSeenByIndicator.maxAvatars)
if (seenByUsers.length > maxAvatars)
SizedBox(
width: 15,
height: 15,
Expand All @@ -97,7 +74,7 @@ class _ChatSeenByIndicatorState extends State<ChatSeenByIndicator> {
borderRadius: BorderRadius.circular(30),
child: Center(
child: Text(
'+${seenByUsers.length - ChatSeenByIndicator.maxAvatars}',
'+${seenByUsers.length - maxAvatars}',
style: const TextStyle(fontSize: 9),
),
),
Expand All @@ -109,3 +86,36 @@ class _ChatSeenByIndicatorState extends State<ChatSeenByIndicator> {
);
}
}

class ChatEventSeenByAvatar extends StatelessWidget {
const ChatEventSeenByAvatar({
super.key,
required this.user,
});

final User user;

@override
Widget build(BuildContext context) {
return Tooltip(
message: user.displayName ?? user.id,
child: InkWell(
borderRadius: BorderRadius.circular(15),
onTap: () async {
final profile = await di<SearchModel>().lookupProfile(user.id);
if (context.mounted) {
showDialog(
context: context,
builder: (context) => ChatProfileDialog(userId: profile.userId),
);
}
},
child: ChatAvatar(
avatarUri: user.avatarUrl,
fallBackIconSize: 10,
dimension: 15,
),
),
);
}
}
6 changes: 0 additions & 6 deletions lib/chat/view/events/chat_event_column.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import '../../../common/date_time_x.dart';
import '../../../common/view/build_context_x.dart';
import '../../../l10n/l10n.dart';
import '../../event_x.dart';
import '../chat_room/chat_seen_by_indicator.dart';
import 'chat_event_tile.dart';

class ChatEventColumn extends StatelessWidget {
Expand Down Expand Up @@ -52,11 +51,6 @@ class ChatEventColumn extends StatelessWidget {
maybePreviousEvent,
),
),
if (showSeenByIndicator)
ChatSeenByIndicator(
room: room,
timeline: timeline,
),
],
);
}
Expand Down

0 comments on commit 69e17a6

Please sign in to comment.