Skip to content

Commit e89e3cc

Browse files
authored
Merge pull request #128 from flutter-news-app-full-source-code/refactor/filter-active-content-status
Refactor/filter active content status
2 parents f6636d1 + 9b90964 commit e89e3cc

File tree

17 files changed

+63
-9
lines changed

17 files changed

+63
-9
lines changed

lib/account/bloc/available_sources_bloc.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ class AvailableSourcesBloc
3333
emit(state.copyWith(status: AvailableSourcesStatus.loading));
3434
try {
3535
// TODO(fulleni): Add pagination if necessary for very large datasets.
36+
// Filter to fetch only active sources.
3637
final response = await _sourcesRepository.readAll(
38+
filter: {'status': ContentStatus.active.name},
3739
sort: [const SortOption('name', SortOrder.asc)],
3840
);
3941
emit(

lib/account/bloc/available_topics_bloc.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ class AvailableTopicsBloc
2929
emit(state.copyWith(status: AvailableTopicsStatus.loading));
3030
try {
3131
// TODO(fulleni): Add pagination if necessary for very large datasets.
32+
// Filter to fetch only active topics.
3233
final response = await _topicsRepository.readAll(
34+
filter: {'status': ContentStatus.active.name},
3335
sort: [const SortOption('name', SortOrder.asc)],
3436
);
3537
emit(

lib/ads/inline_ad_cache_service.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class InlineAdCacheService {
109109
final ad = _cache[id];
110110
if (ad != null) {
111111
_logger.info('Removing and disposing inline ad with ID "$id".');
112+
// Delegate disposal to AdService
112113
_adService.disposeAd(ad);
113114
_cache.remove(id);
114115
} else {
@@ -126,8 +127,12 @@ class InlineAdCacheService {
126127
'Clearing all cached inline ads and disposing their resources.',
127128
);
128129
for (final ad in _cache.values.whereType<InlineAd>()) {
130+
131+
// Delegate disposal to AdService
129132
_adService.disposeAd(ad);
130133
}
134+
135+
// Ensure cache is empty after disposal attempts.
131136
_cache.clear();
132137
_logger.info('All cached inline ads cleared.');
133138
}

lib/ads/interstitial_ad_manager.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ class InterstitialAdManager {
176176
if (requiredTransitions > 0 && _transitionCount >= requiredTransitions) {
177177
_logger.info('Transition count meets threshold. Attempting to show ad.');
178178
await _showAd();
179+
// Reset counter after showing (or attempting to show)
179180
_transitionCount = 0;
180181
} else {
181182
_logger.info(
@@ -201,6 +202,7 @@ class InterstitialAdManager {
201202
}
202203

203204
final adToShow = _preloadedAd!;
205+
// Clear the pre-loaded ad before showing
204206
_preloadedAd = null;
205207

206208
try {
@@ -234,6 +236,8 @@ class InterstitialAdManager {
234236
} finally {
235237
// After the ad is shown or fails to show, dispose of it and
236238
// start pre-loading the next one for the next opportunity.
239+
240+
// Ensure the ad object is disposed
237241
_disposePreloadedAd();
238242
unawaited(_maybePreloadAd(_appBloc.state));
239243
}
@@ -272,6 +276,7 @@ class InterstitialAdManager {
272276
// Await the result of showDialog, which completes when the dialog is popped.
273277
await showDialog<void>(
274278
context: context,
279+
// Prevent dismissing by tapping outside
275280
barrierDismissible: false,
276281
builder: (_) => LocalInterstitialAdDialog(
277282
localInterstitialAd: ad.adObject as LocalInterstitialAd,
@@ -283,6 +288,7 @@ class InterstitialAdManager {
283288
// Await the result of showDialog, which completes when the dialog is popped.
284289
await showDialog<void>(
285290
context: context,
291+
// Prevent dismissing by tapping outside
286292
barrierDismissible: false,
287293
builder: (_) => const DemoInterstitialAdDialog(),
288294
);

lib/ads/widgets/feed_ad_loader_widget.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ class _FeedAdLoaderWidgetState extends State<FeedAdLoaderWidget> {
9898
// completed. This prevents a race condition if a new load is triggered
9999
// while an old one is still in progress.
100100
if (_loadAdCompleter != null && !_loadAdCompleter!.isCompleted) {
101+
// Complete normally to prevent crashes
101102
_loadAdCompleter!.complete();
102103
}
103104
_loadAdCompleter = null;
@@ -125,6 +126,7 @@ class _FeedAdLoaderWidgetState extends State<FeedAdLoaderWidget> {
125126
// This prevents `setState()` calls on a disposed widget.
126127
// Ensure the completer is not already completed before attempting to complete it.
127128
if (_loadAdCompleter != null && !_loadAdCompleter!.isCompleted) {
129+
// Complete normally to prevent crashes
128130
_loadAdCompleter!.complete();
129131
}
130132
_loadAdCompleter = null;
@@ -214,7 +216,6 @@ class _FeedAdLoaderWidgetState extends State<FeedAdLoaderWidget> {
214216
adType: widget.adPlaceholder.adType,
215217
adThemeStyle: widget.adThemeStyle,
216218
headlineImageStyle: headlineImageStyle,
217-
userRole: userRole,
218219
);
219220

220221
if (loadedAd != null) {

lib/ads/widgets/in_article_ad_loader_widget.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class _InArticleAdLoaderWidgetState extends State<InArticleAdLoaderWidget> {
9999
_adCacheService.removeAndDisposeAd(oldCacheKey);
100100

101101
if (_loadAdCompleter != null && !_loadAdCompleter!.isCompleted) {
102+
// Complete normally to prevent crashes
102103
_loadAdCompleter!.complete();
103104
}
104105
_loadAdCompleter = null;
@@ -121,6 +122,7 @@ class _InArticleAdLoaderWidgetState extends State<InArticleAdLoaderWidget> {
121122
_adCacheService.removeAndDisposeAd(cacheKey);
122123

123124
if (_loadAdCompleter != null && !_loadAdCompleter!.isCompleted) {
125+
// Complete normally to prevent crashes
124126
_loadAdCompleter!.complete();
125127
}
126128
_loadAdCompleter = null;

lib/app/bloc/app_bloc.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
355355
),
356356
),
357357
);
358+
// Stop further processing if initialization failed critically.
358359
return;
359360
}
360361
}
@@ -392,6 +393,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
392393
),
393394
),
394395
);
396+
// Stop further processing if migration failed critically.
395397
return;
396398
}
397399
}

lib/app/config/app_config.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,16 @@ class AppConfig {
1414
baseUrl: 'http://api.yourproductiondomain.com',
1515
);
1616

17-
factory AppConfig.demo() =>
18-
const AppConfig(environment: AppEnvironment.demo, baseUrl: '');
17+
factory AppConfig.demo() => const AppConfig(
18+
environment: AppEnvironment.demo,
19+
// No API access needed for in-memory demo
20+
baseUrl: '',
21+
);
1922

2023
factory AppConfig.development() => const AppConfig(
2124
// For local Dart Frog API
2225
environment: AppEnvironment.development,
26+
// Default Dart Frog local URL
2327
baseUrl: 'http://localhost:8080',
2428
);
2529

lib/app/view/app.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class App extends StatelessWidget {
149149
appBloc: context.read<AppBloc>(),
150150
adService: context.read<AdService>(),
151151
),
152+
// Ensure it's created immediately
152153
lazy: false,
153154
),
154155
],

lib/entity_details/bloc/entity_details_bloc.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ class EntityDetailsBloc extends Bloc<EntityDetailsEvent, EntityDetailsState> {
102102
filter['eventCountry.id'] = (entityToLoad as Country).id;
103103
}
104104

105+
// Always filter for active headlines.
106+
filter['status'] = ContentStatus.active.name;
107+
105108
final headlineResponse = await _headlinesRepository.readAll(
106109
filter: filter,
107110
pagination: const PaginationOptions(limit: _headlinesLimit),
@@ -270,6 +273,9 @@ class EntityDetailsBloc extends Bloc<EntityDetailsEvent, EntityDetailsState> {
270273
filter['eventCountry.id'] = (state.entity! as Country).id;
271274
}
272275

276+
// Always filter for active headlines.
277+
filter['status'] = ContentStatus.active.name;
278+
273279
final headlineResponse = await _headlinesRepository.readAll(
274280
filter: filter,
275281
pagination: PaginationOptions(

0 commit comments

Comments
 (0)