Main coves client
1import 'post.dart';
2
3/// Sentinel value for copyWith to distinguish "not provided" from "null"
4const _sentinel = Object();
5
6/// Per-feed state container
7///
8/// Holds all state for a single feed (Discover or For You) including posts,
9/// pagination, loading states, and scroll position.
10class FeedState {
11 const FeedState({
12 this.posts = const [],
13 this.cursor,
14 this.hasMore = true,
15 this.isLoading = false,
16 this.isLoadingMore = false,
17 this.error,
18 this.scrollPosition = 0.0,
19 this.lastRefreshTime,
20 });
21
22 /// Create a default empty state
23 factory FeedState.initial() {
24 return const FeedState();
25 }
26
27 /// Feed posts
28 final List<FeedViewPost> posts;
29
30 /// Pagination cursor for next page
31 final String? cursor;
32
33 /// Whether more pages are available
34 final bool hasMore;
35
36 /// Initial load in progress
37 final bool isLoading;
38
39 /// Pagination (load more) in progress
40 final bool isLoadingMore;
41
42 /// Error message if any
43 final String? error;
44
45 /// Cached scroll position for this feed
46 final double scrollPosition;
47
48 /// Last refresh timestamp for staleness checks
49 final DateTime? lastRefreshTime;
50
51 /// Create a copy with modified fields (immutable updates)
52 ///
53 /// Nullable fields (cursor, error, lastRefreshTime) use a sentinel pattern
54 /// to distinguish between "not provided" and "explicitly set to null".
55 /// Pass null explicitly to clear these fields.
56 FeedState copyWith({
57 List<FeedViewPost>? posts,
58 Object? cursor = _sentinel,
59 bool? hasMore,
60 bool? isLoading,
61 bool? isLoadingMore,
62 Object? error = _sentinel,
63 double? scrollPosition,
64 Object? lastRefreshTime = _sentinel,
65 }) {
66 return FeedState(
67 posts: posts ?? this.posts,
68 cursor: cursor == _sentinel ? this.cursor : cursor as String?,
69 hasMore: hasMore ?? this.hasMore,
70 isLoading: isLoading ?? this.isLoading,
71 isLoadingMore: isLoadingMore ?? this.isLoadingMore,
72 error: error == _sentinel ? this.error : error as String?,
73 scrollPosition: scrollPosition ?? this.scrollPosition,
74 lastRefreshTime:
75 lastRefreshTime == _sentinel
76 ? this.lastRefreshTime
77 : lastRefreshTime as DateTime?,
78 );
79 }
80}