Skip to content

Commit f11a113

Browse files
committed
refactor: use generic data repository
- Use shared models - Use standardized exceptions - Simplified filter logic
1 parent c5501ae commit f11a113

File tree

1 file changed

+78
-27
lines changed

1 file changed

+78
-27
lines changed

lib/headlines-feed/bloc/headlines_feed_bloc.dart

Lines changed: 78 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@ import 'dart:async';
33
import 'package:bloc/bloc.dart';
44
import 'package:bloc_concurrency/bloc_concurrency.dart';
55
import 'package:equatable/equatable.dart';
6-
import 'package:ht_headlines_client/ht_headlines_client.dart'; // Import for Headline and Exceptions
7-
import 'package:ht_headlines_repository/ht_headlines_repository.dart';
6+
import 'package:ht_data_repository/ht_data_repository.dart'; // Generic Data Repository
87
import 'package:ht_main/headlines-feed/models/headline_filter.dart';
8+
import 'package:ht_shared/ht_shared.dart'
9+
show
10+
Category,
11+
Country,
12+
Headline,
13+
HtHttpException,
14+
Source; // Shared models and standardized exceptions
915

1016
part 'headlines_feed_event.dart';
1117
part 'headlines_feed_state.dart';
@@ -14,13 +20,13 @@ part 'headlines_feed_state.dart';
1420
/// Manages the state for the headlines feed feature.
1521
///
1622
/// Handles fetching headlines, applying filters, pagination, and refreshing
17-
/// the feed using the provided [HtHeadlinesRepository].
23+
/// the feed using the provided [HtDataRepository].
1824
/// {@endtemplate}
1925
class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
2026
/// {@macro headlines_feed_bloc}
2127
///
22-
/// Requires a [HtHeadlinesRepository] to interact with the data layer.
23-
HeadlinesFeedBloc({required HtHeadlinesRepository headlinesRepository})
28+
/// Requires a [HtDataRepository<Headline>] to interact with the data layer.
29+
HeadlinesFeedBloc({required HtDataRepository<Headline> headlinesRepository})
2430
: _headlinesRepository = headlinesRepository,
2531
super(HeadlinesFeedLoading()) {
2632
on<HeadlinesFeedFetchRequested>(
@@ -37,7 +43,7 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
3743
on<HeadlinesFeedFiltersCleared>(_onHeadlinesFeedFiltersCleared);
3844
}
3945

40-
final HtHeadlinesRepository _headlinesRepository;
46+
final HtDataRepository<Headline> _headlinesRepository;
4147

4248
/// The number of headlines to fetch per page during pagination or initial load.
4349
static const _headlinesFetchLimit = 10;
@@ -54,12 +60,26 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
5460
) async {
5561
emit(HeadlinesFeedLoading()); // Show loading for filter application
5662
try {
57-
final response = await _headlinesRepository.getHeadlines(
58-
limit: _headlinesFetchLimit,
59-
categories: event.filter.categories,
60-
sources: event.filter.sources,
61-
eventCountries: event.filter.eventCountries,
62-
);
63+
final response = await _headlinesRepository.readAllByQuery({
64+
if (event.filter.categories?.isNotEmpty ?? false)
65+
'categories':
66+
event.filter.categories!
67+
.whereType<Category>()
68+
.map((c) => c.id)
69+
.toList(),
70+
if (event.filter.sources?.isNotEmpty ?? false)
71+
'sources':
72+
event.filter.sources!
73+
.whereType<Source>()
74+
.map((s) => s.id)
75+
.toList(),
76+
if (event.filter.eventCountries?.isNotEmpty ?? false)
77+
'eventCountries':
78+
event.filter.eventCountries!
79+
.whereType<Country>()
80+
.map((c) => c.isoCode)
81+
.toList(),
82+
}, limit: _headlinesFetchLimit,);
6383
emit(
6484
HeadlinesFeedLoaded(
6585
headlines: response.items,
@@ -68,7 +88,7 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
6888
filter: event.filter, // Store the applied filter
6989
),
7090
);
71-
} on HeadlinesFetchException catch (e) {
91+
} on HtHttpException catch (e) {
7292
emit(HeadlinesFeedError(message: e.message));
7393
} catch (e, st) {
7494
// Log the error and stack trace for unexpected errors
@@ -88,7 +108,7 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
88108
emit(HeadlinesFeedLoading()); // Show loading indicator
89109
try {
90110
// Fetch the first page with no filters
91-
final response = await _headlinesRepository.getHeadlines(
111+
final response = await _headlinesRepository.readAll(
92112
limit: _headlinesFetchLimit,
93113
);
94114
emit(
@@ -98,7 +118,7 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
98118
cursor: response.cursor,
99119
),
100120
);
101-
} on HeadlinesFetchException catch (e) {
121+
} on HtHttpException catch (e) {
102122
emit(HeadlinesFeedError(message: e.message));
103123
} catch (e, st) {
104124
// Log the error and stack trace for unexpected errors
@@ -155,12 +175,29 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
155175
}
156176

157177
try {
158-
final response = await _headlinesRepository.getHeadlines(
178+
final response = await _headlinesRepository.readAllByQuery(
179+
{
180+
if (currentFilter.categories?.isNotEmpty ?? false)
181+
'categories':
182+
currentFilter.categories!
183+
.whereType<Category>()
184+
.map((c) => c.id)
185+
.toList(),
186+
if (currentFilter.sources?.isNotEmpty ?? false)
187+
'sources':
188+
currentFilter.sources!
189+
.whereType<Source>()
190+
.map((s) => s.id)
191+
.toList(),
192+
if (currentFilter.eventCountries?.isNotEmpty ?? false)
193+
'eventCountries':
194+
currentFilter.eventCountries!
195+
.whereType<Country>()
196+
.map((c) => c.isoCode)
197+
.toList(),
198+
},
159199
limit: _headlinesFetchLimit,
160200
startAfterId: currentCursor, // Use determined cursor
161-
categories: currentFilter.categories,
162-
sources: currentFilter.sources,
163-
eventCountries: currentFilter.eventCountries,
164201
);
165202
emit(
166203
HeadlinesFeedLoaded(
@@ -172,7 +209,7 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
172209
filter: currentFilter, // Preserve the filter
173210
),
174211
);
175-
} on HeadlinesFetchException catch (e) {
212+
} on HtHttpException catch (e) {
176213
emit(HeadlinesFeedError(message: e.message));
177214
} catch (e, st) {
178215
print('Unexpected error in _onHeadlinesFeedFetchRequested: $e\n$st');
@@ -198,12 +235,26 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
198235

199236
try {
200237
// Fetch the first page using the current filter
201-
final response = await _headlinesRepository.getHeadlines(
202-
limit: _headlinesFetchLimit,
203-
categories: currentFilter.categories,
204-
sources: currentFilter.sources,
205-
eventCountries: currentFilter.eventCountries,
206-
);
238+
final response = await _headlinesRepository.readAllByQuery({
239+
if (currentFilter.categories?.isNotEmpty ?? false)
240+
'categories':
241+
currentFilter.categories!
242+
.whereType<Category>()
243+
.map((c) => c.id)
244+
.toList(),
245+
if (currentFilter.sources?.isNotEmpty ?? false)
246+
'sources':
247+
currentFilter.sources!
248+
.whereType<Source>()
249+
.map((s) => s.id)
250+
.toList(),
251+
if (currentFilter.eventCountries?.isNotEmpty ?? false)
252+
'eventCountries':
253+
currentFilter.eventCountries!
254+
.whereType<Country>()
255+
.map((c) => c.isoCode)
256+
.toList(),
257+
}, limit: _headlinesFetchLimit,);
207258
emit(
208259
HeadlinesFeedLoaded(
209260
headlines: response.items, // Replace headlines on refresh
@@ -212,7 +263,7 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
212263
filter: currentFilter, // Preserve the filter
213264
),
214265
);
215-
} on HeadlinesFetchException catch (e) {
266+
} on HtHttpException catch (e) {
216267
emit(HeadlinesFeedError(message: e.message));
217268
} catch (e, st) {
218269
print('Unexpected error in _onHeadlinesFeedRefreshRequested: $e\n$st');

0 commit comments

Comments
 (0)