diff --git a/lib/screens/account/friend.dart b/lib/screens/account/friend.dart index e801998..c66cd42 100644 --- a/lib/screens/account/friend.dart +++ b/lib/screens/account/friend.dart @@ -5,7 +5,7 @@ import 'package:solian/exts.dart'; import 'package:solian/models/friendship.dart'; import 'package:solian/providers/auth.dart'; import 'package:solian/providers/friend.dart'; -import 'package:solian/widgets/account/account_avatar.dart'; +import 'package:solian/widgets/account/friend_list.dart'; class FriendScreen extends StatefulWidget { const FriendScreen({super.key}); @@ -24,15 +24,6 @@ class _FriendScreenState extends State { return _friendships.where((x) => x.status == status).toList(); } - DismissDirection getDismissDirection(Friendship relation) { - if (relation.status == 2) return DismissDirection.endToStart; - if (relation.status == 1) return DismissDirection.startToEnd; - if (relation.status == 0 && relation.relatedId != _accountId) { - return DismissDirection.startToEnd; - } - return DismissDirection.horizontal; - } - Future getFriendship() async { setState(() => _isBusy = true); @@ -48,6 +39,41 @@ class _FriendScreenState extends State { }); } + void showScopedListPopup(String title, int status) { + showModalBottomSheet( + useRootNavigator: true, + isScrollControlled: true, + context: context, + builder: (context) { + return SizedBox( + height: MediaQuery.of(context).size.height * 0.85, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: Theme.of(context).textTheme.headlineSmall, + ).paddingOnly(left: 24, right: 24, top: 32, bottom: 16), + Expanded( + child: CustomScrollView( + slivers: [ + SliverFriendList( + accountId: _accountId!, + items: filterWithStatus(status), + onUpdate: () { + getFriendship(); + }, + ), + ], + ), + ), + ], + ), + ); + }, + ); + } + void promptAddFriend() async { final FriendProvider provider = Get.find(); @@ -117,46 +143,6 @@ class _FriendScreenState extends State { Future.delayed(Duration.zero, () => getFriendship()); } - Widget buildFriendshipItem(context, index, status) { - final element = filterWithStatus(status)[index]; - final otherside = element.getOtherside(_accountId!); - - final randomId = DateTime.now().microsecondsSinceEpoch >> 10; - - return Dismissible( - key: Key(randomId.toString()), - background: Container( - color: Colors.red, - padding: const EdgeInsets.symmetric(horizontal: 20), - alignment: Alignment.centerLeft, - child: const Icon(Icons.close, color: Colors.white), - ), - secondaryBackground: Container( - color: Colors.green, - padding: const EdgeInsets.symmetric(horizontal: 20), - alignment: Alignment.centerRight, - child: const Icon(Icons.check, color: Colors.white), - ), - direction: getDismissDirection(element), - child: ListTile( - title: Text(otherside.nick), - subtitle: Text(otherside.name), - leading: AccountAvatar(content: otherside.avatar), - ), - onDismissed: (direction) async { - final FriendProvider provider = Get.find(); - if (direction == DismissDirection.startToEnd) { - await provider.updateFriendship(element, 2); - await getFriendship(); - } - if (direction == DismissDirection.endToStart) { - await provider.updateFriendship(element, 1); - await getFriendship(); - } - }, - ); - } - @override Widget build(BuildContext context) { return Material( @@ -183,7 +169,8 @@ class _FriendScreenState extends State { title: Text( '${'accountFriendPending'.tr} (${filterWithStatus(0).length})', ), - onTap: () {}, + onTap: () => + showScopedListPopup('accountFriendPending'.tr, 0), ), ), SliverToBoxAdapter( @@ -195,32 +182,26 @@ class _FriendScreenState extends State { title: Text( '${'accountFriendBlocked'.tr} (${filterWithStatus(2).length})', ), - onTap: () {}, + onTap: () => + showScopedListPopup('accountFriendBlocked'.tr, 2), ), ), - SliverList.builder( - itemCount: filterWithStatus(1).length, - itemBuilder: (_, __) => buildFriendshipItem(_, __, 1), + SliverFriendList( + accountId: _accountId!, + items: filterWithStatus(1), + onUpdate: () { + getFriendship(); + }, + ), + const SliverToBoxAdapter( + child: Divider(thickness: 0.3, height: 0.3), ), SliverToBoxAdapter( - child: Container( - decoration: BoxDecoration( - border: Border( - top: BorderSide( - color: Theme.of(context) - .colorScheme - .surfaceVariant - .withOpacity(0.8), - width: 0.3, - )), - ), - padding: const EdgeInsets.only(top: 16, bottom: 32), - child: Text( - 'accountFriendListHint'.tr, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.bodySmall, - ), - ), + child: Text( + 'accountFriendListHint'.tr, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodySmall, + ).paddingOnly(top: 16, bottom: 32), ), ], ), diff --git a/lib/widgets/account/friend_list.dart b/lib/widgets/account/friend_list.dart new file mode 100644 index 0000000..af2f6e1 --- /dev/null +++ b/lib/widgets/account/friend_list.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:solian/models/friendship.dart'; +import 'package:solian/providers/friend.dart'; +import 'package:solian/widgets/account/account_avatar.dart'; + +class SliverFriendList extends StatelessWidget { + final int accountId; + final List items; + final Function onUpdate; + + const SliverFriendList({ + super.key, + required this.accountId, + required this.items, + required this.onUpdate, + }); + + DismissDirection getDismissDirection(Friendship relation) { + if (relation.status == 2) return DismissDirection.endToStart; + if (relation.status == 1) return DismissDirection.startToEnd; + if (relation.status == 0 && relation.relatedId != accountId) { + return DismissDirection.startToEnd; + } + return DismissDirection.horizontal; + } + + Widget buildItem(context, index) { + final element = items[index]; + final otherside = element.getOtherside(accountId); + + final randomId = DateTime.now().microsecondsSinceEpoch >> 10; + + return Dismissible( + key: Key(randomId.toString()), + background: Container( + color: Colors.red, + padding: const EdgeInsets.symmetric(horizontal: 20), + alignment: Alignment.centerLeft, + child: const Icon(Icons.close, color: Colors.white), + ), + secondaryBackground: Container( + color: Colors.green, + padding: const EdgeInsets.symmetric(horizontal: 20), + alignment: Alignment.centerRight, + child: const Icon(Icons.check, color: Colors.white), + ), + direction: getDismissDirection(element), + child: ListTile( + title: Text(otherside.nick), + subtitle: Text(otherside.name), + leading: AccountAvatar(content: otherside.avatar), + ), + onDismissed: (direction) { + final FriendProvider provider = Get.find(); + if (direction == DismissDirection.startToEnd) { + provider.updateFriendship(element, 2).then((_) => onUpdate()); + } + if (direction == DismissDirection.endToStart) { + provider.updateFriendship(element, 1).then((_) => onUpdate()); + } + }, + ); + } + + @override + Widget build(BuildContext context) { + return SliverList.builder( + itemCount: items.length, + itemBuilder: (_, __) => buildItem(_, __), + ); + } +}