mirror of
https://github.com/krille-chan/fluffychat
synced 2024-09-10 13:05:11 +00:00
refactor: Remove unnecessary setState in ChatPage for better performance
This commit is contained in:
parent
a615de889e
commit
63d7bef515
3 changed files with 222 additions and 215 deletions
|
@ -187,8 +187,6 @@ class ChatController extends State<ChatPageWithRoom> {
|
|||
|
||||
final int _loadHistoryCount = 100;
|
||||
|
||||
String inputText = '';
|
||||
|
||||
String pendingText = '';
|
||||
|
||||
bool showEmojiPicker = false;
|
||||
|
@ -260,7 +258,6 @@ class ChatController extends State<ChatPageWithRoom> {
|
|||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
setReadMarker();
|
||||
if (!scrollController.hasClients) return;
|
||||
if (timeline?.allowNewEvent == false ||
|
||||
scrollController.position.pixels > 0 && _scrolledUp == false) {
|
||||
|
@ -285,7 +282,6 @@ class ChatController extends State<ChatPageWithRoom> {
|
|||
final draft = prefs.getString('draft_$roomId');
|
||||
if (draft != null && draft.isNotEmpty) {
|
||||
sendController.text = draft;
|
||||
setState(() => inputText = draft);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -472,7 +468,7 @@ class ChatController extends State<ChatPageWithRoom> {
|
|||
);
|
||||
|
||||
setState(() {
|
||||
inputText = pendingText;
|
||||
sendController.text = pendingText;
|
||||
replyEvent = null;
|
||||
editEvent = null;
|
||||
pendingText = '';
|
||||
|
@ -938,7 +934,7 @@ class ChatController extends State<ChatPageWithRoom> {
|
|||
);
|
||||
});
|
||||
await loadTimelineFuture;
|
||||
setReadMarker(eventId: timeline!.events.first.eventId);
|
||||
setReadMarker();
|
||||
}
|
||||
scrollController.jumpTo(0);
|
||||
}
|
||||
|
@ -1040,7 +1036,7 @@ class ChatController extends State<ChatPageWithRoom> {
|
|||
setState(() {
|
||||
pendingText = sendController.text;
|
||||
editEvent = selectedEvents.first;
|
||||
inputText = sendController.text =
|
||||
sendController.text =
|
||||
editEvent!.getDisplayEvent(timeline!).calcLocalizedBodyFallback(
|
||||
MatrixLocals(L10n.of(context)!),
|
||||
withSenderNamePrefix: false,
|
||||
|
@ -1187,7 +1183,6 @@ class ChatController extends State<ChatPageWithRoom> {
|
|||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('draft_$roomId', text);
|
||||
});
|
||||
setReadMarker();
|
||||
if (text.endsWith(' ') && Matrix.of(context).hasComplexBundles) {
|
||||
final clients = currentRoomBundle;
|
||||
for (final client in clients) {
|
||||
|
@ -1196,7 +1191,6 @@ class ChatController extends State<ChatPageWithRoom> {
|
|||
text.toLowerCase() == '${prefix.toLowerCase()} ') {
|
||||
setSendingClient(client);
|
||||
setState(() {
|
||||
inputText = '';
|
||||
sendController.text = '';
|
||||
});
|
||||
return;
|
||||
|
@ -1222,9 +1216,15 @@ class ChatController extends State<ChatPageWithRoom> {
|
|||
);
|
||||
}
|
||||
}
|
||||
setState(() => inputText = text);
|
||||
if (_inputTextIsEmpty != text.isEmpty) {
|
||||
setState(() {
|
||||
_inputTextIsEmpty = text.isEmpty;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool _inputTextIsEmpty = true;
|
||||
|
||||
bool get isArchived =>
|
||||
{Membership.leave, Membership.ban}.contains(room.membership);
|
||||
|
||||
|
@ -1291,7 +1291,7 @@ class ChatController extends State<ChatPageWithRoom> {
|
|||
|
||||
void cancelReplyEventAction() => setState(() {
|
||||
if (editEvent != null) {
|
||||
inputText = sendController.text = pendingText;
|
||||
sendController.text = pendingText;
|
||||
pendingText = '';
|
||||
}
|
||||
replyEvent = null;
|
||||
|
|
|
@ -105,7 +105,7 @@ class ChatInputRow extends StatelessWidget {
|
|||
duration: FluffyThemes.animationDuration,
|
||||
curve: FluffyThemes.animationCurve,
|
||||
height: 56,
|
||||
width: controller.inputText.isEmpty ? 56 : 0,
|
||||
width: controller.sendController.text.isEmpty ? 56 : 0,
|
||||
alignment: Alignment.center,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: const BoxDecoration(),
|
||||
|
@ -268,7 +268,7 @@ class ChatInputRow extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
if (PlatformInfos.platformCanRecord &&
|
||||
controller.inputText.isEmpty)
|
||||
controller.sendController.text.isEmpty)
|
||||
Container(
|
||||
height: 56,
|
||||
alignment: Alignment.center,
|
||||
|
@ -278,7 +278,8 @@ class ChatInputRow extends StatelessWidget {
|
|||
onPressed: controller.voiceMessageAction,
|
||||
),
|
||||
),
|
||||
if (!PlatformInfos.isMobile || controller.inputText.isNotEmpty)
|
||||
if (!PlatformInfos.isMobile ||
|
||||
controller.sendController.text.isNotEmpty)
|
||||
Container(
|
||||
height: 56,
|
||||
alignment: Alignment.center,
|
||||
|
|
|
@ -149,222 +149,228 @@ class ChatView extends StatelessWidget {
|
|||
child: GestureDetector(
|
||||
onTapDown: (_) => controller.setReadMarker(),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: StreamBuilder(
|
||||
stream: controller.room.onUpdate.stream
|
||||
.rateLimit(const Duration(seconds: 1)),
|
||||
builder: (context, snapshot) => FutureBuilder(
|
||||
future: controller.loadTimelineFuture,
|
||||
builder: (BuildContext context, snapshot) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
actionsIconTheme: IconThemeData(
|
||||
color: controller.selectedEvents.isEmpty
|
||||
? null
|
||||
: Theme.of(context).colorScheme.primary,
|
||||
child: MouseRegion(
|
||||
onEnter: (_) => controller.setReadMarker(),
|
||||
child: StreamBuilder(
|
||||
stream: controller.room.onUpdate.stream
|
||||
.rateLimit(const Duration(seconds: 1)),
|
||||
builder: (context, snapshot) => FutureBuilder(
|
||||
future: controller.loadTimelineFuture,
|
||||
builder: (BuildContext context, snapshot) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
actionsIconTheme: IconThemeData(
|
||||
color: controller.selectedEvents.isEmpty
|
||||
? null
|
||||
: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
leading: controller.selectMode
|
||||
? IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: controller.clearSelectedEvents,
|
||||
tooltip: L10n.of(context)!.close,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
)
|
||||
: UnreadRoomsBadge(
|
||||
filter: (r) => r.id != controller.roomId,
|
||||
badgePosition: BadgePosition.topEnd(end: 8, top: 4),
|
||||
child: const Center(child: BackButton()),
|
||||
),
|
||||
titleSpacing: 0,
|
||||
title: ChatAppBarTitle(controller),
|
||||
actions: _appBarActions(context),
|
||||
),
|
||||
leading: controller.selectMode
|
||||
? IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: controller.clearSelectedEvents,
|
||||
tooltip: L10n.of(context)!.close,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
floatingActionButton: controller.showScrollDownButton &&
|
||||
controller.selectedEvents.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(bottom: 56.0),
|
||||
child: FloatingActionButton(
|
||||
onPressed: controller.scrollDown,
|
||||
heroTag: null,
|
||||
mini: true,
|
||||
child: const Icon(Icons.arrow_downward_outlined),
|
||||
),
|
||||
)
|
||||
: UnreadRoomsBadge(
|
||||
filter: (r) => r.id != controller.roomId,
|
||||
badgePosition: BadgePosition.topEnd(end: 8, top: 4),
|
||||
child: const Center(child: BackButton()),
|
||||
),
|
||||
titleSpacing: 0,
|
||||
title: ChatAppBarTitle(controller),
|
||||
actions: _appBarActions(context),
|
||||
),
|
||||
floatingActionButton: controller.showScrollDownButton &&
|
||||
controller.selectedEvents.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(bottom: 56.0),
|
||||
child: FloatingActionButton(
|
||||
onPressed: controller.scrollDown,
|
||||
heroTag: null,
|
||||
mini: true,
|
||||
child: const Icon(Icons.arrow_downward_outlined),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
body: DropTarget(
|
||||
onDragDone: controller.onDragDone,
|
||||
onDragEntered: controller.onDragEntered,
|
||||
onDragExited: controller.onDragExited,
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
if (Matrix.of(context).wallpaper != null)
|
||||
Image.file(
|
||||
Matrix.of(context).wallpaper!,
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
fit: BoxFit.cover,
|
||||
filterQuality: FilterQuality.medium,
|
||||
),
|
||||
SafeArea(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
TombstoneDisplay(controller),
|
||||
if (scrollUpBannerEventId != null)
|
||||
Material(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.surfaceVariant,
|
||||
shape: Border(
|
||||
bottom: BorderSide(
|
||||
width: 1,
|
||||
color: Theme.of(context).dividerColor,
|
||||
: null,
|
||||
body: DropTarget(
|
||||
onDragDone: controller.onDragDone,
|
||||
onDragEntered: controller.onDragEntered,
|
||||
onDragExited: controller.onDragExited,
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
if (Matrix.of(context).wallpaper != null)
|
||||
Image.file(
|
||||
Matrix.of(context).wallpaper!,
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
fit: BoxFit.cover,
|
||||
filterQuality: FilterQuality.medium,
|
||||
),
|
||||
SafeArea(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
TombstoneDisplay(controller),
|
||||
if (scrollUpBannerEventId != null)
|
||||
Material(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.surfaceVariant,
|
||||
shape: Border(
|
||||
bottom: BorderSide(
|
||||
width: 1,
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
),
|
||||
child: ListTile(
|
||||
leading: IconButton(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant,
|
||||
icon: const Icon(Icons.close),
|
||||
tooltip: L10n.of(context)!.close,
|
||||
onPressed: () {
|
||||
controller
|
||||
.discardScrollUpBannerEventId();
|
||||
controller.setReadMarker();
|
||||
},
|
||||
),
|
||||
title: Text(
|
||||
L10n.of(context)!.jumpToLastReadMessage,
|
||||
),
|
||||
contentPadding:
|
||||
const EdgeInsets.only(left: 8),
|
||||
trailing: TextButton(
|
||||
onPressed: () {
|
||||
controller.scrollToEventId(
|
||||
scrollUpBannerEventId,
|
||||
);
|
||||
controller
|
||||
.discardScrollUpBannerEventId();
|
||||
},
|
||||
child: Text(L10n.of(context)!.jump),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: ListTile(
|
||||
leading: IconButton(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant,
|
||||
icon: const Icon(Icons.close),
|
||||
tooltip: L10n.of(context)!.close,
|
||||
onPressed: () {
|
||||
controller.discardScrollUpBannerEventId();
|
||||
controller.setReadMarker();
|
||||
PinnedEvents(controller),
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: controller.clearSingleSelectedEvent,
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
if (controller.timeline == null) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator
|
||||
.adaptive(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
);
|
||||
}
|
||||
return ChatEventList(
|
||||
controller: controller,
|
||||
);
|
||||
},
|
||||
),
|
||||
title: Text(
|
||||
L10n.of(context)!.jumpToLastReadMessage,
|
||||
),
|
||||
contentPadding:
|
||||
const EdgeInsets.only(left: 8),
|
||||
trailing: TextButton(
|
||||
onPressed: () {
|
||||
controller.scrollToEventId(
|
||||
scrollUpBannerEventId,
|
||||
);
|
||||
controller.discardScrollUpBannerEventId();
|
||||
},
|
||||
child: Text(L10n.of(context)!.jump),
|
||||
),
|
||||
),
|
||||
),
|
||||
PinnedEvents(controller),
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: controller.clearSingleSelectedEvent,
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
if (controller.timeline == null) {
|
||||
return const Center(
|
||||
child:
|
||||
CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return ChatEventList(
|
||||
controller: controller,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
if (controller.room.canSendDefaultMessages &&
|
||||
controller.room.membership == Membership.join)
|
||||
Container(
|
||||
margin: EdgeInsets.only(
|
||||
bottom: bottomSheetPadding,
|
||||
left: bottomSheetPadding,
|
||||
right: bottomSheetPadding,
|
||||
),
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: FluffyThemes.columnWidth * 2.5,
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Material(
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomLeft:
|
||||
Radius.circular(AppConfig.borderRadius),
|
||||
bottomRight:
|
||||
Radius.circular(AppConfig.borderRadius),
|
||||
if (controller.room.canSendDefaultMessages &&
|
||||
controller.room.membership == Membership.join)
|
||||
Container(
|
||||
margin: EdgeInsets.only(
|
||||
bottom: bottomSheetPadding,
|
||||
left: bottomSheetPadding,
|
||||
right: bottomSheetPadding,
|
||||
),
|
||||
elevation: 4,
|
||||
shadowColor: Colors.black.withAlpha(64),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
color: Theme.of(context).brightness ==
|
||||
Brightness.light
|
||||
? Colors.white
|
||||
: Colors.black,
|
||||
child: controller.room.isAbandonedDMRoom ==
|
||||
true
|
||||
? Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
padding:
|
||||
const EdgeInsets.all(16),
|
||||
foregroundColor:
|
||||
Theme.of(context)
|
||||
.colorScheme
|
||||
.error,
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: FluffyThemes.columnWidth * 2.5,
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Material(
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(
|
||||
AppConfig.borderRadius,
|
||||
),
|
||||
bottomRight: Radius.circular(
|
||||
AppConfig.borderRadius,
|
||||
),
|
||||
),
|
||||
elevation: 4,
|
||||
shadowColor: Colors.black.withAlpha(64),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
color: Theme.of(context).brightness ==
|
||||
Brightness.light
|
||||
? Colors.white
|
||||
: Colors.black,
|
||||
child: controller.room.isAbandonedDMRoom ==
|
||||
true
|
||||
? Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
padding:
|
||||
const EdgeInsets.all(16),
|
||||
foregroundColor:
|
||||
Theme.of(context)
|
||||
.colorScheme
|
||||
.error,
|
||||
),
|
||||
icon: const Icon(
|
||||
Icons.archive_outlined,
|
||||
),
|
||||
onPressed: controller.leaveChat,
|
||||
label: Text(
|
||||
L10n.of(context)!.leave,
|
||||
),
|
||||
),
|
||||
icon: const Icon(
|
||||
Icons.archive_outlined,
|
||||
TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
padding:
|
||||
const EdgeInsets.all(16),
|
||||
),
|
||||
icon: const Icon(
|
||||
Icons.forum_outlined,
|
||||
),
|
||||
onPressed:
|
||||
controller.recreateChat,
|
||||
label: Text(
|
||||
L10n.of(context)!.reopenChat,
|
||||
),
|
||||
),
|
||||
onPressed: controller.leaveChat,
|
||||
label: Text(
|
||||
L10n.of(context)!.leave,
|
||||
),
|
||||
),
|
||||
TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
padding:
|
||||
const EdgeInsets.all(16),
|
||||
),
|
||||
icon: const Icon(
|
||||
Icons.forum_outlined,
|
||||
),
|
||||
onPressed:
|
||||
controller.recreateChat,
|
||||
label: Text(
|
||||
L10n.of(context)!.reopenChat,
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const ConnectionStatusHeader(),
|
||||
ReactionsPicker(controller),
|
||||
ReplyDisplay(controller),
|
||||
ChatInputRow(controller),
|
||||
ChatEmojiPicker(controller),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const ConnectionStatusHeader(),
|
||||
ReactionsPicker(controller),
|
||||
ReplyDisplay(controller),
|
||||
ChatInputRow(controller),
|
||||
ChatEmojiPicker(controller),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (controller.dragging)
|
||||
Container(
|
||||
color: Theme.of(context)
|
||||
.scaffoldBackgroundColor
|
||||
.withOpacity(0.9),
|
||||
alignment: Alignment.center,
|
||||
child: const Icon(
|
||||
Icons.upload_outlined,
|
||||
size: 100,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
if (controller.dragging)
|
||||
Container(
|
||||
color: Theme.of(context)
|
||||
.scaffoldBackgroundColor
|
||||
.withOpacity(0.9),
|
||||
alignment: Alignment.center,
|
||||
child: const Icon(
|
||||
Icons.upload_outlined,
|
||||
size: 100,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
Loading…
Reference in a new issue