Skip to content

Commit 6325a09

Browse files
committed
fix: correctly shift enter and enter send, more fade animations + create timeline model
1 parent 502a5e5 commit 6325a09

File tree

10 files changed

+185
-150
lines changed

10 files changed

+185
-150
lines changed

lib/chat/chat_model.dart

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,6 @@ class ChatModel extends SafeChangeNotifier {
163163
Room? get selectedRoom => _selectedRoom;
164164
Future<void> setSelectedRoom(Room? value) async {
165165
_selectedRoom = value;
166-
if (value == null) {
167-
_roomSearchActive = false;
168-
}
169166
notifyListeners();
170167
}
171168

@@ -370,42 +367,4 @@ class ChatModel extends SafeChangeNotifier {
370367
_setProcessingJoinOrLeave(false);
371368
}
372369
}
373-
374-
// TIMELINES
375-
376-
bool _updatingTimeline = false;
377-
bool get updatingTimeline => _updatingTimeline;
378-
void setUpdatingTimeline(bool value) {
379-
if (value == _updatingTimeline) return;
380-
_updatingTimeline = value;
381-
notifyListeners();
382-
}
383-
384-
Future<void> requestHistory(
385-
Timeline timeline, {
386-
int historyCount = Room.defaultHistoryCount,
387-
StateFilter? filter,
388-
bool notify = true,
389-
}) async {
390-
if (notify) {
391-
setUpdatingTimeline(true);
392-
}
393-
if (timeline.isRequestingHistory) {
394-
setUpdatingTimeline(false);
395-
return;
396-
}
397-
await timeline.requestHistory(filter: filter, historyCount: historyCount);
398-
if (notify) {
399-
setUpdatingTimeline(false);
400-
}
401-
}
402-
403-
bool _roomSearchActive = false;
404-
bool get roomSearchActive => _roomSearchActive;
405-
void toggleRoomSearch({bool? value}) {
406-
bool theValue = value ?? !_roomSearchActive;
407-
if (theValue == _roomSearchActive) return;
408-
_roomSearchActive = theValue;
409-
notifyListeners();
410-
}
411370
}

lib/chat/draft_model.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,12 @@ class DraftModel extends SafeChangeNotifier {
7979
}
8080
}
8181

82-
final draft = getDraft(room.id);
83-
if (draft?.isNotEmpty ?? false) {
82+
final draft = '${getDraft(room.id)}';
83+
removeDraft(room.id);
84+
if (draft.isNotEmpty) {
8485
try {
8586
await room.sendTextEvent(
86-
draft!.trim(),
87+
draft.trim(),
8788
inReplyTo: replyEvent,
8889
editEventId: _editEvents[room.id]?.eventId,
8990
);
@@ -96,7 +97,6 @@ class DraftModel extends SafeChangeNotifier {
9697
_sending = false;
9798
_replyEvent = null;
9899
_editEvents[room.id] = null;
99-
removeDraft(room.id);
100100

101101
notifyListeners();
102102
}

lib/chat/timeline_model.dart

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import 'package:matrix/matrix.dart';
2+
import 'package:safe_change_notifier/safe_change_notifier.dart';
3+
4+
class TimelineModel extends SafeChangeNotifier {
5+
// TIMELINES
6+
7+
bool _updatingTimeline = false;
8+
bool get updatingTimeline => _updatingTimeline;
9+
void setUpdatingTimeline(bool value) {
10+
if (value == _updatingTimeline) return;
11+
_updatingTimeline = value;
12+
notifyListeners();
13+
}
14+
15+
Future<void> requestHistory(
16+
Timeline timeline, {
17+
int historyCount = 350,
18+
StateFilter? filter,
19+
bool notify = true,
20+
}) async {
21+
if (notify) {
22+
setUpdatingTimeline(true);
23+
}
24+
if (timeline.isRequestingHistory) {
25+
setUpdatingTimeline(false);
26+
return;
27+
}
28+
await timeline.requestHistory(filter: filter, historyCount: historyCount);
29+
await timeline.setReadMarker();
30+
if (notify) {
31+
setUpdatingTimeline(false);
32+
}
33+
}
34+
35+
bool _timelineSearchActive = false;
36+
bool get timelineSearchActive => _timelineSearchActive;
37+
void toggleTimelineSearch({bool? value}) {
38+
bool theValue = value ?? !_timelineSearchActive;
39+
if (theValue == _timelineSearchActive) return;
40+
_timelineSearchActive = theValue;
41+
notifyListeners();
42+
}
43+
}

lib/chat/view/chat_room/chat_room_info_drawer_topic.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import 'package:matrix/matrix.dart';
44
import 'package:watch_it/watch_it.dart';
55

66
import '../../../common/view/ui_constants.dart';
7-
import '../../chat_model.dart';
7+
import '../../timeline_model.dart';
88

99
class ChatRoomInfoDrawerTopic extends StatelessWidget with WatchItMixin {
1010
const ChatRoomInfoDrawerTopic({
@@ -17,7 +17,7 @@ class ChatRoomInfoDrawerTopic extends StatelessWidget with WatchItMixin {
1717
@override
1818
Widget build(BuildContext context) {
1919
final updatingTimeline =
20-
watchPropertyValue((ChatModel m) => m.updatingTimeline);
20+
watchPropertyValue((TimelineModel m) => m.updatingTimeline);
2121

2222
return SliverToBoxAdapter(
2323
child: Center(

lib/chat/view/chat_room/chat_room_master_tile_subtitle.dart

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,22 @@ class ChatRoomMasterTileSubTitle extends StatelessWidget with WatchItMixin {
2424
initialValue: room.lastEvent,
2525
).data;
2626

27-
return typingUsers.isEmpty
28-
? _LastEvent(
29-
key: ObjectKey(lastEvent),
30-
lastEvent: lastEvent ?? room.lastEvent,
31-
fallbackText:
32-
room.membership == Membership.invite ? room.name : null,
33-
)
34-
: Text(
35-
typingUsers.length > 1
36-
? context.l10n.numUsersTyping(typingUsers.length)
37-
: context.l10n
38-
.userIsTyping(typingUsers.first.displayName ?? ''),
39-
style: context.textTheme.bodyMedium
40-
?.copyWith(color: context.colorScheme.primary),
41-
maxLines: 1,
42-
);
27+
if (typingUsers.isEmpty) {
28+
return _LastEvent(
29+
key: ValueKey('${lastEvent?.eventId}lastevent'),
30+
lastEvent: room.lastEvent,
31+
fallbackText: room.membership == Membership.invite ? room.name : null,
32+
);
33+
}
34+
35+
return Text(
36+
typingUsers.length > 1
37+
? context.l10n.numUsersTyping(typingUsers.length)
38+
: context.l10n.userIsTyping(typingUsers.first.displayName ?? ''),
39+
style: context.textTheme.bodyMedium
40+
?.copyWith(color: context.colorScheme.primary),
41+
maxLines: 1,
42+
);
4343
}
4444
}
4545

@@ -60,21 +60,42 @@ class _LastEvent extends StatefulWidget with WatchItStatefulWidgetMixin {
6060
class _LastEventState extends State<_LastEvent> {
6161
late final Future<String> _future;
6262

63+
static final Map<String, String> _cache = {};
64+
6365
@override
6466
void initState() {
6567
super.initState();
66-
_future = widget.lastEvent
67-
?.calcLocalizedBody(const MatrixDefaultLocalizations()) ??
68-
Future.value(widget.lastEvent?.body ?? '');
68+
_future = widget.lastEvent != null &&
69+
_cache.containsKey(widget.lastEvent!.eventId)
70+
? Future.value(_cache[widget.lastEvent!.eventId]!)
71+
: widget.lastEvent
72+
?.calcLocalizedBody(const MatrixDefaultLocalizations()) ??
73+
Future.value(widget.lastEvent?.body ?? '');
6974
}
7075

7176
@override
7277
Widget build(BuildContext context) {
78+
if (widget.lastEvent != null &&
79+
_cache.containsKey(widget.lastEvent!.eventId)) {
80+
return Text(
81+
_cache[widget.lastEvent!.eventId]!,
82+
maxLines: 1,
83+
);
84+
}
85+
7386
return FutureBuilder(
7487
future: _future,
7588
builder: (context, snapshot) {
89+
if (snapshot.hasData && widget.lastEvent != null) {
90+
_cache[widget.lastEvent!.eventId] = snapshot.data!;
91+
return Text(
92+
snapshot.data!,
93+
maxLines: 1,
94+
);
95+
}
96+
7697
return Text(
77-
snapshot.hasData ? snapshot.data! : (widget.fallbackText ?? ' '),
98+
widget.fallbackText ?? ' ',
7899
maxLines: 1,
79100
);
80101
},

lib/chat/view/chat_room/chat_room_page.dart

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import '../../../common/view/snackbars.dart';
1010
import '../../../common/view/ui_constants.dart';
1111
import '../../../l10n/l10n.dart';
1212
import '../../chat_model.dart';
13+
import '../../timeline_model.dart';
1314
import 'chat_room_default_background.dart';
1415
import 'chat_room_info_drawer.dart';
15-
import 'chat_timeline_list.dart';
16+
import 'chat_room_timeline_list.dart';
1617
import 'input/chat_input.dart';
1718
import 'titlebar/chat_room_title_bar.dart';
1819

@@ -50,7 +51,8 @@ class _ChatRoomPageState extends State<ChatRoomPage> {
5051
final archiveActive = watchPropertyValue((ChatModel m) => m.archiveActive);
5152
final loadingArchive =
5253
watchPropertyValue((ChatModel m) => m.loadingArchive);
53-
final updating = watchPropertyValue((ChatModel m) => m.updatingTimeline);
54+
final updating =
55+
watchPropertyValue((TimelineModel m) => m.updatingTimeline);
5456

5557
registerStreamHandler(
5658
select: (ChatModel m) => m.getLeftRoomStream(widget.room.id),
@@ -103,7 +105,7 @@ class _ChatRoomPageState extends State<ChatRoomPage> {
103105

104106
return Padding(
105107
padding: const EdgeInsets.only(bottom: kMediumPadding),
106-
child: ChatTimelineList(
108+
child: ChatRoomTimelineList(
107109
timeline: snapshot.data!,
108110
room: widget.room,
109111
listKey: _roomListKey,
@@ -112,22 +114,27 @@ class _ChatRoomPageState extends State<ChatRoomPage> {
112114
},
113115
),
114116
),
115-
if (updating)
116-
Positioned(
117-
top: 3 * kBigPadding,
118-
child: FloatingActionButton.small(
119-
backgroundColor: context.colorScheme.isLight
120-
? Colors.white
121-
: Colors.black.scale(lightness: 0.09),
122-
onPressed: () {},
123-
child: const SizedBox.square(
124-
dimension: 20,
125-
child: Progress(
126-
strokeWidth: 2,
117+
Positioned(
118+
top: 3 * kBigPadding,
119+
child: IgnorePointer(
120+
child: AnimatedOpacity(
121+
duration: const Duration(milliseconds: 200),
122+
opacity: updating ? 1 : 0,
123+
child: FloatingActionButton.small(
124+
backgroundColor: context.colorScheme.isLight
125+
? Colors.white
126+
: Colors.black.scale(lightness: 0.09),
127+
onPressed: () {},
128+
child: const SizedBox.square(
129+
dimension: 20,
130+
child: Progress(
131+
strokeWidth: 2,
132+
),
127133
),
128134
),
129135
),
130136
),
137+
),
131138
],
132139
);
133140
}

0 commit comments

Comments
 (0)