Files
tongxunruanjian/mobile-next/lib/pages/contacts/contacts_view.dart
T

183 lines
5.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:openim_common/openim_common.dart';
import '../../company/brand/app_tokens.dart';
import '../../company/ui/state_views.dart';
import 'contacts_logic.dart';
class ContactsPage extends StatelessWidget {
final logic = Get.find<ContactsLogic>();
ContactsPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.pageBg,
appBar: AppBar(
title: const Text('通讯录'),
actions: [
IconButton(
onPressed: logic.addContacts,
icon: const Icon(Icons.person_add_alt,
size: AppIconSize.md, color: AppColors.textPrimary),
),
],
),
body: Obx(() {
if (logic.loading.value) {
return const CompanyLoadingView();
}
if (logic.loadFailed.value) {
return CompanyFailView(onRetry: logic.reload);
}
final grouped = logic.groupedColleagues;
return CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Column(
children: [
_entry(
icon: Icons.person_add_alt,
label: '新的同事',
count: logic.friendApplicationCount,
onTap: logic.newFriend,
),
_entry(
icon: Icons.group_outlined,
label: '我的群聊',
count: logic.groupApplicationCount,
onTap: logic.myGroup,
),
],
),
),
if (logic.colleagues.isEmpty)
const SliverFillRemaining(
hasScrollBody: false,
child: CompanyEmptyView(
icon: Icons.person_outline,
title: '暂时没有同事',
subtitle: '点右上角添加同事',
),
)
else
for (final entry in grouped.entries) ...[
SliverToBoxAdapter(child: _groupHeader(entry.key)),
SliverList(
delegate: SliverChildBuilderDelegate(
(_, index) => _colleagueRow(entry.value[index]),
childCount: entry.value.length,
),
),
],
],
);
}),
);
}
Widget _groupHeader(String name) {
return Container(
height: 28,
color: AppColors.chatBg,
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: AppGap.x4),
child: Text(
name,
style: const TextStyle(
fontSize: AppFont.small, color: AppColors.textSecondary),
),
);
}
Widget _colleagueRow(ColleagueRow row) {
return InkWell(
onTap: () => logic.openColleague(row),
splashColor: AppColors.chatBg,
highlightColor: AppColors.chatBg,
child: SizedBox(
height: 64,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: AppGap.x4),
child: Row(
children: [
AvatarView(
url: row.faceURL,
text: row.nickname,
width: 48,
height: 48,
),
const SizedBox(width: AppGap.x3),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
row.nickname,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: AppFont.body,
color: AppColors.textPrimary),
),
if (row.subtitle.isNotEmpty)
Text(
row.subtitle,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: AppFont.sub,
color: AppColors.textSecondary),
),
],
),
),
],
),
),
),
);
}
Widget _entry({
required IconData icon,
required String label,
int count = 0,
required VoidCallback onTap,
}) {
return InkWell(
onTap: onTap,
child: SizedBox(
height: 56,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: AppGap.x4),
child: Row(
children: [
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: AppColors.primaryActive,
borderRadius: BorderRadius.circular(AppRadius.control),
),
alignment: Alignment.center,
child:
Icon(icon, size: AppIconSize.sm, color: AppColors.primary),
),
const SizedBox(width: AppGap.x3),
Text(label,
style: const TextStyle(
fontSize: AppFont.body, color: AppColors.textPrimary)),
const Spacer(),
if (count > 0) UnreadCountView(count: count),
],
),
),
),
);
}
}