refactor: Enhance logic when to mark room as read

pull/920/head
krille-chan 1 year ago
parent 03511a1e8d
commit 0cf6a1d74a
No known key found for this signature in database

@ -252,6 +252,7 @@ class ChatController extends State<ChatPageWithRoom>
setState(() => _scrolledUp = true);
} else if (scrollController.position.pixels <= 0 && _scrolledUp == true) {
setState(() => _scrolledUp = false);
setReadMarker();
}
if (scrollController.position.pixels == 0 ||
@ -275,6 +276,7 @@ class ChatController extends State<ChatPageWithRoom>
_loadDraft();
super.initState();
sendingClient = Matrix.of(context).client;
WidgetsBinding.instance.addObserver(this);
_tryLoadTimeline();
}
@ -286,7 +288,6 @@ class ChatController extends State<ChatPageWithRoom>
if (fullyRead.isEmpty) return;
if (timeline!.events.any((event) => event.eventId == fullyRead)) {
Logs().v('Scroll up to visible event', fullyRead);
setReadMarker();
return;
}
if (!mounted) return;
@ -317,6 +318,11 @@ class ChatController extends State<ChatPageWithRoom>
int? animateInEventIndex;
void onInsert(int i) {
if (timeline?.events[i].status == EventStatus.synced) {
final index = timeline!.events.firstIndexWhereNotError;
if (i == index) setReadMarker(eventId: timeline?.events[i].eventId);
}
// setState will be called by updateView() anyway
animateInEventIndex = i;
}
@ -350,6 +356,7 @@ class ChatController extends State<ChatPageWithRoom>
}
timeline!.requestKeys(onlineKeyBackupOnly: false);
if (room.markedUnread) room.markUnread(false);
setReadMarker();
// when the scroll controller is attached we want to scroll to an event id, if specified
// and update the scroll controller...which will trigger a request history, if the
@ -371,7 +378,6 @@ class ChatController extends State<ChatPageWithRoom>
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state != AppLifecycleState.resumed) return;
if (!_scrolledUp) return;
setReadMarker();
}
@ -379,13 +385,19 @@ class ChatController extends State<ChatPageWithRoom>
void setReadMarker({String? eventId}) {
if (_setReadMarkerFuture != null) return;
if (_scrolledUp) return;
if (scrollUpBannerEventId != null) return;
if (eventId == null &&
!room.hasNewMessages &&
room.notificationCount == 0) {
return;
}
if (!Matrix.of(context).webHasFocus) return;
// Do not send read markers when app is not in foreground
if (!Matrix.of(context).webHasFocus ||
WidgetsBinding.instance.lifecycleState != AppLifecycleState.resumed) {
return;
}
final timeline = this.timeline;
if (timeline == null || timeline.events.isEmpty) return;
@ -932,7 +944,6 @@ class ChatController extends State<ChatPageWithRoom>
);
});
await loadTimelineFuture;
setReadMarker();
}
scrollController.jumpTo(0);
}
@ -1174,7 +1185,6 @@ class ChatController extends State<ChatPageWithRoom>
void onInputBarChanged(String text) {
if (_inputTextIsEmpty != text.isEmpty) {
setReadMarker();
setState(() {
_inputTextIsEmpty = text.isEmpty;
});
@ -1300,3 +1310,12 @@ class ChatController extends State<ChatPageWithRoom>
}
enum EmojiPickerType { reaction, keyboard }
extension on List<Event> {
int get firstIndexWhereNotError {
if (isEmpty) return 0;
final index = indexWhere((event) => !event.status.isError);
if (index == -1) return length;
return index;
}
}

@ -150,11 +150,6 @@ class ChatView extends StatelessWidget {
controller.emojiPickerAction();
}
},
child: GestureDetector(
onTapDown: (_) => controller.setReadMarker(),
behavior: HitTestBehavior.opaque,
child: MouseRegion(
onEnter: (_) => controller.setReadMarker(),
child: StreamBuilder(
stream: controller.room.onUpdate.stream
.rateLimit(const Duration(seconds: 1)),
@ -220,9 +215,8 @@ class ChatView extends StatelessWidget {
TombstoneDisplay(controller),
if (scrollUpBannerEventId != null)
Material(
color: Theme.of(context)
.colorScheme
.surfaceVariant,
color:
Theme.of(context).colorScheme.surfaceVariant,
shape: Border(
bottom: BorderSide(
width: 1,
@ -237,23 +231,20 @@ class ChatView extends StatelessWidget {
icon: const Icon(Icons.close),
tooltip: L10n.of(context)!.close,
onPressed: () {
controller
.discardScrollUpBannerEventId();
controller.discardScrollUpBannerEventId();
controller.setReadMarker();
},
),
title: Text(
L10n.of(context)!.jumpToLastReadMessage,
),
contentPadding:
const EdgeInsets.only(left: 8),
contentPadding: const EdgeInsets.only(left: 8),
trailing: TextButton(
onPressed: () {
controller.scrollToEventId(
scrollUpBannerEventId,
);
controller
.discardScrollUpBannerEventId();
controller.discardScrollUpBannerEventId();
},
child: Text(L10n.of(context)!.jump),
),
@ -267,8 +258,7 @@ class ChatView extends StatelessWidget {
builder: (context) {
if (controller.timeline == null) {
return const Center(
child: CircularProgressIndicator
.adaptive(
child: CircularProgressIndicator.adaptive(
strokeWidth: 2,
),
);
@ -308,8 +298,7 @@ class ChatView extends StatelessWidget {
Brightness.light
? Colors.white
: Colors.black,
child: controller.room.isAbandonedDMRoom ==
true
child: controller.room.isAbandonedDMRoom == true
? Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
@ -319,8 +308,7 @@ class ChatView extends StatelessWidget {
padding: const EdgeInsets.all(
16,
),
foregroundColor:
Theme.of(context)
foregroundColor: Theme.of(context)
.colorScheme
.error,
),
@ -341,8 +329,7 @@ class ChatView extends StatelessWidget {
icon: const Icon(
Icons.forum_outlined,
),
onPressed:
controller.recreateChat,
onPressed: controller.recreateChat,
label: Text(
L10n.of(context)!.reopenChat,
),
@ -382,8 +369,6 @@ class ChatView extends StatelessWidget {
},
),
),
),
),
);
}
}

Loading…
Cancel
Save