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(ad-config): remove auto-disable ads for premium users
- Remove _tabController.addListener(_onTabChanged) and related logic
- Remove automatic setting of transitions to 0 for premium users
- Remove isEnabled check from _buildInterstitialRoleSpecificFields
- Update switch label to "Visible to [Role]"
- Remove.enabled parameter from TextFormField
  • Loading branch information
fulleni committed Sep 23, 2025
commit b0514b11bdbb25262568aeccb0387ae1fae7324e
138 changes: 47 additions & 91 deletions lib/app_configuration/widgets/interstitial_ad_settings_form.dart
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
/// Controllers for transitions before showing interstitial ads, mapped by user role.
/// These are used to manage text input for each role's interstitial ad frequency.
late final Map<AppUserRole, TextEditingController>
_transitionsBeforeShowingInterstitialAdsControllers;
_transitionsBeforeShowingInterstitialAdsControllers;

@override
void initState() {
Expand All @@ -45,7 +45,8 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
vsync: this,
);
_initializeControllers();
_tabController.addListener(_onTabChanged);
// Removed _tabController.addListener(_onTabChanged); as automatic disabling
// for premium users is no longer required.
}

/// Initializes text editing controllers for each user role based on current
Expand All @@ -55,19 +56,17 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
widget.remoteConfig.adConfig.interstitialAdConfiguration;
_transitionsBeforeShowingInterstitialAdsControllers = {
for (final role in AppUserRole.values)
role:
TextEditingController(
text: _getTransitionsBeforeInterstitial(
interstitialConfig,
role,
).toString(),
)
..selection = TextSelection.collapsed(
offset: _getTransitionsBeforeInterstitial(
interstitialConfig,
role,
).toString().length,
),
role: TextEditingController(
text: _getTransitionsBeforeInterstitial(
interstitialConfig,
role,
).toString(),
)..selection = TextSelection.collapsed(
offset: _getTransitionsBeforeInterstitial(
interstitialConfig,
role,
).toString().length,
),
};
}

Expand All @@ -87,51 +86,13 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
newInterstitialValue;
_transitionsBeforeShowingInterstitialAdsControllers[role]?.selection =
TextSelection.collapsed(
offset: newInterstitialValue.length,
);
}
}
}

/// Listener for tab changes to enforce business rules, specifically for
/// premium users who should not see ads.
void _onTabChanged() {
if (_tabController.indexIsChanging) return;

final selectedRole = AppUserRole.values[_tabController.index];
if (selectedRole == AppUserRole.premiumUser) {
final adConfig = widget.remoteConfig.adConfig;
final interstitialAdConfig = adConfig.interstitialAdConfiguration;

// If the value for premium is not 0, update the config.
// This enforces the business rule that premium users do not see ads.
final premiumRoleConfig =
interstitialAdConfig.visibleTo[AppUserRole.premiumUser];
if (premiumRoleConfig != null &&
premiumRoleConfig.transitionsBeforeShowingInterstitialAds != 0) {
final updatedVisibleTo =
Map<AppUserRole, InterstitialAdFrequencyConfig>.from(
interstitialAdConfig.visibleTo,
)
..[AppUserRole.premiumUser] = const InterstitialAdFrequencyConfig(
transitionsBeforeShowingInterstitialAds: 0,
);

final updatedInterstitialAdConfig = interstitialAdConfig.copyWith(
visibleTo: updatedVisibleTo,
);

widget.onConfigChanged(
widget.remoteConfig.copyWith(
adConfig: adConfig.copyWith(
interstitialAdConfiguration: updatedInterstitialAdConfig,
),
),
offset: newInterstitialValue.length,
);
}
}
}


@override
void didUpdateWidget(covariant InterstitialAdSettingsForm oldWidget) {
super.didUpdateWidget(oldWidget);
Expand All @@ -144,8 +105,7 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
@override
void dispose() {
_tabController
..removeListener(_onTabChanged)
..dispose();
.dispose();
for (final controller
in _transitionsBeforeShowingInterstitialAdsControllers.values) {
controller.dispose();
Expand Down Expand Up @@ -236,48 +196,44 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
/// Builds role-specific configuration fields for interstitial ad frequency.
///
/// This widget displays an input field for `transitionsBeforeShowingInterstitialAds`
/// for a given [AppUserRole]. Premium users have this field disabled
/// as they should not see ads.
/// for a given [AppUserRole].
Widget _buildInterstitialRoleSpecificFields(
BuildContext context,
AppLocalizations l10n,
AppUserRole role,
InterstitialAdConfiguration config,
) {
final roleConfig = config.visibleTo[role];
final isEnabled = role != AppUserRole.premiumUser;
// Removed isEnabled check as premium users can now be manually configured.

return Column(
children: [
SwitchListTile(
// Changed from CheckboxListTile to SwitchListTile for consistency
title: Text(l10n.enableInArticleAdsForRoleLabel(role.l10n(context))),
value: roleConfig != null && isEnabled,
onChanged: isEnabled
? (value) {
final newVisibleTo =
Map<AppUserRole, InterstitialAdFrequencyConfig>.from(
config.visibleTo,
);
if (value) {
// Default value when enabling for a role
newVisibleTo[role] = const InterstitialAdFrequencyConfig(
transitionsBeforeShowingInterstitialAds: 5,
);
} else {
newVisibleTo.remove(role);
}
widget.onConfigChanged(
widget.remoteConfig.copyWith(
adConfig: widget.remoteConfig.adConfig.copyWith(
interstitialAdConfiguration: config.copyWith(
visibleTo: newVisibleTo,
),
),
),
);
}
: null,
title: Text(l10n.visibleToRoleLabel(role.l10n(context))),
value: roleConfig != null, // Value is true if roleConfig exists
onChanged: (value) {
final newVisibleTo =
Map<AppUserRole, InterstitialAdFrequencyConfig>.from(
config.visibleTo,
);
if (value) {
// Default value when enabling for a role
newVisibleTo[role] = const InterstitialAdFrequencyConfig(
transitionsBeforeShowingInterstitialAds: 5,
);
} else {
newVisibleTo.remove(role);
}
widget.onConfigChanged(
widget.remoteConfig.copyWith(
adConfig: widget.remoteConfig.adConfig.copyWith(
interstitialAdConfiguration: config.copyWith(
visibleTo: newVisibleTo,
),
),
),
);
},
),
if (roleConfig != null)
Padding(
Expand All @@ -295,8 +251,8 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
);
final newVisibleTo =
Map<AppUserRole, InterstitialAdFrequencyConfig>.from(
config.visibleTo,
)..[role] = newRoleConfig;
config.visibleTo,
)..[role] = newRoleConfig;
widget.onConfigChanged(
widget.remoteConfig.copyWith(
adConfig: widget.remoteConfig.adConfig.copyWith(
Expand All @@ -309,7 +265,7 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
},
controller:
_transitionsBeforeShowingInterstitialAdsControllers[role],
enabled: isEnabled,
// Removed enabled: isEnabled
),
),
],
Expand Down

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