Skip to content

Commit 63b767f

Browse files
committed
refactor(account): improve error handling and state updates in notifications
- Refactor notification fetching to use a centralized error handler - Optimize state updates by atomically updating both tabs' data - Improve pagination by updating the correct tab's state after fetching more notifications - Remove unnecessary parameters and simplify the _fetchNotifications method
1 parent b097e98 commit 63b767f

File tree

1 file changed

+90
-80
lines changed

1 file changed

+90
-80
lines changed

lib/account/bloc/in_app_notification_center_bloc.dart

Lines changed: 90 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,31 @@ class InAppNotificationCenterBloc
7070
return;
7171
}
7272

73-
// Fetch both tabs' initial data in parallel.
74-
await Future.wait([
75-
_fetchNotifications(
76-
emit: emit,
77-
userId: userId,
78-
filter: _breakingNewsFilter,
79-
isInitialFetch: true,
80-
),
81-
_fetchNotifications(
82-
emit: emit,
83-
userId: userId,
84-
filter: _digestFilter,
85-
isInitialFetch: true,
86-
),
87-
]);
73+
try {
74+
// Fetch both tabs' initial data in parallel and wait for their results.
75+
final results = await Future.wait([
76+
_fetchNotifications(userId: userId, filter: _breakingNewsFilter),
77+
_fetchNotifications(userId: userId, filter: _digestFilter),
78+
]);
79+
80+
final breakingNewsResponse = results[0];
81+
final digestResponse = results[1];
8882

89-
// After both fetches are complete, set the status to success.
90-
emit(state.copyWith(status: InAppNotificationCenterStatus.success));
83+
// Perform a single, atomic state update with both results.
84+
emit(
85+
state.copyWith(
86+
status: InAppNotificationCenterStatus.success,
87+
breakingNewsNotifications: breakingNewsResponse.items,
88+
breakingNewsHasMore: breakingNewsResponse.hasMore,
89+
breakingNewsCursor: breakingNewsResponse.cursor,
90+
digestNotifications: digestResponse.items,
91+
digestHasMore: digestResponse.hasMore,
92+
digestCursor: digestResponse.cursor,
93+
),
94+
);
95+
} catch (error, stackTrace) {
96+
_handleFetchError(emit, error, stackTrace);
97+
}
9198
}
9299

93100
/// Handles fetching the next page of notifications for the current tab.
@@ -120,15 +127,42 @@ class InAppNotificationCenterBloc
120127
? state.breakingNewsCursor
121128
: state.digestCursor;
122129

123-
await _fetchNotifications(
124-
emit: emit,
125-
userId: userId,
126-
filter: filter,
127-
cursor: cursor,
128-
);
130+
try {
131+
final response = await _fetchNotifications(
132+
userId: userId,
133+
filter: filter,
134+
cursor: cursor,
135+
);
129136

130-
// After fetch, set status back to success.
131-
emit(state.copyWith(status: InAppNotificationCenterStatus.success));
137+
// Append the new items to the correct list.
138+
if (isBreakingNewsTab) {
139+
emit(
140+
state.copyWith(
141+
status: InAppNotificationCenterStatus.success,
142+
breakingNewsNotifications: [
143+
...state.breakingNewsNotifications,
144+
...response.items,
145+
],
146+
breakingNewsHasMore: response.hasMore,
147+
breakingNewsCursor: response.cursor,
148+
),
149+
);
150+
} else {
151+
emit(
152+
state.copyWith(
153+
status: InAppNotificationCenterStatus.success,
154+
digestNotifications: [
155+
...state.digestNotifications,
156+
...response.items,
157+
],
158+
digestHasMore: response.hasMore,
159+
digestCursor: response.cursor,
160+
),
161+
);
162+
}
163+
} catch (error, stackTrace) {
164+
_handleFetchError(emit, error, stackTrace);
165+
}
132166
}
133167

134168
/// Handles the event to change the active tab.
@@ -303,64 +337,22 @@ class InAppNotificationCenterBloc
303337
}
304338

305339
/// A generic method to fetch notifications based on a filter.
306-
Future<void> _fetchNotifications({
307-
required Emitter<InAppNotificationCenterState> emit,
340+
Future<PaginatedResponse<InAppNotification>> _fetchNotifications({
308341
required String userId,
309342
required Map<String, dynamic> filter,
310343
String? cursor,
311-
bool isInitialFetch = false,
312-
}) {
313-
final isBreakingNewsFilter = filter == _breakingNewsFilter;
314-
315-
return _inAppNotificationRepository
316-
.readAll(
317-
userId: userId,
318-
filter: filter,
319-
pagination: PaginationOptions(
320-
limit: _notificationsFetchLimit,
321-
cursor: cursor,
322-
),
323-
sort: [const SortOption('createdAt', SortOrder.desc)],
324-
)
325-
.then((response) {
326-
final newNotifications = response.items;
327-
final nextCursor = response.cursor;
328-
final hasMore = response.hasMore;
329-
330-
if (isBreakingNewsFilter) {
331-
emit(
332-
state.copyWith(
333-
breakingNewsNotifications: isInitialFetch
334-
? newNotifications
335-
: [...state.breakingNewsNotifications, ...newNotifications],
336-
breakingNewsHasMore: hasMore,
337-
breakingNewsCursor: nextCursor,
338-
),
339-
);
340-
} else {
341-
emit(
342-
state.copyWith(
343-
digestNotifications: isInitialFetch
344-
? newNotifications
345-
: [...state.digestNotifications, ...newNotifications],
346-
digestHasMore: hasMore,
347-
digestCursor: nextCursor,
348-
),
349-
);
350-
}
351-
})
352-
.catchError((Object e, StackTrace s) {
353-
_logger.severe('Failed to fetch notifications.', e, s);
354-
final httpException = e is HttpException
355-
? e
356-
: UnknownException(e.toString());
357-
emit(
358-
state.copyWith(
359-
status: InAppNotificationCenterStatus.failure,
360-
error: httpException,
361-
),
362-
);
363-
});
344+
}) async {
345+
// This method now simply fetches and returns the data, or throws on error.
346+
// The responsibility of emitting state is moved to the event handlers.
347+
return _inAppNotificationRepository.readAll(
348+
userId: userId,
349+
filter: filter,
350+
pagination: PaginationOptions(
351+
limit: _notificationsFetchLimit,
352+
cursor: cursor,
353+
),
354+
sort: [const SortOption('createdAt', SortOrder.desc)],
355+
);
364356
}
365357

366358
/// Filter for "Breaking News" notifications.
@@ -389,4 +381,22 @@ class InAppNotificationCenterBloc
389381
],
390382
},
391383
};
384+
385+
/// Centralized error handler for fetch operations.
386+
void _handleFetchError(
387+
Emitter<InAppNotificationCenterState> emit,
388+
Object error,
389+
StackTrace stackTrace,
390+
) {
391+
_logger.severe('Failed to fetch notifications.', error, stackTrace);
392+
final httpException = error is HttpException
393+
? error
394+
: UnknownException(error.toString());
395+
emit(
396+
state.copyWith(
397+
status: InAppNotificationCenterStatus.failure,
398+
error: httpException,
399+
),
400+
);
401+
}
392402
}

0 commit comments

Comments
 (0)