Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Refactor/ad config UI role based #85

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
fulleni merged 13 commits into main from refactor/ad-config-ui-role-based
Sep 23, 2025
Merged
Changes from 1 commit
Commits
Show all changes
13 commits
Select commit Hold shift + click to select a range
965c0ef
chore(deps): update core.git to d7d9afa3
fulleni Sep 23, 2025
eabfc06
refactor(ad_config_form): simplify AdConfigForm widget
fulleni Sep 23, 2025
904c0bb
feat(app_configuration): implement role-based in-article ad slot visi...
fulleni Sep 23, 2025
f9f9cd9
refactor(app_configuration): update feed ad settings form logic
fulleni Sep 23, 2025
f0893b0
refactor(ad): improve interstitial ad config management
fulleni Sep 23, 2025
0ecbf73
feat(localization): add translations for in-article ads settings
fulleni Sep 23, 2025
1f8048b
refactor(app_configuration): improve in-article ad settings UI consis...
fulleni Sep 23, 2025
ffc0c65
refactor(app_configuration): improve ad settings UI and functionality
fulleni Sep 23, 2025
7413d25
refactor(ad): improve UI consistency and code formatting in interstit...
fulleni Sep 23, 2025
d32724b
refactor(ad): revert in-article ad settings UI changes
fulleni Sep 23, 2025
36aa7b6
feat(ad-settings): remove automatic ad disabling for premium users
fulleni Sep 23, 2025
b0514b1
feat(ad-config): remove auto-disable ads for premium users
fulleni Sep 23, 2025
fdfe26f
style: format
fulleni Sep 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(app_configuration): implement role-based in-article ad slot visi...
...bility
- Add TabBar for selecting user roles
- Implement role-specific configuration fields for in-article ad slots
- Use CheckboxListTile to enable/disable ad slots per role
- Update state management with TabController
- Refactor UI layout for better readability
  • Loading branch information
fulleni committed Sep 23, 2025
commit 904c0bb492913cb34e6a245683f9718f218b26cd
118 changes: 96 additions & 22 deletions lib/app_configuration/widgets/article_ad_settings_form.dart
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import 'package:core/core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_news_app_web_dashboard_full_source_code/l10n/app_localizations.dart';
import 'package:flutter_news_app_web_dashboard_full_source_code/l10n/l10n.dart';
import 'package:flutter_news_app_web_dashboard_full_source_code/shared/extensions/banner_ad_shape_l10n.dart';
import 'package:flutter_news_app_web_dashboard_full_source_code/shared/extensions/in_article_ad_slot_type_l10n.dart';
import 'package:flutter_news_app_web_dashboard_full_source_code/shared/extensions/app_user_role_l10n.dart';
import 'package:ui_kit/ui_kit.dart';

/// {@template article_ad_settings_form}
Expand All @@ -28,14 +30,28 @@ class ArticleAdSettingsForm extends StatefulWidget {

class _ArticleAdSettingsFormState extends State<ArticleAdSettingsForm>
with SingleTickerProviderStateMixin {
late TabController _tabController;

@override
void initState() {
super.initState();
_tabController = TabController(
length: AppUserRole.values.length,
vsync: this,
);
}

@override
void didUpdateWidget(covariant ArticleAdSettingsForm oldWidget) {
super.didUpdateWidget(oldWidget);
// No specific controller updates needed here as the UI rebuilds based on
// the remoteConfig directly.
}

@override
void dispose() {
_tabController.dispose();
super.dispose();
}

@override
Expand Down Expand Up @@ -134,34 +150,92 @@ class _ArticleAdSettingsFormState extends State<ArticleAdSettingsForm>
textAlign: TextAlign.start,
),
const SizedBox(height: AppSpacing.lg),
...articleAdConfig.inArticleAdSlotConfigurations.map(
(slotConfig) => SwitchListTile(
title: Text(slotConfig.slotType.l10n(context)),
value: slotConfig.enabled,
onChanged: (value) {
final updatedSlots = articleAdConfig
.inArticleAdSlotConfigurations
.map(
(e) => e.slotType == slotConfig.slotType
? e.copyWith(enabled: value)
: e,
)
.toList();
widget.onConfigChanged(
widget.remoteConfig.copyWith(
adConfig: adConfig.copyWith(
articleAdConfiguration: articleAdConfig.copyWith(
inArticleAdSlotConfigurations: updatedSlots,
),
Align(
alignment: AlignmentDirectional.centerStart,
child: SizedBox(
height: kTextTabBarHeight,
child: TabBar(
controller: _tabController,
tabAlignment: TabAlignment.start,
isScrollable: true,
tabs: AppUserRole.values
.map((role) => Tab(text: role.l10n(context)))
.toList(),
),
),
),
const SizedBox(height: AppSpacing.lg),
SizedBox(
height: 250,
child: TabBarView(
controller: _tabController,
children: AppUserRole.values
.map(
(role) => _buildRoleSpecificFields(
context,
l10n,
role,
articleAdConfig,
),
),
);
},
)
.toList(),
),
),
],
),
],
);
}

/// Builds role-specific configuration fields for in-article ad slots.
///
/// This widget displays checkboxes for each [InArticleAdSlotType] for a
/// given [AppUserRole], allowing to enable/disable specific ad slots.
Widget _buildRoleSpecificFields(
BuildContext context,
AppLocalizations l10n,
AppUserRole role,
ArticleAdConfiguration config,
) {
final roleSlots = config.visibleTo[role];
final isEnabled = role != AppUserRole.premiumUser;

return Column(
children: [
// Checkbox for each InArticleAdSlotType
for (final slotType in InArticleAdSlotType.values)
CheckboxListTile(
title: Text(slotType.l10n(context)),
value: (roleSlots != null && roleSlots[slotType] == true) &&
isEnabled,
onChanged: isEnabled
? (value) {
final newRoleSlots =
Map<InArticleAdSlotType, bool>.from(roleSlots ?? {});
if (value ?? false) {
newRoleSlots[slotType] = true;
} else {
newRoleSlots.remove(slotType);
}

final newVisibleTo =
Map<AppUserRole, Map<InArticleAdSlotType, bool>>.from(
config.visibleTo,
)..[role] = newRoleSlots;

widget.onConfigChanged(
widget.remoteConfig.copyWith(
adConfig: widget.remoteConfig.adConfig.copyWith(
articleAdConfiguration: config.copyWith(
visibleTo: newVisibleTo,
),
),
),
);
}
: null,
),
],
);
}
}

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /