Skip to content

Commit 065b4e5

Browse files
authored
Merge pull request #79 from flutter-news-app-full-source-code/fix-headlines-undo-delete-feature
Fix headlines undo delete feature
2 parents 71dc7fa + f46afd5 commit 065b4e5

26 files changed

+523
-158
lines changed

lib/app/bloc/app_bloc.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
135135
unawaited(_authenticationRepository.signOut());
136136
emit(
137137
state.copyWith(clearUserAppSettings: true),
138-
); // Clear settings on logout
138+
);
139139
}
140140

141141
@override

lib/app/view/app.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import 'package:flutter_news_app_web_dashboard_full_source_code/content_manageme
1515
import 'package:flutter_news_app_web_dashboard_full_source_code/l10n/app_localizations.dart';
1616
import 'package:flutter_news_app_web_dashboard_full_source_code/overview/bloc/overview_bloc.dart';
1717
import 'package:flutter_news_app_web_dashboard_full_source_code/router/router.dart';
18+
import 'package:flutter_news_app_web_dashboard_full_source_code/shared/services/pending_deletions_service.dart';
1819
import 'package:flutter_news_app_web_dashboard_full_source_code/shared/shared.dart';
1920
import 'package:go_router/go_router.dart';
2021
import 'package:kv_storage_service/kv_storage_service.dart';
@@ -37,6 +38,7 @@ class App extends StatelessWidget {
3738
required DataRepository<LocalAd> localAdsRepository,
3839
required KVStorageService storageService,
3940
required AppEnvironment environment,
41+
required PendingDeletionsService pendingDeletionsService,
4042
super.key,
4143
}) : _authenticationRepository = authenticationRepository,
4244
_headlinesRepository = headlinesRepository,
@@ -50,7 +52,8 @@ class App extends StatelessWidget {
5052
_countriesRepository = countriesRepository,
5153
_languagesRepository = languagesRepository,
5254
_localAdsRepository = localAdsRepository,
53-
_environment = environment;
55+
_environment = environment,
56+
_pendingDeletionsService = pendingDeletionsService;
5457

5558
final AuthRepository _authenticationRepository;
5659
final DataRepository<Headline> _headlinesRepository;
@@ -67,6 +70,9 @@ class App extends StatelessWidget {
6770
final KVStorageService _kvStorageService;
6871
final AppEnvironment _environment;
6972

73+
/// The service for managing pending deletions with an undo period.
74+
final PendingDeletionsService _pendingDeletionsService;
75+
7076
@override
7177
Widget build(BuildContext context) {
7278
return MultiRepositoryProvider(
@@ -86,6 +92,9 @@ class App extends StatelessWidget {
8692
RepositoryProvider(
8793
create: (context) => const ThrottledFetchingService(),
8894
),
95+
RepositoryProvider.value(
96+
value: _pendingDeletionsService,
97+
),
8998
],
9099
child: MultiBlocProvider(
91100
providers: [

lib/app_configuration/view/app_configuration_page.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ class _AppConfigurationPageState extends State<AppConfigurationPage>
174174
icon: Icons.settings_applications_outlined,
175175
headline: l10n.appConfigurationPageTitle,
176176
subheadline: l10n.loadAppSettingsSubheadline,
177-
); // Fallback
177+
);
178178
},
179179
),
180180
bottomNavigationBar: _buildBottomAppBar(context),

lib/app_configuration/view/tabs/advertisements_configuration_tab.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class _AdvertisementsConfigurationTabState
7979
}
8080
: null,
8181
initiallyExpanded: expandedIndex == tileIndex && adConfig.enabled,
82-
enabled: adConfig.enabled, // Disable the tile itself
82+
enabled: adConfig.enabled,
8383
children: [
8484
AdPlatformConfigForm(
8585
remoteConfig: widget.remoteConfig,
@@ -110,7 +110,7 @@ class _AdvertisementsConfigurationTabState
110110
}
111111
: null,
112112
initiallyExpanded: expandedIndex == tileIndex && adConfig.enabled,
113-
enabled: adConfig.enabled, // Disable the tile itself
113+
enabled: adConfig.enabled,
114114
children: [
115115
FeedAdSettingsForm(
116116
remoteConfig: widget.remoteConfig,
@@ -141,7 +141,7 @@ class _AdvertisementsConfigurationTabState
141141
}
142142
: null,
143143
initiallyExpanded: expandedIndex == tileIndex && adConfig.enabled,
144-
enabled: adConfig.enabled, // Disable the tile itself
144+
enabled: adConfig.enabled,
145145
children: [
146146
ArticleAdSettingsForm(
147147
remoteConfig: widget.remoteConfig,
@@ -172,7 +172,7 @@ class _AdvertisementsConfigurationTabState
172172
}
173173
: null,
174174
initiallyExpanded: expandedIndex == tileIndex && adConfig.enabled,
175-
enabled: adConfig.enabled, // Disable the tile itself
175+
enabled: adConfig.enabled,
176176
children: [
177177
InterstitialAdSettingsForm(
178178
remoteConfig: widget.remoteConfig,

lib/app_configuration/widgets/ad_platform_config_form.dart

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -219,12 +219,11 @@ class _AdPlatformConfigFormState extends State<AdPlatformConfigForm> {
219219
ExpansionTile(
220220
title: Text(l10n.primaryAdPlatformTitle),
221221
childrenPadding: const EdgeInsetsDirectional.only(
222-
start: AppSpacing.lg, // Adjusted padding for hierarchy
222+
start: AppSpacing.lg,
223223
top: AppSpacing.md,
224224
bottom: AppSpacing.md,
225225
),
226-
expandedCrossAxisAlignment:
227-
CrossAxisAlignment.start, // Align content to start
226+
expandedCrossAxisAlignment: CrossAxisAlignment.start,
228227
children: [
229228
Text(
230229
l10n.primaryAdPlatformDescription,
@@ -233,7 +232,7 @@ class _AdPlatformConfigFormState extends State<AdPlatformConfigForm> {
233232
context,
234233
).colorScheme.onSurface.withOpacity(0.7),
235234
),
236-
textAlign: TextAlign.start, // Ensure text aligns to start
235+
textAlign: TextAlign.start,
237236
),
238237
const SizedBox(height: AppSpacing.lg),
239238
Align(
@@ -246,10 +245,7 @@ class _AdPlatformConfigFormState extends State<AdPlatformConfigForm> {
246245
),
247246
segments: AdPlatformType.values
248247
.where(
249-
(type) =>
250-
type !=
251-
AdPlatformType
252-
.demo, // Ignore demo ad platform for dashboard
248+
(type) => type != AdPlatformType.demo,
253249
)
254250
.map(
255251
(type) => ButtonSegment<AdPlatformType>(
@@ -281,12 +277,11 @@ class _AdPlatformConfigFormState extends State<AdPlatformConfigForm> {
281277
ExpansionTile(
282278
title: Text(l10n.adUnitIdentifiersTitle),
283279
childrenPadding: const EdgeInsetsDirectional.only(
284-
start: AppSpacing.lg, // Adjusted padding for hierarchy
280+
start: AppSpacing.lg,
285281
top: AppSpacing.md,
286282
bottom: AppSpacing.md,
287283
),
288-
expandedCrossAxisAlignment:
289-
CrossAxisAlignment.start, // Align content to start
284+
expandedCrossAxisAlignment: CrossAxisAlignment.start,
290285
children: [
291286
Text(
292287
l10n.adUnitIdentifiersDescription,
@@ -295,7 +290,7 @@ class _AdPlatformConfigFormState extends State<AdPlatformConfigForm> {
295290
context,
296291
).colorScheme.onSurface.withOpacity(0.7),
297292
),
298-
textAlign: TextAlign.start, // Ensure text aligns to start
293+
textAlign: TextAlign.start,
299294
),
300295
const SizedBox(height: AppSpacing.lg),
301296
_buildAdUnitIdentifierFields(
@@ -313,12 +308,11 @@ class _AdPlatformConfigFormState extends State<AdPlatformConfigForm> {
313308
ExpansionTile(
314309
title: Text(l10n.localAdManagementTitle),
315310
childrenPadding: const EdgeInsetsDirectional.only(
316-
start: AppSpacing.lg, // Adjusted padding for hierarchy
311+
start: AppSpacing.lg,
317312
top: AppSpacing.md,
318313
bottom: AppSpacing.md,
319314
),
320-
expandedCrossAxisAlignment:
321-
CrossAxisAlignment.start, // Align content to start
315+
expandedCrossAxisAlignment: CrossAxisAlignment.start,
322316
children: [
323317
Text(
324318
l10n.localAdManagementDescription,
@@ -327,7 +321,7 @@ class _AdPlatformConfigFormState extends State<AdPlatformConfigForm> {
327321
context,
328322
).colorScheme.onSurface.withOpacity(0.7),
329323
),
330-
textAlign: TextAlign.start, // Ensure text aligns to start
324+
textAlign: TextAlign.start,
331325
),
332326
const SizedBox(height: AppSpacing.lg),
333327
Center(

lib/app_configuration/widgets/app_config_form_fields.dart

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ class AppConfigIntField extends StatelessWidget {
3737
return Padding(
3838
padding: const EdgeInsets.symmetric(vertical: AppSpacing.sm),
3939
child: Column(
40-
crossAxisAlignment:
41-
CrossAxisAlignment.start, // Ensure alignment to start
40+
crossAxisAlignment: CrossAxisAlignment.start,
4241
children: [
4342
Text(label, style: theme.textTheme.titleMedium),
4443
const SizedBox(height: AppSpacing.xs),
@@ -47,7 +46,7 @@ class AppConfigIntField extends StatelessWidget {
4746
style: theme.textTheme.bodySmall?.copyWith(
4847
color: theme.colorScheme.onSurface.withOpacity(0.7),
4948
),
50-
textAlign: TextAlign.start, // Ensure text aligns to start
49+
textAlign: TextAlign.start,
5150
),
5251
const SizedBox(height: AppSpacing.xs),
5352
TextFormField(
@@ -107,8 +106,7 @@ class AppConfigTextField extends StatelessWidget {
107106
return Padding(
108107
padding: const EdgeInsets.symmetric(vertical: AppSpacing.sm),
109108
child: Column(
110-
crossAxisAlignment:
111-
CrossAxisAlignment.start, // Ensure alignment to start
109+
crossAxisAlignment: CrossAxisAlignment.start,
112110
children: [
113111
Text(label, style: theme.textTheme.titleMedium),
114112
const SizedBox(height: AppSpacing.xs),
@@ -117,7 +115,7 @@ class AppConfigTextField extends StatelessWidget {
117115
style: theme.textTheme.bodySmall?.copyWith(
118116
color: theme.colorScheme.onSurface.withOpacity(0.7),
119117
),
120-
textAlign: TextAlign.start, // Ensure text aligns to start
118+
textAlign: TextAlign.start,
121119
),
122120
const SizedBox(height: AppSpacing.xs),
123121
TextFormField(

lib/app_configuration/widgets/feed_ad_settings_form.dart

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -145,19 +145,18 @@ class _FeedAdSettingsFormState extends State<FeedAdSettingsForm>
145145
ExpansionTile(
146146
title: Text(l10n.feedAdTypeSelectionTitle),
147147
childrenPadding: const EdgeInsetsDirectional.only(
148-
start: AppSpacing.lg, // Adjusted padding for hierarchy
148+
start: AppSpacing.lg,
149149
top: AppSpacing.md,
150150
bottom: AppSpacing.md,
151151
),
152-
expandedCrossAxisAlignment:
153-
CrossAxisAlignment.start, // Align content to start
152+
expandedCrossAxisAlignment: CrossAxisAlignment.start,
154153
children: [
155154
Text(
156155
l10n.feedAdTypeSelectionDescription,
157156
style: Theme.of(context).textTheme.bodySmall?.copyWith(
158157
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.7),
159158
),
160-
textAlign: TextAlign.start, // Ensure text aligns to start
159+
textAlign: TextAlign.start,
161160
),
162161
const SizedBox(height: AppSpacing.lg),
163162
Align(
@@ -199,19 +198,18 @@ class _FeedAdSettingsFormState extends State<FeedAdSettingsForm>
199198
ExpansionTile(
200199
title: Text(l10n.userRoleFrequencySettingsTitle),
201200
childrenPadding: const EdgeInsetsDirectional.only(
202-
start: AppSpacing.lg, // Adjusted padding for hierarchy
201+
start: AppSpacing.lg,
203202
top: AppSpacing.md,
204203
bottom: AppSpacing.md,
205204
),
206-
expandedCrossAxisAlignment:
207-
CrossAxisAlignment.start, // Align content to start
205+
expandedCrossAxisAlignment: CrossAxisAlignment.start,
208206
children: [
209207
Text(
210208
l10n.userRoleFrequencySettingsDescription,
211209
style: Theme.of(context).textTheme.bodySmall?.copyWith(
212210
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.7),
213211
),
214-
textAlign: TextAlign.start, // Ensure text aligns to start
212+
textAlign: TextAlign.start,
215213
),
216214
const SizedBox(height: AppSpacing.lg),
217215
// Replaced SegmentedButton with TabBar for role selection
@@ -232,7 +230,7 @@ class _FeedAdSettingsFormState extends State<FeedAdSettingsForm>
232230
const SizedBox(height: AppSpacing.lg),
233231
// TabBarView to display role-specific fields
234232
SizedBox(
235-
height: 250, // Fixed height for TabBarView within a ListView
233+
height: 250,
236234
child: TabBarView(
237235
controller: _tabController,
238236
children: AppUserRole.values

lib/app_configuration/widgets/feed_decorator_form.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ class _FeedDecoratorFormState extends State<FeedDecoratorForm>
184184
const SizedBox(height: AppSpacing.lg),
185185
// TabBarView to display role-specific fields
186186
SizedBox(
187-
height: 250, // Fixed height for TabBarView within a ListView
187+
height: 250,
188188
child: TabBarView(
189189
controller: _tabController,
190190
children: AppUserRole.values

lib/app_configuration/widgets/interstitial_ad_settings_form.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
163163
),
164164
const SizedBox(height: AppSpacing.lg),
165165
SizedBox(
166-
height: 250, // Fixed height for TabBarView within a ListView
166+
height: 250,
167167
child: TabBarView(
168168
controller: _tabController,
169169
children: AppUserRole.values

lib/app_configuration/widgets/user_preference_limits_form.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ class _UserPreferenceLimitsFormState extends State<UserPreferenceLimitsForm>
167167
const SizedBox(height: AppSpacing.lg),
168168
// TabBarView to display role-specific fields
169169
SizedBox(
170-
height: 250, // Fixed height for TabBarView within a ListView
170+
height: 250,
171171
child: TabBarView(
172172
controller: _tabController,
173173
children: AppUserRole.values

0 commit comments

Comments
 (0)