fix: re-enable chat list animation

Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
This commit is contained in:
TheOneWithTheBraid 2022-12-25 18:33:06 +01:00
parent 7cdeb98671
commit 478634cb99

View File

@ -17,6 +17,7 @@ import '../../widgets/connection_status_header.dart';
import '../../widgets/matrix.dart'; import '../../widgets/matrix.dart';
class ChatListViewBody extends StatelessWidget { class ChatListViewBody extends StatelessWidget {
static final _transitionSwitcherKey = GlobalKey();
final ChatListController controller; final ChatListController controller;
const ChatListViewBody(this.controller, {Key? key}) : super(key: key); const ChatListViewBody(this.controller, {Key? key}) : super(key: key);
@ -28,6 +29,7 @@ class ChatListViewBody extends StatelessWidget {
final client = Matrix.of(context).client; final client = Matrix.of(context).client;
return PageTransitionSwitcher( return PageTransitionSwitcher(
key: _transitionSwitcherKey,
transitionBuilder: ( transitionBuilder: (
Widget child, Widget child,
Animation<double> primaryAnimation, Animation<double> primaryAnimation,
@ -41,237 +43,244 @@ class ChatListViewBody extends StatelessWidget {
child: child, child: child,
); );
}, },
child: Builder(builder: (context) { child: Builder(
if (controller.activeFilter == ActiveFilter.spaces && key: ValueKey(
!controller.isSearchMode) { controller.activeFilter != ActiveFilter.spaces
return SpaceView( ? controller.activeFilter
controller, : controller.activeSpaceId ?? controller.activeFilter,
scrollController: controller.scrollController, ),
key: Key(controller.activeSpaceId ?? 'Spaces'), builder: (context) {
); if (controller.activeFilter == ActiveFilter.spaces &&
} !controller.isSearchMode) {
if (controller.waitForFirstSync && client.prevBatch != null) { return SpaceView(
final rooms = controller.filteredRooms; controller,
final displayStoriesHeader = { scrollController: controller.scrollController,
ActiveFilter.allChats, );
ActiveFilter.messages, }
}.contains(controller.activeFilter); if (controller.waitForFirstSync && client.prevBatch != null) {
return ListView.builder( final rooms = controller.filteredRooms;
controller: controller.scrollController, final displayStoriesHeader = {
// add +1 space below in order to properly scroll below the spaces bar ActiveFilter.allChats,
itemCount: rooms.length + 1, ActiveFilter.messages,
itemBuilder: (BuildContext context, int i) { }.contains(controller.activeFilter);
if (i == 0) { return ListView.builder(
return Column( controller: controller.scrollController,
mainAxisSize: MainAxisSize.min, // add +1 space below in order to properly scroll below the spaces bar
children: [ itemCount: rooms.length + 1,
if (roomSearchResult != null) ...[ itemBuilder: (BuildContext context, int i) {
SearchTitle( if (i == 0) {
title: L10n.of(context)!.publicRooms, return Column(
icon: const Icon(Icons.explore_outlined), mainAxisSize: MainAxisSize.min,
), children: [
AnimatedContainer( if (roomSearchResult != null) ...[
height: roomSearchResult.chunk.isEmpty ? 0 : 106, SearchTitle(
duration: const Duration(milliseconds: 250), title: L10n.of(context)!.publicRooms,
clipBehavior: Clip.hardEdge, icon: const Icon(Icons.explore_outlined),
decoration: const BoxDecoration(), ),
child: ListView.builder( AnimatedContainer(
scrollDirection: Axis.horizontal, height: roomSearchResult.chunk.isEmpty ? 0 : 106,
itemCount: roomSearchResult.chunk.length, duration: const Duration(milliseconds: 250),
itemBuilder: (context, i) => _SearchItem( clipBehavior: Clip.hardEdge,
title: roomSearchResult.chunk[i].name ?? decoration: const BoxDecoration(),
roomSearchResult child: ListView.builder(
.chunk[i].canonicalAlias?.localpart ?? scrollDirection: Axis.horizontal,
L10n.of(context)!.group, itemCount: roomSearchResult.chunk.length,
avatar: roomSearchResult.chunk[i].avatarUrl, itemBuilder: (context, i) => _SearchItem(
onPressed: () => showModalBottomSheet( title: roomSearchResult.chunk[i].name ??
context: context, roomSearchResult
builder: (c) => PublicRoomBottomSheet( .chunk[i].canonicalAlias?.localpart ??
roomAlias: L10n.of(context)!.group,
roomSearchResult.chunk[i].canonicalAlias ?? avatar: roomSearchResult.chunk[i].avatarUrl,
roomSearchResult.chunk[i].roomId, onPressed: () => showModalBottomSheet(
outerContext: context, context: context,
chunk: roomSearchResult.chunk[i], builder: (c) => PublicRoomBottomSheet(
roomAlias: roomSearchResult
.chunk[i].canonicalAlias ??
roomSearchResult.chunk[i].roomId,
outerContext: context,
chunk: roomSearchResult.chunk[i],
),
), ),
), ),
), ),
), ),
), ],
], if (userSearchResult != null) ...[
if (userSearchResult != null) ...[ SearchTitle(
SearchTitle( title: L10n.of(context)!.users,
title: L10n.of(context)!.users, icon: const Icon(Icons.group_outlined),
icon: const Icon(Icons.group_outlined), ),
), AnimatedContainer(
AnimatedContainer( height: userSearchResult.results.isEmpty ? 0 : 106,
height: userSearchResult.results.isEmpty ? 0 : 106, duration: const Duration(milliseconds: 250),
duration: const Duration(milliseconds: 250), clipBehavior: Clip.hardEdge,
clipBehavior: Clip.hardEdge, decoration: const BoxDecoration(),
decoration: const BoxDecoration(), child: ListView.builder(
child: ListView.builder( 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].displayName ?? userSearchResult
userSearchResult.results[i].userId.localpart ?? .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(
context: context, context: context,
builder: (c) => ProfileBottomSheet( builder: (c) => ProfileBottomSheet(
userId: userSearchResult.results[i].userId, userId: userSearchResult.results[i].userId,
outerContext: context, outerContext: context,
),
), ),
), ),
), ),
), ),
],
if (controller.isSearchMode)
SearchTitle(
title: L10n.of(context)!.stories,
icon: const Icon(Icons.camera_alt_outlined),
),
if (displayStoriesHeader)
StoriesHeader(
key: const Key('stories_header'),
filter: controller.searchController.text,
),
const ConnectionStatusHeader(),
AnimatedContainer(
height: controller.isTorBrowser ? 64 : 0,
duration: const Duration(milliseconds: 300),
clipBehavior: Clip.hardEdge,
curve: Curves.bounceInOut,
decoration: const BoxDecoration(),
child: Material(
color: Theme.of(context).colorScheme.surface,
child: ListTile(
leading: const Icon(Icons.vpn_key),
title: Text(L10n.of(context)!.dehydrateTor),
subtitle: Text(L10n.of(context)!.dehydrateTorLong),
trailing: const Icon(Icons.chevron_right_outlined),
onTap: controller.dehydrate,
),
),
), ),
if (controller.isSearchMode)
SearchTitle(
title: L10n.of(context)!.chats,
icon: const Icon(Icons.chat_outlined),
),
if (rooms.isEmpty && !controller.isSearchMode)
Padding(
padding: const EdgeInsets.all(32.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 32),
Image.asset(
'assets/start_chat.png',
),
Divider(
height: 1,
color:
Theme.of(context).colorScheme.onBackground,
),
const SizedBox(height: 32),
FloatingActionButton.extended(
backgroundColor:
Theme.of(context).colorScheme.primary,
foregroundColor:
Theme.of(context).colorScheme.onPrimary,
icon: const Icon(Icons.edit_outlined),
onPressed: () =>
VRouter.of(context).to('/newprivatechat'),
label: Text(L10n.of(context)!.startFirstChat),
),
],
),
),
], ],
if (controller.isSearchMode) );
SearchTitle( }
title: L10n.of(context)!.stories, i--;
icon: const Icon(Icons.camera_alt_outlined), if (!rooms[i]
), .displayname
if (displayStoriesHeader) .toLowerCase()
StoriesHeader( .contains(controller.searchController.text.toLowerCase())) {
key: const Key('stories_header'), return Container();
filter: controller.searchController.text, }
), return ChatListItem(
const ConnectionStatusHeader(), rooms[i],
AnimatedContainer( key: Key('chat_list_item_${rooms[i].id}'),
height: controller.isTorBrowser ? 64 : 0, selected: controller.selectedRoomIds.contains(rooms[i].id),
duration: const Duration(milliseconds: 300), onTap: controller.selectMode == SelectMode.select
clipBehavior: Clip.hardEdge, ? () => controller.toggleSelection(rooms[i].id)
curve: Curves.bounceInOut, : null,
decoration: const BoxDecoration(), onLongPress: () => controller.toggleSelection(rooms[i].id),
child: Material( activeChat: controller.activeChat == rooms[i].id,
color: Theme.of(context).colorScheme.surface,
child: ListTile(
leading: const Icon(Icons.vpn_key),
title: Text(L10n.of(context)!.dehydrateTor),
subtitle: Text(L10n.of(context)!.dehydrateTorLong),
trailing: const Icon(Icons.chevron_right_outlined),
onTap: controller.dehydrate,
),
),
),
if (controller.isSearchMode)
SearchTitle(
title: L10n.of(context)!.chats,
icon: const Icon(Icons.chat_outlined),
),
if (rooms.isEmpty && !controller.isSearchMode)
Padding(
padding: const EdgeInsets.all(32.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 32),
Image.asset(
'assets/start_chat.png',
),
Divider(
height: 1,
color: Theme.of(context).colorScheme.onBackground,
),
const SizedBox(height: 32),
FloatingActionButton.extended(
backgroundColor:
Theme.of(context).colorScheme.primary,
foregroundColor:
Theme.of(context).colorScheme.onPrimary,
icon: const Icon(Icons.edit_outlined),
onPressed: () =>
VRouter.of(context).to('/newprivatechat'),
label: Text(L10n.of(context)!.startFirstChat),
),
],
),
),
],
); );
} },
i--; );
if (!rooms[i] }
.displayname const dummyChatCount = 5;
.toLowerCase() final titleColor =
.contains(controller.searchController.text.toLowerCase())) { Theme.of(context).textTheme.bodyText1!.color!.withAlpha(100);
return Container(); final subtitleColor =
} Theme.of(context).textTheme.bodyText1!.color!.withAlpha(50);
return ChatListItem( return ListView.builder(
rooms[i], itemCount: dummyChatCount,
key: Key('chat_list_item_${rooms[i].id}'), itemBuilder: (context, i) => Opacity(
selected: controller.selectedRoomIds.contains(rooms[i].id), opacity: (dummyChatCount - i) / dummyChatCount,
onTap: controller.selectMode == SelectMode.select child: ListTile(
? () => controller.toggleSelection(rooms[i].id) leading: CircleAvatar(
: null, backgroundColor: titleColor,
onLongPress: () => controller.toggleSelection(rooms[i].id), child: CircularProgressIndicator(
activeChat: controller.activeChat == rooms[i].id, strokeWidth: 1,
); color: Theme.of(context).textTheme.bodyText1!.color,
}, ),
);
}
const dummyChatCount = 5;
final titleColor =
Theme.of(context).textTheme.bodyText1!.color!.withAlpha(100);
final subtitleColor =
Theme.of(context).textTheme.bodyText1!.color!.withAlpha(50);
return ListView.builder(
key: const Key('dummychats'),
itemCount: dummyChatCount,
itemBuilder: (context, i) => Opacity(
opacity: (dummyChatCount - i) / dummyChatCount,
child: ListTile(
leading: CircleAvatar(
backgroundColor: titleColor,
child: CircularProgressIndicator(
strokeWidth: 1,
color: Theme.of(context).textTheme.bodyText1!.color,
), ),
), title: Row(
title: Row( children: [
children: [ Expanded(
Expanded( child: Container(
child: Container( height: 14,
height: 14, decoration: BoxDecoration(
decoration: BoxDecoration( color: titleColor,
color: titleColor, borderRadius: BorderRadius.circular(3),
borderRadius: BorderRadius.circular(3), ),
), ),
), ),
), const SizedBox(width: 36),
const SizedBox(width: 36), Container(
Container( height: 14,
height: 14, width: 14,
width: 14, decoration: BoxDecoration(
decoration: BoxDecoration( color: subtitleColor,
color: subtitleColor, borderRadius: BorderRadius.circular(14),
borderRadius: BorderRadius.circular(14), ),
), ),
), const SizedBox(width: 12),
const SizedBox(width: 12), Container(
Container( height: 14,
height: 14, width: 14,
width: 14, decoration: BoxDecoration(
decoration: BoxDecoration( color: subtitleColor,
color: subtitleColor, borderRadius: BorderRadius.circular(14),
borderRadius: BorderRadius.circular(14), ),
), ),
), ],
], ),
), subtitle: Container(
subtitle: Container( decoration: BoxDecoration(
decoration: BoxDecoration( color: subtitleColor,
color: subtitleColor, borderRadius: BorderRadius.circular(3),
borderRadius: BorderRadius.circular(3), ),
height: 12,
margin: const EdgeInsets.only(right: 22),
), ),
height: 12,
margin: const EdgeInsets.only(right: 22),
), ),
), ),
), );
); },
}), ),
); );
} }
} }