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

App config premium user ad deactivation and local ads tab order synchronization #84

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
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions lib/app_configuration/widgets/app_config_form_fields.dart
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class AppConfigIntField extends StatelessWidget {
required this.value,
required this.onChanged,
this.controller,
this.enabled = true,
super.key,
});

Expand All @@ -31,6 +32,9 @@ class AppConfigIntField extends StatelessWidget {
/// Optional text editing controller for more control.
final TextEditingController? controller;

/// Whether the input field is enabled. Defaults to true.
final bool enabled;

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
Expand All @@ -50,6 +54,7 @@ class AppConfigIntField extends StatelessWidget {
),
const SizedBox(height: AppSpacing.xs),
TextFormField(
enabled: enabled,
controller: controller,
initialValue: controller == null ? value.toString() : null,
keyboardType: TextInputType.number,
Expand Down
48 changes: 45 additions & 3 deletions lib/app_configuration/widgets/feed_ad_settings_form.dart
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,37 @@ class _FeedAdSettingsFormState extends State<FeedAdSettingsForm>
vsync: this,
);
_initializeControllers();
_tabController.addListener(_onTabChanged);
}

void _onTabChanged() {
if (_tabController.indexIsChanging) return;

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

// If the values for premium are not 0, update the config.
// This enforces the business rule that premium users do not see ads.
if (feedAdConfig.frequencyConfig.premiumAdFrequency != 0 ||
feedAdConfig.frequencyConfig.premiumAdPlacementInterval != 0) {
final updatedFrequencyConfig = feedAdConfig.frequencyConfig.copyWith(
premiumAdFrequency: 0,
premiumAdPlacementInterval: 0,
);
final updatedFeedAdConfig = feedAdConfig.copyWith(
frequencyConfig: updatedFrequencyConfig,
);
widget.onConfigChanged(
widget.remoteConfig.copyWith(
adConfig: adConfig.copyWith(
feedAdConfiguration: updatedFeedAdConfig,
),
),
);
}
}
}

@override
Expand Down Expand Up @@ -109,7 +140,9 @@ class _FeedAdSettingsFormState extends State<FeedAdSettingsForm>

@override
void dispose() {
_tabController.dispose();
_tabController
..removeListener(_onTabChanged)
..dispose();
for (final controller in _adFrequencyControllers.values) {
controller.dispose();
}
Expand Down Expand Up @@ -257,6 +290,9 @@ class _FeedAdSettingsFormState extends State<FeedAdSettingsForm>
AppUserRole role,
FeedAdConfiguration config,
) {
// Premium users do not see ads, so their settings are disabled.
final isEnabled = role != AppUserRole.premiumUser;

return Column(
children: [
AppConfigIntField(
Expand All @@ -273,6 +309,7 @@ class _FeedAdSettingsFormState extends State<FeedAdSettingsForm>
);
},
controller: _adFrequencyControllers[role],
enabled: isEnabled,
),
AppConfigIntField(
label: l10n.adPlacementIntervalLabel,
Expand All @@ -292,6 +329,7 @@ class _FeedAdSettingsFormState extends State<FeedAdSettingsForm>
);
},
controller: _adPlacementIntervalControllers[role],
enabled: isEnabled,
),
],
);
Expand Down Expand Up @@ -338,9 +376,11 @@ class _FeedAdSettingsFormState extends State<FeedAdSettingsForm>
),
);
case AppUserRole.premiumUser:
// Premium users should not see ads, so their frequency is always 0.
// The UI field is disabled, but this is a safeguard.
return config.copyWith(
frequencyConfig: config.frequencyConfig.copyWith(
premiumAdFrequency: value,
premiumAdFrequency: 0,
),
);
}
Expand All @@ -365,9 +405,11 @@ class _FeedAdSettingsFormState extends State<FeedAdSettingsForm>
),
);
case AppUserRole.premiumUser:
// Premium users should not see ads, so their interval is always 0.
// The UI field is disabled, but this is a safeguard.
return config.copyWith(
frequencyConfig: config.frequencyConfig.copyWith(
premiumAdPlacementInterval: value,
premiumAdPlacementInterval: 0,
),
);
}
Expand Down
46 changes: 44 additions & 2 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 @@ -42,6 +42,40 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
vsync: this,
);
_initializeControllers();
_tabController.addListener(_onTabChanged);
}

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.
if (interstitialAdConfig
.feedInterstitialAdFrequencyConfig
.premiumUserTransitionsBeforeShowingInterstitialAds !=
0) {
final updatedFrequencyConfig = interstitialAdConfig
.feedInterstitialAdFrequencyConfig
.copyWith(
premiumUserTransitionsBeforeShowingInterstitialAds: 0,
);
final updatedInterstitialAdConfig = interstitialAdConfig.copyWith(
feedInterstitialAdFrequencyConfig: updatedFrequencyConfig,
);
widget.onConfigChanged(
widget.remoteConfig.copyWith(
adConfig: adConfig.copyWith(
interstitialAdConfiguration: updatedInterstitialAdConfig,
),
),
);
}
}
}

@override
Expand Down Expand Up @@ -96,7 +130,9 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>

@override
void dispose() {
_tabController.dispose();
_tabController
..removeListener(_onTabChanged)
..dispose();
for (final controller
in _transitionsBeforeShowingInterstitialAdsControllers.values) {
controller.dispose();
Expand Down Expand Up @@ -190,6 +226,9 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
AppUserRole role,
InterstitialAdConfiguration config,
) {
// Premium users do not see ads, so their settings are disabled.
final isEnabled = role != AppUserRole.premiumUser;

return Column(
children: [
AppConfigIntField(
Expand All @@ -211,6 +250,7 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
);
},
controller: _transitionsBeforeShowingInterstitialAdsControllers[role],
enabled: isEnabled,
),
],
);
Expand Down Expand Up @@ -255,8 +295,10 @@ class _InterstitialAdSettingsFormState extends State<InterstitialAdSettingsForm>
standardUserTransitionsBeforeShowingInterstitialAds: value,
);
case AppUserRole.premiumUser:
// Premium users should not see ads, so their frequency is always 0.
// The UI field is disabled, but this is a safeguard.
newFrequencyConfig = currentFrequencyConfig.copyWith(
premiumUserTransitionsBeforeShowingInterstitialAds: value,
premiumUserTransitionsBeforeShowingInterstitialAds: 0,
);
}

Expand Down
20 changes: 13 additions & 7 deletions lib/local_ads_management/view/archived_local_ads_page.dart
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,19 @@ class _ArchivedLocalAdsViewState extends State<_ArchivedLocalAdsView>
with SingleTickerProviderStateMixin {
late TabController _tabController;

// Statically define the tab order to ensure consistency.
final List<AdType> _tabs = [
AdType.native,
AdType.banner,
AdType.interstitial,
AdType.video,
];

@override
void initState() {
super.initState();
_tabController = TabController(
length: AdType.values.length,
length: _tabs.length,
vsync: this,
);
}
Expand All @@ -76,9 +84,7 @@ class _ArchivedLocalAdsViewState extends State<_ArchivedLocalAdsView>
controller: _tabController,
tabAlignment: TabAlignment.start,
isScrollable: true,
tabs: AdType.values
.map((type) => Tab(text: type.l10n(context)))
.toList(),
tabs: _tabs.map((type) => Tab(text: type.l10n(context))).toList(),
),
),
body: BlocListener<ArchiveLocalAdsBloc, ArchiveLocalAdsState>(
Expand Down Expand Up @@ -149,9 +155,9 @@ class _ArchivedLocalAdsViewState extends State<_ArchivedLocalAdsView>
},
child: TabBarView(
controller: _tabController,
children: AdType.values.map((type) {
return _ArchivedLocalAdsDataTable(adType: type);
}).toList(),
children: _tabs
.map((type) => _ArchivedLocalAdsDataTable(adType: type))
.toList(),
),
),
);
Expand Down
10 changes: 5 additions & 5 deletions pubspec.lock
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ packages:
description:
path: "."
ref: HEAD
resolved-ref: dd37d11352124113978ebeda3b509d932db61cf5
resolved-ref: b6a3fb4ad862901a56b424fd92a9702f30513404
url: "https://github.com/flutter-news-app-full-source-code/core.git"
source: git
version: "0.0.0"
Expand Down Expand Up @@ -269,10 +269,10 @@ packages:
dependency: "direct main"
description:
name: go_router
sha256: eb059dfe59f08546e9787f895bd01652076f996bcbf485a8609ef990419ad227
sha256: b1488741c9ce37b72e026377c69a59c47378493156fc38efb5a54f6def3f92a3
url: "https://pub.dev"
source: hosted
version: "16.2.1"
version: "16.2.2"
google_fonts:
dependency: "direct main"
description:
Expand Down Expand Up @@ -488,10 +488,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_android
sha256: a2608114b1ffdcbc9c120eb71a0e207c71da56202852d4aab8a5e30a82269e74
sha256: bd14436108211b0d4ee5038689a56d4ae3620fd72fd6036e113bf1345bc74d9e
url: "https://pub.dev"
source: hosted
version: "2.4.12"
version: "2.4.13"
shared_preferences_foundation:
dependency: transitive
description:
Expand Down
Loading

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