together_mobile/lib/screens/contact/contact_screen.dart

321 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:badges/badges.dart' as badges;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:get_it_mixin/get_it_mixin.dart';
import 'package:together_mobile/common/constants.dart';
import 'package:together_mobile/models/apply_list_model.dart';
import 'package:together_mobile/models/contact_model.dart';
import 'package:together_mobile/models/user_model.dart';
import 'package:together_mobile/request/server.dart';
import 'package:together_mobile/screens/contact/components/friend_group.dart';
import 'package:together_mobile/screens/contact/components/friend_tile.dart';
import 'package:together_mobile/screens/contact/components/group_chat_tile.dart';
class ContactScreen extends StatefulWidget with GetItStatefulWidgetMixin {
ContactScreen({super.key});
@override
State<ContactScreen> createState() => _ContactScreenState();
}
class _ContactScreenState extends State<ContactScreen> with GetItStateMixin {
final Map<String, bool> _shows = {
'friendGroups': true,
'allFriends': false,
'groupChats': false
};
@override
Widget build(BuildContext context) {
Map<String, FriendSetting> friends = watchOnly(
(Contact contact) => contact.friends,
);
List<String> friendGroups = watchOnly(
(Contact contact) => contact.friendGroups,
);
int applyCount = watchOnly(
(ApplyList applyList) => applyList.count,
);
int friendCount = friends.length;
// Create a localkey, use to generate the custom scroll view,
// or there will be a error: "Duplicate GlobalKey detected in widget tree."
// But when I wrap custom scroll view into the RefrashIndicator, the key isn't needed any more
// const Key customScrollKey = ValueKey<String>('bottom-sliver-list');
return Scaffold(
appBar: AppBar(
leading: Container(
margin: const EdgeInsets.only(left: 8),
child: get<UserProfile>().avatar.isEmpty
? const CircleAvatar(
backgroundImage: AssetImage('assets/images/user_2.png'),
)
: CircleAvatar(
backgroundImage: CachedNetworkImageProvider(
'$avatarsUrl/${get<UserProfile>().avatar}',
),
),
),
title: const Text('通讯录'),
centerTitle: true,
actions: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.search),
splashRadius: 20,
),
IconButton(
onPressed: () {
context.push('/contact/add');
},
icon: const Icon(Icons.person_add_alt_1),
splashRadius: 20,
),
],
),
body: RefreshIndicator(
onRefresh: () async {
await Future.delayed(const Duration(seconds: 2));
},
child: CustomScrollView(
physics: const BouncingScrollPhysics(),
// key: customScrollKey,
slivers: [
SliverFixedExtentList(
delegate: SliverChildListDelegate(
[
// apply list
TextButton(
onPressed: () async {
// await getApplicantInfo(get<ApplyList>().applicantIds);
context.push('/contact/apply_list');
},
style: TextButton.styleFrom(
iconColor: Theme.of(context).textTheme.bodyLarge?.color,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
badges.Badge(
showBadge: applyCount > 0,
badgeStyle: const badges.BadgeStyle(
badgeColor: kErrorColor,
elevation: 12,
),
badgeContent: Text(
applyCount.toString(),
style: TextStyle(
fontSize: 11,
color:
Theme.of(context).colorScheme.inversePrimary,
),
),
badgeAnimation: const badges.BadgeAnimation.scale(),
position:
badges.BadgePosition.topEnd(top: -12, end: -15),
child: Text(
'添加申请',
style: TextStyle(
fontSize: 16,
color:
Theme.of(context).textTheme.bodyLarge?.color,
),
),
),
const Icon(
Icons.keyboard_arrow_right,
size: 30,
),
],
),
),
TextButton(
onPressed: () async {
context.push<int>('/contact/friend_group');
},
style: TextButton.styleFrom(
iconColor: Theme.of(context).textTheme.bodyLarge?.color,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'分组管理',
style: TextStyle(
fontSize: 16,
color: Theme.of(context).textTheme.bodyLarge?.color,
),
),
const Icon(
Icons.keyboard_arrow_right,
size: 30,
),
],
),
),
],
),
itemExtent: 50.0,
),
SliverPersistentHeader(
delegate: _MySliverPersistentHeader(_shows, _change, _refresh),
pinned: true,
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
if (_shows['friendGroups']!) {
return FriendGroup(
key: ValueKey(friendGroups[index]),
groupName: friendGroups[index],
);
} else if (_shows['allFriends']!) {
String friendId = friends.keys.toList()[index];
// print(friends);
return FriendTile(
key: ValueKey(
friendId,
),
friendId: friendId,
);
} else {
return GroupChatTile();
}
},
childCount: _shows['friendGroups']!
? friendGroups.length
: _shows['allFriends']!
? friendCount
: get<Contact>().groupChats.length,
),
),
],
),
),
);
}
void _change(String which) {
switch (which) {
case 'friendGroups':
setState(() {
_shows['friendGroups'] = true;
_shows['allFriends'] = false;
_shows['groupChats'] = false;
});
break;
case 'allFriends':
setState(() {
_shows['friendGroups'] = false;
_shows['allFriends'] = true;
_shows['groupChats'] = false;
});
break;
case 'groupChats':
setState(() {
_shows['friendGroups'] = false;
_shows['allFriends'] = false;
_shows['groupChats'] = true;
});
break;
}
}
void _refresh() {
setState(() {});
}
}
class _MySliverPersistentHeader extends SliverPersistentHeaderDelegate {
const _MySliverPersistentHeader(this.shows, this.change, this.refresh);
final Map<String, bool> shows;
final Function(String) change;
final VoidCallback refresh;
@override
double get minExtent => 50;
@override
double get maxExtent => 50;
@override
Widget build(
BuildContext context,
double shrinkOffset,
bool overlapsContent,
) {
return Container(
height: 50,
color: Theme.of(context).colorScheme.background,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
change('friendGroups');
},
child: Container(
margin: const EdgeInsets.only(left: 10),
padding: const EdgeInsets.all(4),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: shows['friendGroups']!
? kSecondaryColor.withOpacity(0.15)
: Theme.of(context).brightness == Brightness.light
? null
: Theme.of(context).colorScheme.background,
),
child: const Text('分组'),
),
),
InkWell(
onTap: () {
change('allFriends');
},
child: Container(
padding: const EdgeInsets.all(4),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: shows['allFriends']!
? kSecondaryColor.withOpacity(0.15)
: Theme.of(context).brightness == Brightness.light
? null
: Theme.of(context).colorScheme.background,
),
child: const Text('全部好友'),
),
),
InkWell(
onTap: () {
change('groupChats');
},
child: Container(
margin: const EdgeInsets.only(right: 10),
padding: const EdgeInsets.all(4),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: shows['groupChats']!
? kSecondaryColor.withOpacity(0.15)
: Theme.of(context).brightness == Brightness.light
? null
: Theme.of(context).colorScheme.background,
),
child: const Text('群聊'),
),
),
],
),
);
}
@override
bool shouldRebuild(covariant _MySliverPersistentHeader oldDelegate) {
return true;
}
}