mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-11-06 20:19:30 +01:00
Merge branch 'soru/rate-limit-rerender' into 'main'
feat: Rate limit streams so that large accounts have a smoother UI See merge request famedly/fluffychat!464
This commit is contained in:
commit
63ae83b852
@ -9,6 +9,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:vrouter/vrouter.dart';
|
||||
import '../../widgets/matrix.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import '../../utils/stream_extension.dart';
|
||||
|
||||
class ChatListView extends StatelessWidget {
|
||||
final ChatListController controller;
|
||||
@ -161,7 +162,8 @@ class ChatListView extends StatelessWidget {
|
||||
.client
|
||||
.onSync
|
||||
.stream
|
||||
.where((s) => s.hasRoomUpdate),
|
||||
.where((s) => s.hasRoomUpdate)
|
||||
.rateLimit(Duration(seconds: 1)),
|
||||
builder: (context, snapshot) {
|
||||
return FutureBuilder<void>(
|
||||
future: controller.waitForFirstSync(),
|
||||
|
@ -27,6 +27,8 @@ import 'package:scroll_to_index/scroll_to_index.dart';
|
||||
import 'package:swipe_to_action/swipe_to_action.dart';
|
||||
import 'package:vrouter/vrouter.dart';
|
||||
|
||||
import '../../utils/stream_extension.dart';
|
||||
|
||||
class ChatView extends StatelessWidget {
|
||||
final ChatController controller;
|
||||
|
||||
@ -72,7 +74,8 @@ class ChatView extends StatelessWidget {
|
||||
titleSpacing: 0,
|
||||
title: controller.selectedEvents.isEmpty
|
||||
? StreamBuilder(
|
||||
stream: controller.room.onUpdate.stream,
|
||||
stream: controller.room.onUpdate.stream
|
||||
.rateLimit(Duration(milliseconds: 250)),
|
||||
builder: (context, snapshot) => ListTile(
|
||||
leading: Avatar(controller.room.avatar,
|
||||
controller.room.displayname),
|
||||
@ -105,7 +108,8 @@ class ChatView extends StatelessWidget {
|
||||
.stream
|
||||
.where((p) =>
|
||||
p.senderId ==
|
||||
controller.room.directChatMatrixID),
|
||||
controller.room.directChatMatrixID)
|
||||
.rateLimit(Duration(seconds: 1)),
|
||||
builder: (context, snapshot) => Text(
|
||||
controller.room
|
||||
.getLocalizedStatus(context),
|
||||
@ -283,8 +287,10 @@ class ChatView extends StatelessWidget {
|
||||
: Container()
|
||||
: i == 0
|
||||
? StreamBuilder(
|
||||
stream:
|
||||
controller.room.onUpdate.stream,
|
||||
stream: controller
|
||||
.room.onUpdate.stream
|
||||
.rateLimit(Duration(
|
||||
milliseconds: 250)),
|
||||
builder: (_, __) {
|
||||
final seenByText = controller.room
|
||||
.getLocalizedSeenByText(
|
||||
|
46
lib/utils/stream_extension.dart
Normal file
46
lib/utils/stream_extension.dart
Normal file
@ -0,0 +1,46 @@
|
||||
import 'dart:async';
|
||||
|
||||
extension StreamExtension on Stream {
|
||||
/// Returns a new Stream which outputs only `true` for every update of the original
|
||||
/// stream, ratelimited by the Duration t
|
||||
Stream<bool> rateLimit(Duration t) {
|
||||
final controller = StreamController<bool>();
|
||||
Timer timer;
|
||||
var gotMessage = false;
|
||||
// as we call our inline-defined function recursively we need to make sure that the
|
||||
// variable exists prior of creating the function. Silly dart.
|
||||
Function _onMessage;
|
||||
// callback to determine if we should send out an update
|
||||
_onMessage = () {
|
||||
// do nothing if it is already closed
|
||||
if (controller.isClosed) {
|
||||
return;
|
||||
}
|
||||
if (timer == null) {
|
||||
// if we don't have a timer yet, send out the update and start a timer
|
||||
gotMessage = false;
|
||||
controller.add(true);
|
||||
timer = Timer(t, () {
|
||||
// the timer has ended...delete it and, if we got a message, re-run the
|
||||
// method to send out an update!
|
||||
timer = null;
|
||||
if (gotMessage) {
|
||||
_onMessage();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// set that we got a message
|
||||
gotMessage = true;
|
||||
}
|
||||
};
|
||||
final subscription = listen((_) => _onMessage(),
|
||||
onDone: () => controller.close(),
|
||||
onError: (e, s) => controller.addError(e, s));
|
||||
// add proper cleanup to the subscription and the controller, to not memory leak
|
||||
controller.onCancel = () {
|
||||
subscription.cancel();
|
||||
controller.close();
|
||||
};
|
||||
return controller.stream;
|
||||
}
|
||||
}
|
@ -289,7 +289,9 @@ class ChatListItem extends StatelessWidget {
|
||||
curve: Curves.bounceInOut,
|
||||
padding: EdgeInsets.symmetric(horizontal: 7),
|
||||
height: unreadBubbleSize,
|
||||
width: room.notificationCount == 0 && !room.isUnread ? 0 : null,
|
||||
width: room.notificationCount == 0 && !room.isUnread
|
||||
? 0
|
||||
: unreadBubbleSize,
|
||||
decoration: BoxDecoration(
|
||||
color: room.highlightCount > 0
|
||||
? Colors.red
|
||||
|
Loading…
Reference in New Issue
Block a user