import 'package:flutter/material.dart'; import '../theme.dart'; /// 空 / 加载中 / 加载失败 / 断网 四态组件,文案严格按效果图 states.png。 /// 空态:还没有消息 class EmptyConversations extends StatelessWidget { /// 「去找同事」按钮点击(跳到通讯录 Tab) final VoidCallback? onFindContacts; const EmptyConversations({super.key, this.onFindContacts}); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.chat_bubble_outline, size: 64, color: AppColors.divider), const SizedBox(height: AppGap.x6), const Text('还没有消息', style: TextStyle(fontSize: AppFont.body, color: AppColors.textPrimary)), const SizedBox(height: AppGap.x2), const Text('去通讯录找同事聊聊吧', style: TextStyle(fontSize: AppFont.sub, color: AppColors.textSecondary)), const SizedBox(height: AppGap.x6), FilledButton( onPressed: onFindContacts, style: FilledButton.styleFrom( backgroundColor: AppColors.primary, padding: const EdgeInsets.symmetric(horizontal: AppGap.x6, vertical: AppGap.x3), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), child: const Text('去找同事', style: TextStyle(fontSize: AppFont.body)), ), ], ), ); } } /// 加载中 class LoadingConversations extends StatelessWidget { const LoadingConversations({super.key}); @override Widget build(BuildContext context) { return const Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ SizedBox( width: 32, height: 32, child: CircularProgressIndicator(strokeWidth: 3, color: AppColors.primary), ), SizedBox(height: AppGap.x6), Text('正在加载', style: TextStyle(fontSize: AppFont.body, color: AppColors.textPrimary)), SizedBox(height: AppGap.x2), Text('消息马上就好,请稍等', style: TextStyle(fontSize: AppFont.sub, color: AppColors.textSecondary)), ], ), ); } } /// 加载失败 class ErrorConversations extends StatelessWidget { final VoidCallback? onRetry; const ErrorConversations({super.key, this.onRetry}); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.error_outline, size: 64, color: AppColors.divider), const SizedBox(height: AppGap.x6), const Text('消息没加载出来', style: TextStyle(fontSize: AppFont.body, color: AppColors.textPrimary)), const SizedBox(height: AppGap.x2), const Text('检查一下网络,再点重试', style: TextStyle(fontSize: AppFont.sub, color: AppColors.textSecondary)), const SizedBox(height: AppGap.x6), OutlinedButton( onPressed: onRetry, style: OutlinedButton.styleFrom( foregroundColor: AppColors.primary, side: const BorderSide(color: AppColors.primary), padding: const EdgeInsets.symmetric(horizontal: AppGap.x6, vertical: AppGap.x3), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), child: const Text('重试', style: TextStyle(fontSize: AppFont.body)), ), ], ), ); } } /// 断网时顶部的深色横幅 class OfflineBanner extends StatelessWidget { const OfflineBanner({super.key}); @override Widget build(BuildContext context) { return Container( width: double.infinity, color: AppColors.bannerBg, padding: const EdgeInsets.symmetric(horizontal: AppGap.x4, vertical: AppGap.x2), child: const Row( children: [ Icon(Icons.error_outline, size: 16, color: Colors.white), SizedBox(width: AppGap.x2), Text('当前网络不可用,请检查网络连接', style: TextStyle(fontSize: AppFont.sub, color: Colors.white)), ], ), ); } } /// 断网时列表底部的灰字提示 class OfflineFooter extends StatelessWidget { const OfflineFooter({super.key}); @override Widget build(BuildContext context) { return const Padding( padding: EdgeInsets.symmetric(vertical: AppGap.x4), child: Center( child: Text('老消息还能看,新消息联网后自动收到', style: TextStyle(fontSize: AppFont.small, color: AppColors.textSecondary)), ), ); } }