import 'package:autosos_flutter/model/misc.dart'; import 'package:autosos_flutter/provider/providers.dart'; import 'package:autosos_flutter/router/app_router.dart'; import 'package:autosos_flutter/widget/multi_state_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; /// 消息中心(对应 Android MessengerActivity) class MessengerPage extends ConsumerStatefulWidget { const MessengerPage({super.key}); @override ConsumerState createState() => _MessengerPageState(); } class _MessengerPageState extends ConsumerState { MultiState _state = MultiState.loading; List _items = []; int _page = 1; bool _hasMore = true; bool _loadingMore = false; final _scroll = ScrollController(); @override void initState() { super.initState(); _load(reset: true); _scroll.addListener(() { if (_scroll.position.pixels >= _scroll.position.maxScrollExtent - 200) { _load(); } }); } @override void dispose() { _scroll.dispose(); super.dispose(); } Future _load({bool reset = false}) async { if (reset) { _page = 1; _hasMore = true; _items = []; setState(() => _state = MultiState.loading); } if (!_hasMore || _loadingMore) return; _loadingMore = true; try { final resp = await ref.read(userApiProvider).messages( page: _page, size: 20, ); if (!mounted) return; if (!resp.isSuccess) { if (reset) setState(() => _state = MultiState.error); return; } final list = resp.data?.list ?? []; _items.addAll(list); _hasMore = (resp.data?.hasMore ?? false) && list.length >= 20; _page++; setState(() { _state = _items.isEmpty ? MultiState.empty : MultiState.success; }); } catch (e) { if (mounted && reset) setState(() => _state = MultiState.error); } finally { _loadingMore = false; } } Future _onTap(MessengerItem item) async { if (!item.read) { try { await ref.read(userApiProvider).readMessage(item.id); } catch (_) {} } if (!mounted) return; setState(() { final i = _items.indexWhere((e) => e.id == item.id); if (i >= 0) { _items[i] = MessengerItem( id: item.id, title: item.title, content: item.content, createdAt: item.createdAt, read: true, link: item.link, ); } }); if (item.link != null && item.link!.isNotEmpty) { context.push( '${Routes.webview}?url=${Uri.encodeComponent(item.link!)}&title=${Uri.encodeComponent(item.title)}', ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('消息中心')), body: RefreshIndicator( onRefresh: () => _load(reset: true), child: MultiStateView( state: _state, emptyText: '暂无消息', onRetry: () => _load(reset: true), child: ListView.separated( controller: _scroll, itemCount: _items.length + (_hasMore ? 1 : 0), separatorBuilder: (_, __) => Divider( height: 1, color: Colors.grey.shade200, indent: 16, ), itemBuilder: (ctx, i) { if (i >= _items.length) { return const Padding( padding: EdgeInsets.all(16), child: Center( child: CircularProgressIndicator(strokeWidth: 2), ), ); } final m = _items[i]; return ListTile( leading: CircleAvatar( backgroundColor: m.read ? Colors.grey.shade300 : Theme.of(context).primaryColor, child: const Icon(Icons.notifications, color: Colors.white, size: 20), ), title: Text( m.title, style: TextStyle( fontWeight: m.read ? FontWeight.normal : FontWeight.bold, ), ), subtitle: Text( m.content, maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 13), ), trailing: Text( DateFormat('MM-dd HH:mm').format(m.createdAt), style: const TextStyle(fontSize: 11, color: Colors.grey), ), onTap: () => _onTap(m), ); }, ), ), ), ); } }