Skip to content

Commit

Permalink
chore: move event column back to list, avatar outside bubbles
Browse files Browse the repository at this point in the history
  • Loading branch information
Feichtmeier committed Jan 16, 2025
1 parent 73fdd51 commit ad4e7d1
Show file tree
Hide file tree
Showing 18 changed files with 450 additions and 475 deletions.
5 changes: 3 additions & 2 deletions lib/chat/bootstrap/view/key_verification_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:matrix/matrix.dart';
import 'package:yaru/yaru.dart';

import '../../../common/view/build_context_x.dart';
import '../../../common/view/ui_constants.dart';
import '../../../l10n/l10n.dart';
import '../../common/view/chat_avatar.dart';
import '../../chat_master/view/chat_master_detail_page.dart';
Expand Down Expand Up @@ -218,8 +219,8 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
avatarUri: user?.avatarUrl,
),
const SizedBox(
width: 38,
height: 38,
width: kAvatarDefaultSize,
height: kAvatarDefaultSize,
child: CircularProgressIndicator(strokeWidth: 2),
),
],
Expand Down
4 changes: 2 additions & 2 deletions lib/chat/chat_master/view/chat_space_control_panel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ChatSpaceControlPanel extends StatelessWidget with WatchItMixin {
spacing: kMediumPadding,
children: [
SizedBox.square(
dimension: 38,
dimension: kAvatarDefaultSize,
child: OutlinedButton(
style: OutlinedButton.styleFrom(
padding: EdgeInsets.zero,
Expand Down Expand Up @@ -55,7 +55,7 @@ class ChatSpaceControlPanel extends StatelessWidget with WatchItMixin {
),
),
SizedBox.square(
dimension: 38,
dimension: kAvatarDefaultSize,
child: OutlinedButton(
style: OutlinedButton.styleFrom(
padding: EdgeInsets.zero,
Expand Down
1 change: 0 additions & 1 deletion lib/chat/chat_room/common/view/chat_room_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ class _ChatRoomPageState extends State<ChatRoomPage> {
padding: const EdgeInsets.only(bottom: kMediumPadding),
child: ChatRoomTimelineList(
timeline: snapshot.data!,
room: widget.room,
listKey: _roomListKey,
),
);
Expand Down
139 changes: 78 additions & 61 deletions lib/chat/chat_room/common/view/chat_room_timeline_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@ import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:watch_it/watch_it.dart';
import 'package:yaru/yaru.dart';

import '../../../../common/date_time_x.dart';
import '../../../../common/view/build_context_x.dart';
import '../../../../common/view/theme.dart';
import '../../../../common/view/ui_constants.dart';
import '../../../events/view/chat_event_column.dart';
import '../../../../l10n/l10n.dart';
import '../../../common/event_x.dart';
import '../../../events/view/chat_event_tile.dart';
import '../../../settings/settings_model.dart';
import '../../titlebar/chat_room_title_bar.dart';
import '../timeline_model.dart';
import 'chat_seen_by_indicator.dart';
import 'chat_typing_indicator.dart';

class ChatRoomTimelineList extends StatefulWidget
with WatchItStatefulWidgetMixin {
const ChatRoomTimelineList({
super.key,
required this.timeline,
required this.listKey,
required this.room,
});

final Timeline timeline;
final Room room;
final GlobalKey<AnimatedListState> listKey;

@override
Expand Down Expand Up @@ -52,67 +53,82 @@ class _ChatRoomTimelineListState extends State<ChatRoomTimelineList> {
@override
Widget build(BuildContext context) {
final theme = context.theme;
final showAvatarChanges =
watchPropertyValue((SettingsModel m) => m.showChatAvatarChanges);
final showDisplayNameChanges =
watchPropertyValue((SettingsModel m) => m.showChatDisplaynameChanges);

return Stack(
children: [
Column(
children: [
Expanded(
child: NotificationListener<ScrollEndNotification>(
onNotification: onScroll,
child: AnimatedList(
controller: _controller,
padding: const EdgeInsets.symmetric(
horizontal: kMediumPadding,
),
key: widget.listKey,
reverse: true,
initialItemCount: widget.timeline.events.length,
itemBuilder: (context, i, animation) {
final event = widget.timeline.events[i];

final maybePreviousEvent =
widget.timeline.events.elementAtOrNull(i + 1);

if (i == 0 && !widget.room.isArchived) {
widget.timeline.setReadMarker();
}

return AutoScrollTag(
index: i,
controller: _controller,
key: ValueKey('${event.eventId}tag'),
child: FadeTransition(
opacity: animation,
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,
),
],
NotificationListener<ScrollEndNotification>(
onNotification: onScroll,
child: AnimatedList(
controller: _controller,
padding: const EdgeInsets.symmetric(
horizontal: kMediumPadding,
vertical: kSmallPadding,
),
key: widget.listKey,
reverse: true,
initialItemCount: widget.timeline.events.length,
itemBuilder: (context, i, animation) {
final event = widget.timeline.events[i];

if (event.hideEventInTimeline(
showAvatarChanges: showAvatarChanges,
showDisplayNameChanges: showDisplayNameChanges,
)) {
return SizedBox.shrink(
key: ValueKey(ValueKey(event.eventId)),
);
}

final previous = widget.timeline.events.elementAtOrNull(i + 1);

if (i == 0 && !widget.timeline.room.isArchived) {
widget.timeline.setReadMarker();
}

return AutoScrollTag(
index: i,
controller: _controller,
key: ValueKey('${event.eventId}tag'),
child: FadeTransition(
opacity: animation,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (previous != null &&
event.originServerTs.toLocal().day !=
previous.originServerTs.toLocal().day)
Text(
previous.originServerTs
.toLocal()
.formatAndLocalizeDay(context.l10n),
textAlign: TextAlign.center,
style: theme.textTheme.labelSmall,
),
ChatEventTile(
key: ValueKey('${event.eventId}column'),
event: event,
partOfMessageCohort:
event.partOfMessageCohort(previous),
onReplyOriginClick: (event) => _jump(event),
timeline: widget.timeline,
),
);
},
if (i == 0)
ChatEventSeenByIndicator(
key: ValueKey(
'${event.eventId}${widget.timeline.events.length}',
),
event: event,
),
],
),
),
),
),
ChatTypingIndicator(room: widget.room),
],
);
},
),
),
if (_showScrollButton)
Positioned(
Expand All @@ -127,7 +143,8 @@ class _ChatRoomTimelineListState extends State<ChatRoomTimelineList> {
backgroundColor: getMonochromeBg(theme: theme, darkFactor: 5),
onPressed: () => showDialog(
context: context,
builder: (context) => ChatRoomSearchDialog(room: widget.room),
builder: (context) =>
ChatRoomSearchDialog(room: widget.timeline.room),
),
child: Icon(
YaruIcons.search,
Expand Down Expand Up @@ -190,7 +207,7 @@ class _ChatRoomTimelineListState extends State<ChatRoomTimelineList> {
retryCount--;
}
await _maybeScrollTo(index);
if (!widget.room.isArchived) {
if (!widget.timeline.room.isArchived) {
widget.timeline.setReadMarker(eventId: event.eventId);
}
}
Expand Down
6 changes: 1 addition & 5 deletions lib/chat/chat_room/common/view/chat_seen_by_indicator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,7 @@ class ChatEventSeenByIndicator extends StatelessWidget with WatchItMixin {

return Container(
width: double.infinity,
alignment: event.room.isDirectChat ||
di<ChatModel>().isUserEvent(event) &&
event.type != EventTypes.Reaction
? Alignment.centerRight
: Alignment.centerLeft,
alignment: Alignment.center,
child: AnimatedContainer(
padding: const EdgeInsets.symmetric(
vertical: kSmallPadding,
Expand Down
45 changes: 22 additions & 23 deletions lib/chat/chat_room/common/view/chat_typing_indicator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,14 @@ class ChatTypingIndicator extends StatelessWidget with WatchItMixin {
[];

return AnimatedContainer(
height: typingUsers.isEmpty ? 0 : kTypingAvatarSize + kMediumPadding,
height: typingUsers.isEmpty ? 0 : kTypingAvatarSize,
duration: kAvatarAnimationDuration,
curve: kAvatarAnimationCurve,
alignment: Alignment.centerLeft,
clipBehavior: Clip.hardEdge,
decoration: const BoxDecoration(),
padding: const EdgeInsets.symmetric(
horizontal: kBigPadding,
vertical: kSmallPadding,
),
child: Row(
mainAxisSize: MainAxisSize.min,
Expand All @@ -55,7 +54,7 @@ class ChatTypingIndicator extends StatelessWidget with WatchItMixin {
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: kMediumPadding,
horizontal: kSmallPadding,
),
child: typingUsers.isEmpty ? null : const _TypingDots(),
),
Expand Down Expand Up @@ -105,27 +104,27 @@ class __TypingDotsState extends State<_TypingDots> {
@override
Widget build(BuildContext context) {
final theme = context.theme;
const size = 8.0;

return Row(
mainAxisSize: MainAxisSize.min,
children: [
for (var i = 1; i <= 3; i++)
AnimatedContainer(
duration: animationDuration * 1.5,
curve: Curves.bounceIn,
width: size,
height: _tick == i ? size * 2 : size,
margin: EdgeInsets.symmetric(
horizontal: 2,
vertical: _tick == i ? 4 : 8,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(size * 2),
color: theme.colorScheme.secondary,
const size = kTypingAvatarSize / 3;

return Padding(
padding: const EdgeInsets.symmetric(vertical: kSmallPadding),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
for (var i = 1; i <= 3; i++)
AnimatedContainer(
duration: animationDuration * 1.5,
curve: Curves.bounceIn,
width: size,
height: _tick == i ? size * 3 : size,
margin: const EdgeInsets.symmetric(horizontal: size / 2),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(size * 2),
color: theme.colorScheme.primary,
),
),
),
],
],
),
);
}
}
Loading

0 comments on commit ad4e7d1

Please sign in to comment.