mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-11-07 04:29:29 +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 'package:vrouter/vrouter.dart';
|
||||||
import '../../widgets/matrix.dart';
|
import '../../widgets/matrix.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
import '../../utils/stream_extension.dart';
|
||||||
|
|
||||||
class ChatListView extends StatelessWidget {
|
class ChatListView extends StatelessWidget {
|
||||||
final ChatListController controller;
|
final ChatListController controller;
|
||||||
@ -161,7 +162,8 @@ class ChatListView extends StatelessWidget {
|
|||||||
.client
|
.client
|
||||||
.onSync
|
.onSync
|
||||||
.stream
|
.stream
|
||||||
.where((s) => s.hasRoomUpdate),
|
.where((s) => s.hasRoomUpdate)
|
||||||
|
.rateLimit(Duration(seconds: 1)),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
return FutureBuilder<void>(
|
return FutureBuilder<void>(
|
||||||
future: controller.waitForFirstSync(),
|
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:swipe_to_action/swipe_to_action.dart';
|
||||||
import 'package:vrouter/vrouter.dart';
|
import 'package:vrouter/vrouter.dart';
|
||||||
|
|
||||||
|
import '../../utils/stream_extension.dart';
|
||||||
|
|
||||||
class ChatView extends StatelessWidget {
|
class ChatView extends StatelessWidget {
|
||||||
final ChatController controller;
|
final ChatController controller;
|
||||||
|
|
||||||
@ -72,7 +74,8 @@ class ChatView extends StatelessWidget {
|
|||||||
titleSpacing: 0,
|
titleSpacing: 0,
|
||||||
title: controller.selectedEvents.isEmpty
|
title: controller.selectedEvents.isEmpty
|
||||||
? StreamBuilder(
|
? StreamBuilder(
|
||||||
stream: controller.room.onUpdate.stream,
|
stream: controller.room.onUpdate.stream
|
||||||
|
.rateLimit(Duration(milliseconds: 250)),
|
||||||
builder: (context, snapshot) => ListTile(
|
builder: (context, snapshot) => ListTile(
|
||||||
leading: Avatar(controller.room.avatar,
|
leading: Avatar(controller.room.avatar,
|
||||||
controller.room.displayname),
|
controller.room.displayname),
|
||||||
@ -105,7 +108,8 @@ class ChatView extends StatelessWidget {
|
|||||||
.stream
|
.stream
|
||||||
.where((p) =>
|
.where((p) =>
|
||||||
p.senderId ==
|
p.senderId ==
|
||||||
controller.room.directChatMatrixID),
|
controller.room.directChatMatrixID)
|
||||||
|
.rateLimit(Duration(seconds: 1)),
|
||||||
builder: (context, snapshot) => Text(
|
builder: (context, snapshot) => Text(
|
||||||
controller.room
|
controller.room
|
||||||
.getLocalizedStatus(context),
|
.getLocalizedStatus(context),
|
||||||
@ -283,8 +287,10 @@ class ChatView extends StatelessWidget {
|
|||||||
: Container()
|
: Container()
|
||||||
: i == 0
|
: i == 0
|
||||||
? StreamBuilder(
|
? StreamBuilder(
|
||||||
stream:
|
stream: controller
|
||||||
controller.room.onUpdate.stream,
|
.room.onUpdate.stream
|
||||||
|
.rateLimit(Duration(
|
||||||
|
milliseconds: 250)),
|
||||||
builder: (_, __) {
|
builder: (_, __) {
|
||||||
final seenByText = controller.room
|
final seenByText = controller.room
|
||||||
.getLocalizedSeenByText(
|
.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,
|
curve: Curves.bounceInOut,
|
||||||
padding: EdgeInsets.symmetric(horizontal: 7),
|
padding: EdgeInsets.symmetric(horizontal: 7),
|
||||||
height: unreadBubbleSize,
|
height: unreadBubbleSize,
|
||||||
width: room.notificationCount == 0 && !room.isUnread ? 0 : null,
|
width: room.notificationCount == 0 && !room.isUnread
|
||||||
|
? 0
|
||||||
|
: unreadBubbleSize,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: room.highlightCount > 0
|
color: room.highlightCount > 0
|
||||||
? Colors.red
|
? Colors.red
|
||||||
|
Loading…
Reference in New Issue
Block a user