refactor: Chat list body code

This commit is contained in:
Christian Pauly 2022-09-10 13:32:46 +02:00
parent a4ee523849
commit 518c688c58

View File

@ -1,5 +1,3 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:animations/animations.dart'; import 'package:animations/animations.dart';
@ -18,49 +16,48 @@ import '../../utils/stream_extension.dart';
import '../../widgets/connection_status_header.dart'; import '../../widgets/connection_status_header.dart';
import '../../widgets/matrix.dart'; import '../../widgets/matrix.dart';
class ChatListViewBody extends StatefulWidget { class ChatListViewBody extends StatelessWidget {
final ChatListController controller; final ChatListController controller;
const ChatListViewBody(this.controller, {Key? key}) : super(key: key); const ChatListViewBody(this.controller, {Key? key}) : super(key: key);
@override
State<ChatListViewBody> createState() => _ChatListViewBodyState();
}
class _ChatListViewBodyState extends State<ChatListViewBody> {
// the matrix sync stream
late StreamSubscription _subscription;
@override
void initState() {
_subscription = Matrix.of(context)
.client
.onSync
.stream
.where((s) => s.hasRoomUpdate)
.rateLimit(const Duration(seconds: 1))
.listen((d) => setState(() {}));
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final roomSearchResult = widget.controller.roomSearchResult; final roomSearchResult = controller.roomSearchResult;
final userSearchResult = widget.controller.userSearchResult; final userSearchResult = controller.userSearchResult;
Widget child; final client = Matrix.of(context).client;
if (widget.controller.waitForFirstSync &&
Matrix.of(context).client.prevBatch != null &&
widget.controller.activeFilter != ActiveFilter.spaces) {
final rooms = widget.controller.filteredRooms;
return PageTransitionSwitcher(
transitionBuilder: (
Widget child,
Animation<double> primaryAnimation,
Animation<double> secondaryAnimation,
) {
return SharedAxisTransition(
animation: primaryAnimation,
secondaryAnimation: secondaryAnimation,
transitionType: SharedAxisTransitionType.vertical,
fillColor: Theme.of(context).scaffoldBackgroundColor,
child: child,
);
},
child: StreamBuilder(
stream: client.onSync.stream
.where((s) => s.hasRoomUpdate)
.rateLimit(const Duration(seconds: 1)),
builder: (context, _) {
if (controller.waitForFirstSync &&
client.prevBatch != null &&
controller.activeFilter != ActiveFilter.spaces) {
final rooms = controller.filteredRooms;
final displayStoriesHeader = { final displayStoriesHeader = {
ActiveFilter.allChats, ActiveFilter.allChats,
ActiveFilter.messages, ActiveFilter.messages,
}.contains(widget.controller.activeFilter); }.contains(controller.activeFilter);
child = ListView.builder( return ListView.builder(
key: ValueKey(Matrix.of(context).client.userID.toString() + key: ValueKey(client.userID.toString() +
widget.controller.activeFilter.toString()), controller.activeFilter.toString()),
controller: widget.controller.scrollController, controller: controller.scrollController,
// add +1 space below in order to properly scroll below the spaces bar // add +1 space below in order to properly scroll below the spaces bar
itemCount: rooms.length + 1, itemCount: rooms.length + 1,
itemBuilder: (BuildContext context, int i) { itemBuilder: (BuildContext context, int i) {
@ -90,8 +87,8 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
onPressed: () => showModalBottomSheet( onPressed: () => showModalBottomSheet(
context: context, context: context,
builder: (c) => PublicRoomBottomSheet( builder: (c) => PublicRoomBottomSheet(
roomAlias: roomAlias: roomSearchResult
roomSearchResult.chunk[i].canonicalAlias ?? .chunk[i].canonicalAlias ??
roomSearchResult.chunk[i].roomId, roomSearchResult.chunk[i].roomId,
outerContext: context, outerContext: context,
chunk: roomSearchResult.chunk[i], chunk: roomSearchResult.chunk[i],
@ -115,8 +112,10 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: userSearchResult.results.length, itemCount: userSearchResult.results.length,
itemBuilder: (context, i) => _SearchItem( itemBuilder: (context, i) => _SearchItem(
title: userSearchResult.results[i].displayName ?? title:
userSearchResult.results[i].userId.localpart ?? userSearchResult.results[i].displayName ??
userSearchResult
.results[i].userId.localpart ??
L10n.of(context)!.unknownDevice, L10n.of(context)!.unknownDevice,
avatar: userSearchResult.results[i].avatarUrl, avatar: userSearchResult.results[i].avatarUrl,
onPressed: () => showModalBottomSheet( onPressed: () => showModalBottomSheet(
@ -130,18 +129,18 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
), ),
), ),
], ],
if (widget.controller.isSearchMode) if (controller.isSearchMode)
SearchTitle( SearchTitle(
title: L10n.of(context)!.stories, title: L10n.of(context)!.stories,
icon: const Icon(Icons.camera_alt_outlined), icon: const Icon(Icons.camera_alt_outlined),
), ),
if (displayStoriesHeader) if (displayStoriesHeader)
StoriesHeader( StoriesHeader(
filter: widget.controller.searchController.text, filter: controller.searchController.text,
), ),
const ConnectionStatusHeader(), const ConnectionStatusHeader(),
AnimatedContainer( AnimatedContainer(
height: widget.controller.isTorBrowser ? 64 : 0, height: controller.isTorBrowser ? 64 : 0,
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 300),
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
curve: Curves.bounceInOut, curve: Curves.bounceInOut,
@ -151,18 +150,20 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
child: ListTile( child: ListTile(
leading: const Icon(Icons.vpn_key), leading: const Icon(Icons.vpn_key),
title: Text(L10n.of(context)!.dehydrateTor), title: Text(L10n.of(context)!.dehydrateTor),
subtitle: Text(L10n.of(context)!.dehydrateTorLong), subtitle:
trailing: const Icon(Icons.chevron_right_outlined), Text(L10n.of(context)!.dehydrateTorLong),
onTap: widget.controller.dehydrate, trailing:
const Icon(Icons.chevron_right_outlined),
onTap: controller.dehydrate,
), ),
), ),
), ),
if (widget.controller.isSearchMode) if (controller.isSearchMode)
SearchTitle( SearchTitle(
title: L10n.of(context)!.chats, title: L10n.of(context)!.chats,
icon: const Icon(Icons.chat_outlined), icon: const Icon(Icons.chat_outlined),
), ),
if (rooms.isEmpty && !widget.controller.isSearchMode) if (rooms.isEmpty && !controller.isSearchMode)
Column( Column(
key: const ValueKey(null), key: const ValueKey(null),
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -191,33 +192,34 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
} }
i--; i--;
if (!rooms[i].displayname.toLowerCase().contains( if (!rooms[i].displayname.toLowerCase().contains(
widget.controller.searchController.text.toLowerCase())) { controller.searchController.text.toLowerCase())) {
return Container(); return Container();
} }
return ChatListItem( return ChatListItem(
rooms[i], rooms[i],
selected: widget.controller.selectedRoomIds.contains(rooms[i].id), selected: controller.selectedRoomIds.contains(rooms[i].id),
onTap: widget.controller.selectMode == SelectMode.select onTap: controller.selectMode == SelectMode.select
? () => widget.controller.toggleSelection(rooms[i].id) ? () => controller.toggleSelection(rooms[i].id)
: null, : null,
onLongPress: () => widget.controller.toggleSelection(rooms[i].id), onLongPress: () => controller.toggleSelection(rooms[i].id),
activeChat: widget.controller.activeChat == rooms[i].id, activeChat: controller.activeChat == rooms[i].id,
); );
}, },
); );
} else if (widget.controller.activeFilter == ActiveFilter.spaces) { }
child = SpaceView( if (controller.activeFilter == ActiveFilter.spaces) {
widget.controller, return SpaceView(
scrollController: widget.controller.scrollController, controller,
key: Key(widget.controller.activeSpaceId ?? 'Spaces'), scrollController: controller.scrollController,
key: Key(controller.activeSpaceId ?? 'Spaces'),
); );
} else { }
const dummyChatCount = 5; const dummyChatCount = 5;
final titleColor = final titleColor =
Theme.of(context).textTheme.bodyText1!.color!.withAlpha(100); Theme.of(context).textTheme.bodyText1!.color!.withAlpha(100);
final subtitleColor = final subtitleColor =
Theme.of(context).textTheme.bodyText1!.color!.withAlpha(50); Theme.of(context).textTheme.bodyText1!.color!.withAlpha(50);
child = ListView.builder( return ListView.builder(
key: const Key('dummychats'), key: const Key('dummychats'),
itemCount: dummyChatCount, itemCount: dummyChatCount,
itemBuilder: (context, i) => Opacity( itemBuilder: (context, i) => Opacity(
@ -272,35 +274,8 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
), ),
), ),
); );
} }),
return PageTransitionSwitcher(
transitionBuilder: (
Widget child,
Animation<double> primaryAnimation,
Animation<double> secondaryAnimation,
) {
return SharedAxisTransition(
animation: primaryAnimation,
secondaryAnimation: secondaryAnimation,
transitionType: SharedAxisTransitionType.vertical,
fillColor: Theme.of(context).scaffoldBackgroundColor,
child: child,
); );
},
child: child,
);
}
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
@override
void didUpdateWidget(covariant ChatListViewBody oldWidget) {
setState(() {});
super.didUpdateWidget(oldWidget);
} }
} }