Files
sweet_chat_app/lib/pages/contacts_page.dart

173 lines
4.5 KiB
Dart

import 'package:azlistview/azlistview.dart';
import 'package:flutter/material.dart';
import 'package:lpinyin/lpinyin.dart';
import 'package:sweet_chat_app/apis/user_api.dart';
import 'package:sweet_chat_app/models/user.dart';
import 'package:sweet_chat_app/utils/SpUtil.dart';
import 'chat_page.dart';
class ContactInfo extends ISuspensionBean {
final String name;
final String avatar;
String? tagIndex;
String? namePinyin;
ContactInfo({
required this.name,
required this.avatar,
this.tagIndex,
this.namePinyin,
});
@override
String getSuspensionTag() => tagIndex ?? '#';
}
/// ================= Page =================
class ContactsPage extends StatefulWidget {
const ContactsPage({super.key});
@override
State<ContactsPage> createState() => _ContactsPageState();
}
class _ContactsPageState extends State<ContactsPage> {
List<ContactInfo> contactList = [];
@override
void initState() {
super.initState();
_loadFriends();
}
Future<void> _loadFriends() async {
final userId = SpUtil.getInt('userId') ?? 0;
final friendList = await getUserFriendsApi(userId);
setState(() {
_handleList(friendList);
});
}
void _handleList(List<User> friends) {
contactList =
friends.map((user) {
final pinyin = PinyinHelper.getPinyinE(user.nickname);
final tag = pinyin.substring(0, 1).toUpperCase();
return ContactInfo(
name: user.nickname,
avatar: user.avatarUrl,
tagIndex: RegExp(r'^[A-Z]$').hasMatch(tag) ? tag : '#',
namePinyin: pinyin,
);
}).toList();
SuspensionUtil.sortListBySuspensionTag(contactList);
SuspensionUtil.setShowSuspensionStatus(contactList);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
appBar: _buildAppBar(),
body: Column(
children: [_buildSearchBar(), Expanded(child: _buildAzListView())],
),
);
}
PreferredSizeWidget _buildAppBar() {
return AppBar(
automaticallyImplyLeading: false,
backgroundColor: Color(0xFF120D25),
elevation: 0,
centerTitle: true,
title: const Text(
'通讯录',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
);
}
Widget _buildAzListView() {
return AzListView(
data: contactList,
itemCount: contactList.length,
itemBuilder: (_, index) {
final contact = contactList[index];
return ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(contact.avatar),
onBackgroundImageError: (_, __) {},
),
title: Text(
contact.name,
style: const TextStyle(fontSize: 16, color: Colors.white),
),
onTap: () => onTapContact(contact),
);
},
susItemBuilder: (_, index) {
final tag = contactList[index].getSuspensionTag();
return Container(
height: 28,
padding: const EdgeInsets.symmetric(horizontal: 16),
alignment: Alignment.centerLeft,
color: const Color(0xFF2B2744),
child: Text(
tag,
style: const TextStyle(fontSize: 13, color: Colors.grey),
),
);
},
indexBarData: [...kIndexBarData],
indexBarOptions: IndexBarOptions(
textStyle: const TextStyle(fontSize: 12, color: Color(0xFF8E8E93)),
selectItemDecoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.green,
),
),
);
}
Widget _buildSearchBar() {
return Container(
height: 44,
decoration: BoxDecoration(color: Color(0xFF2F2A47)),
child: TextField(
textAlignVertical: TextAlignVertical.center,
style: const TextStyle(color: Colors.white),
decoration: InputDecoration(
isDense: true,
hintText: '搜索联系人',
hintStyle: const TextStyle(fontSize: 15, color: Colors.white),
prefixIcon: const Icon(Icons.search, size: 20, color: Colors.white),
border: InputBorder.none,
),
),
);
}
void onTapContact(ContactInfo contact) {
Navigator.push(
context,
MaterialPageRoute(
builder:
(_) => ChatPage(
contactName: contact.name,
avatarUrl: contact.avatar,
),
),
);
}
}