Skip to content

Commit 0d7a29f

Browse files
authored
feat: youtube previews (#138)
* feat: youtube previews * add timeline history commands * fix: streamline history request handling in TimelineManager
1 parent da23a4b commit 0d7a29f

15 files changed

+280
-117
lines changed

lib/chat_master/view/chat_edit_room_mixin.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
22
import 'package:flutter_it/flutter_it.dart';
33

44
import '../../chat_room/create_or_edit/edit_room_manager.dart';
5+
import '../../chat_room/timeline/timeline_manager.dart';
56
import '../../l10n/l10n.dart';
67
import 'chat_clear_archive_progress_bar.dart';
78

@@ -32,8 +33,12 @@ mixin ChatEditRoomMixin {
3233
),
3334
action: SnackBarAction(
3435
label: context.l10n.delete,
35-
onPressed: () => di<EditRoomManager>().globalForgetRoomCommand
36-
.run(newValue.data),
36+
onPressed: () {
37+
di<EditRoomManager>().globalForgetRoomCommand.run(
38+
newValue.data,
39+
);
40+
di<TimelineManager>().removeTimeline(newValue.data!.id);
41+
},
3742
),
3843
),
3944
);

lib/chat_room/common/view/chat_room_page.dart

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ import '../../../app/view/mouse_and_keyboard_command_wrapper.dart';
1313
import '../../../chat_master/view/chat_space_discover_button.dart';
1414
import '../../../chat_master/view/chat_spaces_search_list.dart';
1515
import '../../../common/chat_manager.dart';
16-
import '../../../common/view/build_context_x.dart';
1716
import '../../../common/view/common_widgets.dart';
1817
import '../../../common/view/confirm.dart';
1918
import '../../../common/view/snackbars.dart';
20-
import '../../../common/view/theme.dart';
2119
import '../../../common/view/ui_constants.dart';
2220
import '../../../l10n/l10n.dart';
2321
import '../../create_or_edit/edit_room_manager.dart';
@@ -143,11 +141,6 @@ class _ChatRoomPageState extends State<ChatRoomPage> {
143141
}
144142

145143
final l10n = context.l10n;
146-
final colorScheme = context.colorScheme;
147-
148-
final updating = watchPropertyValue(
149-
(TimelineManager m) => m.getUpdatingTimeline(widget.room.id),
150-
);
151144

152145
final threadeMode = watchPropertyValue((DraftManager m) => m.threadMode);
153146

@@ -243,28 +236,6 @@ class _ChatRoomPageState extends State<ChatRoomPage> {
243236
},
244237
),
245238
),
246-
if (updating &&
247-
chatRoomScaffoldKey.currentState?.isEndDrawerOpen != true)
248-
Positioned(
249-
top: 4 * kBigPadding,
250-
child: RepaintBoundary(
251-
child: CircleAvatar(
252-
backgroundColor: getMonochromeBg(
253-
theme: context.theme,
254-
factor: 3,
255-
darkFactor: 4,
256-
),
257-
maxRadius: 15,
258-
child: SizedBox.square(
259-
dimension: 18,
260-
child: Progress(
261-
strokeWidth: 2,
262-
color: colorScheme.onSurface,
263-
),
264-
),
265-
),
266-
),
267-
),
268239
],
269240
),
270241
),

lib/chat_room/info_drawer/chat_room_info_drawer_forget_button.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import '../../common/view/build_context_x.dart';
88
import '../../common/view/ui_constants.dart';
99
import '../../l10n/l10n.dart';
1010
import '../create_or_edit/edit_room_manager.dart';
11+
import '../timeline/timeline_manager.dart';
1112

1213
class ChatRoomInfoDrawerForgetButton extends StatelessWidget {
1314
const ChatRoomInfoDrawerForgetButton({super.key, required this.room});
@@ -38,6 +39,7 @@ class ChatRoomInfoDrawerForgetButton extends StatelessWidget {
3839
onPressed: () {
3940
di<ChatManager>().setSelectedRoom(null);
4041
di<EditRoomManager>().globalForgetRoomCommand.run(room);
42+
di<TimelineManager>().removeTimeline(room.id);
4143
},
4244
icon: Icon(
4345
YaruIcons.trash,

lib/chat_room/info_drawer/chat_room_info_drawer_media_grid.dart

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import 'package:flutter_it/flutter_it.dart';
33
import 'package:matrix/matrix.dart';
44
import 'package:yaru/yaru.dart';
55

6-
import '../../common/chat_manager.dart';
76
import '../../common/view/build_context_x.dart';
87
import '../../common/view/common_widgets.dart';
98
import '../../common/view/ui_constants.dart';
@@ -98,15 +97,12 @@ class ChatRoomInfoMediaGrid extends StatelessWidget
9897
final colorScheme = context.colorScheme;
9998
final l10n = context.l10n;
10099

101-
watchStream((ChatManager m) => m.getEventStream(room), initialValue: null);
102-
watchStream(
103-
(ChatManager m) => m.getHistoryStream(room),
104-
initialValue: null,
100+
final t = watchValue(
101+
(TimelineManager m) => m.getRequestHistoryCommand(room.id).results,
105102
);
106103

107-
final timeline = watchPropertyValue(
108-
(TimelineManager m) => m.getTimeline(room.id),
109-
);
104+
final timeline =
105+
t.paramData?.timeline ?? di<TimelineManager>().getTimeline(room.id);
110106

111107
if (timeline == null) {
112108
return Center(
@@ -132,11 +128,11 @@ class ChatRoomInfoMediaGrid extends StatelessWidget
132128
return Center(
133129
child: NotificationListener<ScrollEndNotification>(
134130
onNotification: (notification) {
135-
di<TimelineManager>().requestHistory(
136-
timeline,
131+
di<TimelineManager>().getRequestHistoryCommand(timeline.room.id).run((
132+
timeline: timeline,
133+
historyCount: 100,
137134
filter: StateFilter(types: [EventTypes.Message]),
138-
historyCount: 1000,
139-
);
135+
));
140136

141137
return true;
142138
},
@@ -208,8 +204,9 @@ class ChatLoadMoreHistoryButton extends StatelessWidget with WatchItMixin {
208204

209205
@override
210206
Widget build(BuildContext context) {
211-
final updatingTimeline = watchPropertyValue(
212-
(TimelineManager m) => m.getUpdatingTimeline(timeline.room.id),
207+
final updatingTimeline = watchValue(
208+
(TimelineManager m) =>
209+
m.getRequestHistoryCommand(timeline.room.id).isRunning,
213210
);
214211

215212
return OutlinedButton.icon(
@@ -219,11 +216,12 @@ class ChatLoadMoreHistoryButton extends StatelessWidget with WatchItMixin {
219216
child: Progress(strokeWidth: 2),
220217
)
221218
: const Icon(YaruIcons.refresh),
222-
onPressed: () => di<TimelineManager>().requestHistory(
223-
timeline,
224-
filter: StateFilter(types: [EventTypes.Message]),
225-
historyCount: 1000,
226-
),
219+
onPressed: () =>
220+
di<TimelineManager>().getRequestHistoryCommand(timeline.room.id).run((
221+
timeline: timeline,
222+
historyCount: 1000,
223+
filter: StateFilter(types: [EventTypes.Message]),
224+
)),
227225
label: Text(context.l10n.loadMore),
228226
);
229227
}

lib/chat_room/info_drawer/chat_room_info_drawer_media_grid_headline.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ class ChatRoomInfoDrawerMediaGridHeadline extends StatelessWidget
1515

1616
@override
1717
Widget build(BuildContext context) {
18-
final updating = watchPropertyValue(
19-
(TimelineManager m) => m.getUpdatingTimeline(room.id),
18+
final updating = watchValue(
19+
(TimelineManager m) => m.getRequestHistoryCommand(room.id).isRunning,
2020
);
2121
return Row(
2222
spacing: kSmallPadding,

lib/chat_room/timeline/chat_room_timeline_list.dart

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:yaru/yaru.dart';
77

88
import '../../common/chat_manager.dart';
99
import '../../common/view/build_context_x.dart';
10+
import '../../common/view/common_widgets.dart';
1011
import '../../common/view/theme.dart';
1112
import '../../common/view/ui_constants.dart';
1213
import '../../events/chat_download_manager.dart';
@@ -79,10 +80,13 @@ class _ChatRoomTimelineListState extends State<ChatRoomTimelineList> {
7980
).data ??
8081
[];
8182

82-
watchPropertyValue(
83-
(TimelineManager m) => m.getUpdatingTimeline(widget.timeline.room.id),
83+
final isRequestingHistory = watchValue(
84+
(TimelineManager m) =>
85+
m.getRequestHistoryCommand(widget.timeline.room.id).isRunning,
8486
);
8587

88+
final canRequestHistory = widget.timeline.canRequestHistory;
89+
8690
return Stack(
8791
children: [
8892
NotificationListener<ScrollEndNotification>(
@@ -108,6 +112,11 @@ class _ChatRoomTimelineListState extends State<ChatRoomTimelineList> {
108112
di<TimelineManager>().trySetReadMarker(widget.timeline);
109113
}
110114

115+
final hideInTimeline = event.hideInTimeline(
116+
showAvatarChanges: showAvatarChanges,
117+
showDisplayNameChanges: showDisplayNameChanges,
118+
);
119+
111120
return AutoScrollTag(
112121
index: i,
113122
controller: _controller,
@@ -117,10 +126,7 @@ class _ChatRoomTimelineListState extends State<ChatRoomTimelineList> {
117126
child: Column(
118127
mainAxisSize: MainAxisSize.min,
119128
children: [
120-
if (!event.hideInTimeline(
121-
showAvatarChanges: showAvatarChanges,
122-
showDisplayNameChanges: showDisplayNameChanges,
123-
)) ...[
129+
if (!hideInTimeline) ...[
124130
if (previous != null &&
125131
event.originServerTs.toLocal().day !=
126132
previous.originServerTs.toLocal().day)
@@ -154,7 +160,9 @@ class _ChatRoomTimelineListState extends State<ChatRoomTimelineList> {
154160
),
155161
],
156162

157-
if (event.showAsBubble && !widget.timeline.room.isSpace)
163+
if (!hideInTimeline &&
164+
!event.showAsBadge &&
165+
!widget.timeline.room.isSpace)
158166
i == 0
159167
? ChatEventSeenByIndicator(
160168
key: ValueKey(
@@ -189,22 +197,29 @@ class _ChatRoomTimelineListState extends State<ChatRoomTimelineList> {
189197
),
190198
),
191199
),
192-
if (widget.timeline.canRequestHistory)
200+
if (canRequestHistory)
193201
Positioned(
194202
right: kBigPadding,
195203
top: pinnedEvents.isNotEmpty ? 4 * kBigPadding : kBigPadding,
196204
child: FloatingActionButton.small(
197205
heroTag: 'historyRequestButtonTag',
198206
tooltip: context.l10n.loadMore,
199207
backgroundColor: theme.colorScheme.surface,
200-
child: Icon(
201-
YaruIcons.history,
202-
color: theme.colorScheme.onSurface,
203-
),
204-
onPressed: () => di<TimelineManager>().requestHistory(
205-
widget.timeline,
206-
historyCount: 50,
207-
),
208+
onPressed: isRequestingHistory
209+
? null
210+
: () => di<TimelineManager>()
211+
.getRequestHistoryCommand(widget.timeline.room.id)
212+
.run((
213+
timeline: widget.timeline,
214+
historyCount: 50,
215+
filter: null,
216+
)),
217+
child: isRequestingHistory
218+
? const SizedBox.square(
219+
dimension: 18,
220+
child: Progress(strokeWidth: 2),
221+
)
222+
: Icon(YaruIcons.history, color: theme.colorScheme.onSurface),
208223
),
209224
),
210225
if (_showScrollButton)
@@ -232,10 +247,9 @@ class _ChatRoomTimelineListState extends State<ChatRoomTimelineList> {
232247
if (metrics.atEdge) {
233248
final isAtBottom = metrics.pixels != 0;
234249
if (isAtBottom) {
235-
di<TimelineManager>().requestHistory(
236-
widget.timeline,
237-
historyCount: 150,
238-
);
250+
di<TimelineManager>()
251+
.getRequestHistoryCommand(widget.timeline.room.id)
252+
.run((timeline: widget.timeline, historyCount: 150, filter: null));
239253
} else {
240254
setState(() => _showScrollButton = false);
241255
}
@@ -255,10 +269,9 @@ class _ChatRoomTimelineListState extends State<ChatRoomTimelineList> {
255269
: widget.timeline.events.indexOf(eventInTimeline);
256270

257271
while (index == -1 && retryCount >= 0) {
258-
await di<TimelineManager>().requestHistory(
259-
widget.timeline,
260-
historyCount: 5,
261-
);
272+
await di<TimelineManager>()
273+
.getRequestHistoryCommand(widget.timeline.room.id)
274+
.runAsync((timeline: widget.timeline, historyCount: 5, filter: null));
262275
index = widget.timeline.events.indexOf(event);
263276
retryCount--;
264277
}

lib/chat_room/timeline/chat_thread_dialog.dart

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,20 @@ class _ChatThreadDialogState extends State<ChatThreadDialog> {
6060
@override
6161
Widget build(BuildContext context) {
6262
final room = widget.timeline.room;
63-
watchStream((ChatManager m) => m.getEventStream(room), initialValue: null);
64-
watchStream(
65-
(ChatManager m) => m.getHistoryStream(room),
63+
final fromStream = watchStream(
64+
(ChatManager m) => m.getEventStream(room),
6665
initialValue: null,
66+
preserveState: false,
67+
).data;
68+
watchValue(
69+
(TimelineManager m) => m.getRequestHistoryCommand(room.id).isRunning,
6770
);
6871

69-
watchPropertyValue((TimelineManager m) => m.getTimeline(room.id));
70-
7172
var events = {
72-
...widget.event.aggregatedEvents(
73-
widget.timeline,
74-
RelationshipTypes.thread,
75-
),
73+
...widget.event
74+
.aggregatedEvents(widget.timeline, RelationshipTypes.thread)
75+
.toList()
76+
.reversed,
7677
widget.event,
7778
};
7879
return AlertDialog(
@@ -85,6 +86,7 @@ class _ChatThreadDialogState extends State<ChatThreadDialog> {
8586
width: 500,
8687
height: 600,
8788
child: ListView.builder(
89+
key: ValueKey(fromStream),
8890
reverse: true,
8991
padding: const EdgeInsets.all(kMediumPadding),
9092
itemCount: events.length,

0 commit comments

Comments
 (0)