notifications_provider.dart 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import 'package:flutter_riverpod/flutter_riverpod.dart';
  2. import '../core/network/dio_client.dart';
  3. import '../data/models/announcement/announcement.dart';
  4. import '../data/services/announcement_service.dart';
  5. // ── State ──────────────────────────────────────────────────
  6. class AppNotificationsState {
  7. final List<AnnouncementContent> notifications;
  8. final bool isLoading;
  9. final bool hasMore;
  10. final int currentPage;
  11. final String? errorMessage;
  12. const AppNotificationsState({
  13. this.notifications = const [],
  14. this.isLoading = false,
  15. this.hasMore = true,
  16. this.currentPage = 1,
  17. this.errorMessage,
  18. });
  19. AppNotificationsState copyWith({
  20. List<AnnouncementContent>? notifications,
  21. bool? isLoading,
  22. bool? hasMore,
  23. int? currentPage,
  24. String? errorMessage,
  25. }) =>
  26. AppNotificationsState(
  27. notifications: notifications ?? this.notifications,
  28. isLoading: isLoading ?? this.isLoading,
  29. hasMore: hasMore ?? this.hasMore,
  30. currentPage: currentPage ?? this.currentPage,
  31. errorMessage: errorMessage,
  32. );
  33. }
  34. // ── Notifier ───────────────────────────────────────────────
  35. class AppNotificationsNotifier
  36. extends AutoDisposeNotifier<AppNotificationsState> {
  37. static const _pageSize = 10;
  38. AnnouncementService get _service =>
  39. AnnouncementService(ref.read(dioClientProvider));
  40. @override
  41. AppNotificationsState build() {
  42. Future.microtask(_loadFirst);
  43. return const AppNotificationsState(isLoading: true);
  44. }
  45. Future<void> _loadFirst() async {
  46. try {
  47. final result = await _service.getAnnouncementPage(
  48. pageNo: 1,
  49. pageSize: _pageSize,
  50. );
  51. state = state.copyWith(
  52. notifications: result.content,
  53. isLoading: false,
  54. currentPage: 1,
  55. hasMore: result.content.length >= _pageSize,
  56. );
  57. } catch (e) {
  58. state = state.copyWith(isLoading: false, errorMessage: e.toString());
  59. }
  60. }
  61. /// 下拉刷新
  62. Future<void> refresh() async {
  63. state = state.copyWith(isLoading: true, errorMessage: null);
  64. try {
  65. final result = await _service.getAnnouncementPage(
  66. pageNo: 1,
  67. pageSize: _pageSize,
  68. );
  69. state = state.copyWith(
  70. notifications: result.content,
  71. isLoading: false,
  72. currentPage: 1,
  73. hasMore: result.content.length >= _pageSize,
  74. );
  75. } catch (e) {
  76. state = state.copyWith(isLoading: false, errorMessage: e.toString());
  77. }
  78. }
  79. /// 上拉加载更多
  80. Future<void> loadMore() async {
  81. if (state.isLoading || !state.hasMore) return;
  82. state = state.copyWith(isLoading: true);
  83. try {
  84. final nextPage = state.currentPage + 1;
  85. final result = await _service.getAnnouncementPage(
  86. pageNo: nextPage,
  87. pageSize: _pageSize,
  88. );
  89. state = state.copyWith(
  90. notifications: [...state.notifications, ...result.content],
  91. isLoading: false,
  92. currentPage: nextPage,
  93. hasMore: result.content.length >= _pageSize,
  94. );
  95. } catch (e) {
  96. state = state.copyWith(isLoading: false, errorMessage: e.toString());
  97. }
  98. }
  99. }
  100. // ── Provider ───────────────────────────────────────────────
  101. final notificationsProvider = AutoDisposeNotifierProvider<
  102. AppNotificationsNotifier, AppNotificationsState>(
  103. AppNotificationsNotifier.new,
  104. );