diff --git a/lib/app_configuration/widgets/feed_decorator_form.dart b/lib/app_configuration/widgets/feed_decorator_form.dart index e02ab891..0fcd664f 100644 --- a/lib/app_configuration/widgets/feed_decorator_form.dart +++ b/lib/app_configuration/widgets/feed_decorator_form.dart @@ -119,6 +119,30 @@ class _FeedDecoratorFormState extends State super.dispose(); } + /// Determines if a given decorator type is logically applicable to a user role. + /// + /// This method centralizes the business logic for decorator visibility + /// to prevent illogical configurations in the dashboard. + bool _isDecoratorApplicableToRole( + FeedDecoratorType decoratorType, + AppUserRole role, + ) { + switch (decoratorType) { + // The 'linkAccount' decorator is only for guest users. + case FeedDecoratorType.linkAccount: + return role == AppUserRole.guestUser; + // The 'upgrade' decorator is only for standard users. + case FeedDecoratorType.upgrade: + return role == AppUserRole.standardUser; + // All other decorators are applicable to any user role. + case FeedDecoratorType.rateApp: + case FeedDecoratorType.enableNotifications: + case FeedDecoratorType.suggestedTopics: + case FeedDecoratorType.suggestedSources: + return true; + } + } + @override Widget build(BuildContext context) { final l10n = AppLocalizationsX(context).l10n; @@ -210,18 +234,19 @@ class _FeedDecoratorFormState extends State FeedDecoratorConfig decoratorConfig, ) { final roleConfig = decoratorConfig.visibleTo[role]; - final isLinkAccountForStandardOrPremium = - widget.decoratorType == FeedDecoratorType.linkAccount && - (role == AppUserRole.standardUser || role == AppUserRole.premiumUser); + final isApplicable = _isDecoratorApplicableToRole( + widget.decoratorType, + role, + ); return Column( children: [ CheckboxListTile( title: Text(l10n.visibleToRoleLabel(role.l10n(context))), - value: roleConfig != null, - onChanged: isLinkAccountForStandardOrPremium - ? null // Disable for standard and premium users for linkAccount - : (value) { + value: roleConfig != null && isApplicable, + // Disable the checkbox if the decorator is not applicable to the role. + onChanged: isApplicable + ? (value) { final newVisibleTo = Map.from( decoratorConfig.visibleTo, @@ -245,7 +270,8 @@ class _FeedDecoratorFormState extends State feedDecoratorConfig: newFeedDecoratorConfig, ), ); - }, + } + : null, ), if (roleConfig != null) Padding( diff --git a/lib/content_management/bloc/draft_headlines/draft_headlines_bloc.dart b/lib/content_management/bloc/draft_headlines/draft_headlines_bloc.dart index 6e969596..7b8a618d 100644 --- a/lib/content_management/bloc/draft_headlines/draft_headlines_bloc.dart +++ b/lib/content_management/bloc/draft_headlines/draft_headlines_bloc.dart @@ -120,7 +120,7 @@ class DraftHeadlinesBloc final headlineToPublish = originalHeadlines[headlineIndex]; final updatedHeadlines = List.from(originalHeadlines) ..removeAt(headlineIndex); - + // Optimistically remove the headline from the UI. emit( state.copyWith( diff --git a/lib/content_management/bloc/draft_topics/draft_topics_bloc.dart b/lib/content_management/bloc/draft_topics/draft_topics_bloc.dart index 2f789165..def36564 100644 --- a/lib/content_management/bloc/draft_topics/draft_topics_bloc.dart +++ b/lib/content_management/bloc/draft_topics/draft_topics_bloc.dart @@ -119,7 +119,7 @@ class DraftTopicsBloc extends Bloc { final topicToPublish = originalTopics[topicIndex]; final updatedTopics = List.from(originalTopics) ..removeAt(topicIndex); - + // Optimistically remove the topic from the UI. emit( state.copyWith(