Skip to content

Commit cfca236

Browse files
committed
feat(search): Inject feed items in search results
- Inject feed items into search results - Added AppBloc and FeedInjectorService - Updated state management for feed items
1 parent 2ffd617 commit cfca236

File tree

1 file changed

+96
-45
lines changed

1 file changed

+96
-45
lines changed

lib/headlines-search/bloc/headlines_search_bloc.dart

Lines changed: 96 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import 'package:bloc/bloc.dart';
22
import 'package:bloc_concurrency/bloc_concurrency.dart';
33
import 'package:equatable/equatable.dart';
4-
import 'package:ht_data_repository/ht_data_repository.dart'; // Generic Data Repository
5-
import 'package:ht_main/headlines-search/models/search_model_type.dart'; // Import SearchModelType
6-
import 'package:ht_shared/ht_shared.dart' show Category, Headline, HtHttpException, PaginatedResponse, Source; // Shared models
4+
import 'package:ht_data_repository/ht_data_repository.dart';
5+
import 'package:ht_main/app/bloc/app_bloc.dart'; // Added
6+
import 'package:ht_main/headlines-search/models/search_model_type.dart';
7+
import 'package:ht_main/shared/services/feed_injector_service.dart'; // Added
8+
import 'package:ht_shared/ht_shared.dart'; // Updated for FeedItem, AppConfig, User etc.
79

810
part 'headlines_search_event.dart';
911
part 'headlines_search_state.dart';
@@ -14,12 +16,14 @@ class HeadlinesSearchBloc
1416
required HtDataRepository<Headline> headlinesRepository,
1517
required HtDataRepository<Category> categoryRepository,
1618
required HtDataRepository<Source> sourceRepository,
17-
// required HtDataRepository<Country> countryRepository, // Removed
18-
}) : _headlinesRepository = headlinesRepository,
19-
_categoryRepository = categoryRepository,
20-
_sourceRepository = sourceRepository,
21-
// _countryRepository = countryRepository, // Removed
22-
super(const HeadlinesSearchInitial()) {
19+
required AppBloc appBloc, // Added
20+
required FeedInjectorService feedInjectorService, // Added
21+
}) : _headlinesRepository = headlinesRepository,
22+
_categoryRepository = categoryRepository,
23+
_sourceRepository = sourceRepository,
24+
_appBloc = appBloc, // Added
25+
_feedInjectorService = feedInjectorService, // Added
26+
super(const HeadlinesSearchInitial()) {
2327
on<HeadlinesSearchModelTypeChanged>(_onHeadlinesSearchModelTypeChanged);
2428
on<HeadlinesSearchFetchRequested>(
2529
_onSearchFetchRequested,
@@ -30,7 +34,8 @@ class HeadlinesSearchBloc
3034
final HtDataRepository<Headline> _headlinesRepository;
3135
final HtDataRepository<Category> _categoryRepository;
3236
final HtDataRepository<Source> _sourceRepository;
33-
// final HtDataRepository<Country> _countryRepository; // Removed
37+
final AppBloc _appBloc; // Added
38+
final FeedInjectorService _feedInjectorService; // Added
3439
static const _limit = 10;
3540

3641
Future<void> _onHeadlinesSearchModelTypeChanged(
@@ -61,7 +66,7 @@ class HeadlinesSearchBloc
6166
if (searchTerm.isEmpty) {
6267
emit(
6368
HeadlinesSearchSuccess(
64-
results: const [],
69+
items: const [], // Changed
6570
hasMore: false,
6671
lastSearchTerm: '',
6772
selectedModelType: modelType,
@@ -86,32 +91,57 @@ class HeadlinesSearchBloc
8691
limit: _limit,
8792
startAfterId: successState.cursor,
8893
);
94+
// Cast to List<Headline> for the injector
95+
final headlines = response.items.cast<Headline>();
96+
final currentUser = _appBloc.state.user;
97+
final appConfig = _appBloc.state.appConfig;
98+
if (appConfig == null) {
99+
emit(successState.copyWith(errorMessage: 'App configuration not available for pagination.'));
100+
return;
101+
}
102+
final injectedItems = _feedInjectorService.injectItems(
103+
headlines: headlines,
104+
user: currentUser,
105+
appConfig: appConfig,
106+
currentFeedItemCount: successState.items.length,
107+
);
108+
emit(
109+
successState.copyWith(
110+
items: List.of(successState.items)..addAll(injectedItems),
111+
hasMore: response.hasMore, // hasMore from original headline fetch
112+
cursor: response.cursor,
113+
),
114+
);
115+
break; // Added break
89116
case SearchModelType.category:
90117
response = await _categoryRepository.readAllByQuery(
91118
{'q': searchTerm, 'model': modelType.toJson()},
92119
limit: _limit,
93120
startAfterId: successState.cursor,
94121
);
122+
emit(
123+
successState.copyWith(
124+
items: List.of(successState.items)..addAll(response.items.cast<FeedItem>()),
125+
hasMore: response.hasMore,
126+
cursor: response.cursor,
127+
),
128+
);
129+
break; // Added break
95130
case SearchModelType.source:
96131
response = await _sourceRepository.readAllByQuery(
97132
{'q': searchTerm, 'model': modelType.toJson()},
98133
limit: _limit,
99134
startAfterId: successState.cursor,
100135
);
101-
// case SearchModelType.country: // Removed
102-
// response = await _countryRepository.readAllByQuery(
103-
// {'q': searchTerm, 'model': modelType.toJson()},
104-
// limit: _limit,
105-
// startAfterId: successState.cursor,
106-
// );
136+
emit(
137+
successState.copyWith(
138+
items: List.of(successState.items)..addAll(response.items.cast<FeedItem>()),
139+
hasMore: response.hasMore,
140+
cursor: response.cursor,
141+
),
142+
);
143+
break; // Added break
107144
}
108-
emit(
109-
successState.copyWith(
110-
results: List.of(successState.results)..addAll(response.items),
111-
hasMore: response.hasMore,
112-
cursor: response.cursor,
113-
),
114-
);
115145
} on HtHttpException catch (e) {
116146
emit(successState.copyWith(errorMessage: e.message));
117147
} catch (e, st) {
@@ -132,34 +162,55 @@ class HeadlinesSearchBloc
132162
),
133163
);
134164
try {
135-
PaginatedResponse<dynamic> response;
165+
PaginatedResponse<dynamic> rawResponse;
166+
List<FeedItem> processedItems;
167+
136168
switch (modelType) {
137169
case SearchModelType.headline:
138-
response = await _headlinesRepository.readAllByQuery({
139-
'q': searchTerm,
140-
'model': modelType.toJson(),
141-
}, limit: _limit,);
170+
rawResponse = await _headlinesRepository.readAllByQuery(
171+
{'q': searchTerm, 'model': modelType.toJson()},
172+
limit: _limit,
173+
);
174+
final headlines = rawResponse.items.cast<Headline>();
175+
final currentUser = _appBloc.state.user;
176+
final appConfig = _appBloc.state.appConfig;
177+
if (appConfig == null) {
178+
emit(
179+
HeadlinesSearchFailure(
180+
errorMessage: 'App configuration not available.',
181+
lastSearchTerm: searchTerm,
182+
selectedModelType: modelType,
183+
),
184+
);
185+
return;
186+
}
187+
processedItems = _feedInjectorService.injectItems(
188+
headlines: headlines,
189+
user: currentUser,
190+
appConfig: appConfig,
191+
currentFeedItemCount: 0,
192+
);
193+
break;
142194
case SearchModelType.category:
143-
response = await _categoryRepository.readAllByQuery({
144-
'q': searchTerm,
145-
'model': modelType.toJson(),
146-
}, limit: _limit,);
195+
rawResponse = await _categoryRepository.readAllByQuery(
196+
{'q': searchTerm, 'model': modelType.toJson()},
197+
limit: _limit,
198+
);
199+
processedItems = rawResponse.items.cast<FeedItem>();
200+
break;
147201
case SearchModelType.source:
148-
response = await _sourceRepository.readAllByQuery({
149-
'q': searchTerm,
150-
'model': modelType.toJson(),
151-
}, limit: _limit,);
152-
// case SearchModelType.country: // Removed
153-
// response = await _countryRepository.readAllByQuery({
154-
// 'q': searchTerm,
155-
// 'model': modelType.toJson(),
156-
// }, limit: _limit,);
202+
rawResponse = await _sourceRepository.readAllByQuery(
203+
{'q': searchTerm, 'model': modelType.toJson()},
204+
limit: _limit,
205+
);
206+
processedItems = rawResponse.items.cast<FeedItem>();
207+
break;
157208
}
158209
emit(
159210
HeadlinesSearchSuccess(
160-
results: response.items,
161-
hasMore: response.hasMore,
162-
cursor: response.cursor,
211+
items: processedItems, // Changed
212+
hasMore: rawResponse.hasMore,
213+
cursor: rawResponse.cursor,
163214
lastSearchTerm: searchTerm,
164215
selectedModelType: modelType,
165216
),

0 commit comments

Comments
 (0)