From a1877ffe2083d7ae8777d3c51596eb5879e62594 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 04:55:58 +0100 Subject: [PATCH 01/12] build(deps): update core dependency to version 1.3.1 - Update git ref in pubspec.yaml and pubspec.lock - Change ref from b3bf1fbe84c51006c55c0eed7fb5de2f11a95208 to e66e076572bd326e50e9d5286ef5059ff658ed65 --- pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 43e9f9c9..98b60a22 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -89,8 +89,8 @@ packages: dependency: "direct main" description: path: "." - ref: b3bf1fbe84c51006c55c0eed7fb5de2f11a95208 - resolved-ref: b3bf1fbe84c51006c55c0eed7fb5de2f11a95208 + ref: e66e076572bd326e50e9d5286ef5059ff658ed65 + resolved-ref: e66e076572bd326e50e9d5286ef5059ff658ed65 url: "https://github.com/flutter-news-app-full-source-code/core.git" source: git version: "1.3.1" diff --git a/pubspec.yaml b/pubspec.yaml index ca9323d0..80c6e57c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -94,7 +94,7 @@ dependency_overrides: core: git: url: https://github.com/flutter-news-app-full-source-code/core.git - ref: b3bf1fbe84c51006c55c0eed7fb5de2f11a95208 + ref: e66e076572bd326e50e9d5286ef5059ff658ed65 http_client: git: url: https://github.com/flutter-news-app-full-source-code/http-client.git From ef548f519eefdab868126e78bfd9232581bfaf0a Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 05:14:35 +0100 Subject: [PATCH 02/12] feat(l10n): add app review positive interaction types and thresholds - Add new positive interaction types for app review settings - Introduce interaction cycle threshold as a replacement for positive interaction threshold - Update descriptions and labels for app review prompt settings --- lib/l10n/arb/app_ar.arb | 34 +++++++++++++++++++++++++++------- lib/l10n/arb/app_en.arb | 34 +++++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/lib/l10n/arb/app_ar.arb b/lib/l10n/arb/app_ar.arb index c1651171..93c25749 100644 --- a/lib/l10n/arb/app_ar.arb +++ b/lib/l10n/arb/app_ar.arb @@ -2201,14 +2201,14 @@ "enableAppFeedbackSystemDescription": "ينشط النظام الداخلي الذي يسأل المستخدمين بشكل دوري عما إذا كانوا يستمتعون بالتطبيق.", "@enableAppFeedbackSystemDescription": { "description": "وصف المفتاح الرئيسي لتفعيل نظام ملاحظات التطبيق." + }, + "interactionCycleThresholdLabel": "عتبة دورة التفاعل", + "@interactionCycleThresholdLabel": { + "description": "تسمية حقل إدخال عتبة دورة التفاعل." }, - "positiveInteractionThresholdLabel": "عتبة التفاعل الإيجابي", - "@positiveInteractionThresholdLabel": { - "description": "تسمية حقل إدخال عتبة التفاعل الإيجابي." - }, - "positiveInteractionThresholdDescription": "يحدد عدد الإجراءات الإيجابية (مثل الحفظ، الإعجاب) المطلوبة لتشغيل موجه الاستمتاع. يظهر الموجه في كل مرة يكون فيها إجمالي الإجراءات الإيجابية للمستخدم من مضاعفات هذا الرقم.", - "@positiveInteractionThresholdDescription": { - "description": "وصف حقل إدخال عتبة التفاعل الإيجابي." + "interactionCycleThresholdDescription": "يحدد عدد الإجراءات الإيجابية (مثل الحفظ، الإعجاب) المطلوبة لتشغيل موجه الاستمتاع. يظهر الموجه في كل مرة يكون فيها إجمالي الإجراءات الإيجابية للمستخدم من مضاعفات هذا الرقم.", + "@interactionCycleThresholdDescription": { + "description": "وصف حقل إدخال عتبة دورة التفاعل." }, "initialPromptCooldownLabel": "فترة تهدئة الموجه الأولي (أيام)", "@initialPromptCooldownLabel": { @@ -2238,6 +2238,26 @@ "@internalPromptLogicTitle": { "description": "عنوان قسم منطق الموجه الداخلي لمراجعة التطبيق." }, + "eligiblePositiveInteractionsTitle": "التفاعلات الإيجابية المؤهلة", + "@eligiblePositiveInteractionsTitle": { + "description": "عنوان قسم التفاعلات الإيجابية المؤهلة." + }, + "positiveInteractionTypeSaveItem": "حفظ عنصر محتوى (مثل عنوان رئيسي)", + "@positiveInteractionTypeSaveItem": { + "description": "تسمية نوع التفاعل الإيجابي 'حفظ عنصر'." + }, + "positiveInteractionTypeFollowItem": "متابعة كيان (مثل موضوع أو مصدر أو بلد)", + "@positiveInteractionTypeFollowItem": { + "description": "تسمية نوع التفاعل الإيجابي 'متابعة عنصر'." + }, + "positiveInteractionTypeShareContent": "مشاركة عنصر محتوى (مثل عنوان رئيسي)", + "@positiveInteractionTypeShareContent": { + "description": "تسمية نوع التفاعل الإيجابي 'مشاركة محتوى'." + }, + "positiveInteractionTypeSaveFilter": "إنشاء مرشح محفوظ", + "@positiveInteractionTypeSaveFilter": { + "description": "تسمية نوع التفاعل الإيجابي 'حفظ مرشح'." + }, "followUpActionsTitle": "إجراءات المتابعة", "@followUpActionsTitle": { "description": "عنوان قسم إجراءات المتابعة لمراجعة التطبيق." diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 8c046670..6873d9e4 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -2197,14 +2197,14 @@ "enableAppFeedbackSystemDescription": "Activates the internal system that periodically asks users if they are enjoying the app.", "@enableAppFeedbackSystemDescription": { "description": "Description for the master switch to enable the app feedback system." + }, + "interactionCycleThresholdLabel": "Interaction Cycle Threshold", + "@interactionCycleThresholdLabel": { + "description": "Label for the interaction cycle threshold input field." }, - "positiveInteractionThresholdLabel": "Positive Interaction Threshold", - "@positiveInteractionThresholdLabel": { - "description": "Label for the positive interaction threshold input field." - }, - "positiveInteractionThresholdDescription": "Defines the number of positive actions (e.g., save, like) required to trigger the enjoyment prompt. The prompt is shown each time the user's total positive actions is a multiple of this number.", - "@positiveInteractionThresholdDescription": { - "description": "Description for the positive interaction threshold input field." + "interactionCycleThresholdDescription": "Defines the number of positive actions (e.g., save, like) required to trigger the enjoyment prompt. The prompt is shown each time the user's total positive actions is a multiple of this number.", + "@interactionCycleThresholdDescription": { + "description": "Description for the interaction cycle threshold input field." }, "initialPromptCooldownLabel": "Initial Prompt Cooldown (Days)", "@initialPromptCooldownLabel": { @@ -2234,6 +2234,26 @@ "@internalPromptLogicTitle": { "description": "Title for the nested expansion tile for internal app review prompt settings." }, + "eligiblePositiveInteractionsTitle": "Eligible Positive Interactions", + "@eligiblePositiveInteractionsTitle": { + "description": "Title for the expansion tile for eligible positive interactions." + }, + "positiveInteractionTypeSaveItem": "Save a content item (e.g., a headline)", + "@positiveInteractionTypeSaveItem": { + "description": "Label for the 'save item' positive interaction type." + }, + "positiveInteractionTypeFollowItem": "Follow an entity (e.g., a topic, source, or country)", + "@positiveInteractionTypeFollowItem": { + "description": "Label for the 'follow item' positive interaction type." + }, + "positiveInteractionTypeShareContent": "Share a content item (e.g., a headline)", + "@positiveInteractionTypeShareContent": { + "description": "Label for the 'share content' positive interaction type." + }, + "positiveInteractionTypeSaveFilter": "Create a saved filter", + "@positiveInteractionTypeSaveFilter": { + "description": "Label for the 'save filter' positive interaction type." + }, "followUpActionsTitle": "Follow-up Actions", "@followUpActionsTitle": { "description": "Title for the nested expansion tile for app review follow-up actions." From 0e750c54a8e2be212efdfc80a57323757ef019b1 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 05:14:50 +0100 Subject: [PATCH 03/12] build(l10n): sync --- lib/l10n/app_localizations.dart | 40 ++++++++++++++++++++++++++---- lib/l10n/app_localizations_ar.dart | 22 ++++++++++++++-- lib/l10n/app_localizations_en.dart | 24 +++++++++++++++--- 3 files changed, 76 insertions(+), 10 deletions(-) diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 2d729a3f..e35a9726 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -3272,17 +3272,17 @@ abstract class AppLocalizations { /// **'Activates the internal system that periodically asks users if they are enjoying the app.'** String get enableAppFeedbackSystemDescription; - /// Label for the positive interaction threshold input field. + /// Label for the interaction cycle threshold input field. /// /// In en, this message translates to: - /// **'Positive Interaction Threshold'** - String get positiveInteractionThresholdLabel; + /// **'Interaction Cycle Threshold'** + String get interactionCycleThresholdLabel; - /// Description for the positive interaction threshold input field. + /// Description for the interaction cycle threshold input field. /// /// In en, this message translates to: /// **'Defines the number of positive actions (e.g., save, like) required to trigger the enjoyment prompt. The prompt is shown each time the user\'s total positive actions is a multiple of this number.'** - String get positiveInteractionThresholdDescription; + String get interactionCycleThresholdDescription; /// Label for the initial prompt cooldown input field. /// @@ -3326,6 +3326,36 @@ abstract class AppLocalizations { /// **'Internal Prompt Logic'** String get internalPromptLogicTitle; + /// Title for the expansion tile for eligible positive interactions. + /// + /// In en, this message translates to: + /// **'Eligible Positive Interactions'** + String get eligiblePositiveInteractionsTitle; + + /// Label for the 'save item' positive interaction type. + /// + /// In en, this message translates to: + /// **'Save a content item (e.g., a headline)'** + String get positiveInteractionTypeSaveItem; + + /// Label for the 'follow item' positive interaction type. + /// + /// In en, this message translates to: + /// **'Follow an entity (e.g., a topic, source, or country)'** + String get positiveInteractionTypeFollowItem; + + /// Label for the 'share content' positive interaction type. + /// + /// In en, this message translates to: + /// **'Share a content item (e.g., a headline)'** + String get positiveInteractionTypeShareContent; + + /// Label for the 'save filter' positive interaction type. + /// + /// In en, this message translates to: + /// **'Create a saved filter'** + String get positiveInteractionTypeSaveFilter; + /// Title for the nested expansion tile for app review follow-up actions. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_ar.dart b/lib/l10n/app_localizations_ar.dart index d34a8ec4..a54255c8 100644 --- a/lib/l10n/app_localizations_ar.dart +++ b/lib/l10n/app_localizations_ar.dart @@ -1763,10 +1763,10 @@ class AppLocalizationsAr extends AppLocalizations { 'ينشط النظام الداخلي الذي يسأل المستخدمين بشكل دوري عما إذا كانوا يستمتعون بالتطبيق.'; @override - String get positiveInteractionThresholdLabel => 'عتبة التفاعل الإيجابي'; + String get interactionCycleThresholdLabel => 'عتبة دورة التفاعل'; @override - String get positiveInteractionThresholdDescription => + String get interactionCycleThresholdDescription => 'يحدد عدد الإجراءات الإيجابية (مثل الحفظ، الإعجاب) المطلوبة لتشغيل موجه الاستمتاع. يظهر الموجه في كل مرة يكون فيها إجمالي الإجراءات الإيجابية للمستخدم من مضاعفات هذا الرقم.'; @override @@ -1793,6 +1793,24 @@ class AppLocalizationsAr extends AppLocalizations { @override String get internalPromptLogicTitle => 'منطق الموجه الداخلي'; + @override + String get eligiblePositiveInteractionsTitle => 'التفاعلات الإيجابية المؤهلة'; + + @override + String get positiveInteractionTypeSaveItem => + 'حفظ عنصر محتوى (مثل عنوان رئيسي)'; + + @override + String get positiveInteractionTypeFollowItem => + 'متابعة كيان (مثل موضوع أو مصدر أو بلد)'; + + @override + String get positiveInteractionTypeShareContent => + 'مشاركة عنصر محتوى (مثل عنوان رئيسي)'; + + @override + String get positiveInteractionTypeSaveFilter => 'إنشاء مرشح محفوظ'; + @override String get followUpActionsTitle => 'إجراءات المتابعة'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 3c5adaf9..6db20c49 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -1766,11 +1766,10 @@ class AppLocalizationsEn extends AppLocalizations { 'Activates the internal system that periodically asks users if they are enjoying the app.'; @override - String get positiveInteractionThresholdLabel => - 'Positive Interaction Threshold'; + String get interactionCycleThresholdLabel => 'Interaction Cycle Threshold'; @override - String get positiveInteractionThresholdDescription => + String get interactionCycleThresholdDescription => 'Defines the number of positive actions (e.g., save, like) required to trigger the enjoyment prompt. The prompt is shown each time the user\'s total positive actions is a multiple of this number.'; @override @@ -1798,6 +1797,25 @@ class AppLocalizationsEn extends AppLocalizations { @override String get internalPromptLogicTitle => 'Internal Prompt Logic'; + @override + String get eligiblePositiveInteractionsTitle => + 'Eligible Positive Interactions'; + + @override + String get positiveInteractionTypeSaveItem => + 'Save a content item (e.g., a headline)'; + + @override + String get positiveInteractionTypeFollowItem => + 'Follow an entity (e.g., a topic, source, or country)'; + + @override + String get positiveInteractionTypeShareContent => + 'Share a content item (e.g., a headline)'; + + @override + String get positiveInteractionTypeSaveFilter => 'Create a saved filter'; + @override String get followUpActionsTitle => 'Follow-up Actions'; From 1d2f007fb45578ca2e3741bbdf2a9ba4cca0d96b Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 05:16:23 +0100 Subject: [PATCH 04/12] feat(app_configuration): enhance app review settings - Rename positiveInteractionThreshold to interactionCycleThreshold - Add localization support for interaction cycle threshold label and description - Implement switchable list for eligible positive interactions - Update UI to display new interaction types and their descriptions --- .../widgets/app_review_settings_form.dart | 95 ++++++++++++++++--- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/lib/app_configuration/widgets/app_review_settings_form.dart b/lib/app_configuration/widgets/app_review_settings_form.dart index 9498d03b..6df9e295 100644 --- a/lib/app_configuration/widgets/app_review_settings_form.dart +++ b/lib/app_configuration/widgets/app_review_settings_form.dart @@ -1,6 +1,7 @@ import 'package:core/core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_news_app_web_dashboard_full_source_code/app_configuration/widgets/app_config_form_fields.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:ui_kit/ui_kit.dart'; @@ -26,7 +27,7 @@ class AppReviewSettingsForm extends StatefulWidget { } class _AppReviewSettingsFormState extends State { - late final TextEditingController _positiveInteractionThresholdController; + late final TextEditingController _interactionCycleThresholdController; late final TextEditingController _initialPromptCooldownController; @override @@ -46,8 +47,8 @@ class _AppReviewSettingsFormState extends State { void _initializeControllers() { final appReviewConfig = widget.remoteConfig.features.community.appReview; - _positiveInteractionThresholdController = TextEditingController( - text: appReviewConfig.positiveInteractionThreshold.toString(), + _interactionCycleThresholdController = TextEditingController( + text: appReviewConfig.interactionCycleThreshold.toString(), ); _initialPromptCooldownController = TextEditingController( text: appReviewConfig.initialPromptCooldownDays.toString(), @@ -56,9 +57,8 @@ class _AppReviewSettingsFormState extends State { void _updateControllers() { final appReviewConfig = widget.remoteConfig.features.community.appReview; - _positiveInteractionThresholdController.text = appReviewConfig - .positiveInteractionThreshold - .toString(); + _interactionCycleThresholdController.text = + appReviewConfig.interactionCycleThreshold.toString(); _initialPromptCooldownController.text = appReviewConfig .initialPromptCooldownDays .toString(); @@ -66,7 +66,7 @@ class _AppReviewSettingsFormState extends State { @override void dispose() { - _positiveInteractionThresholdController.dispose(); + _interactionCycleThresholdController.dispose(); _initialPromptCooldownController.dispose(); super.dispose(); } @@ -121,14 +121,14 @@ class _AppReviewSettingsFormState extends State { expandedCrossAxisAlignment: CrossAxisAlignment.start, children: [ AppConfigIntField( - label: l10n.positiveInteractionThresholdLabel, + label: l10n.interactionCycleThresholdLabel, description: - l10n.positiveInteractionThresholdDescription, - value: appReviewConfig.positiveInteractionThreshold, + l10n.interactionCycleThresholdDescription, + value: appReviewConfig.interactionCycleThreshold, onChanged: (value) { final newConfig = communityConfig.copyWith( appReview: appReviewConfig.copyWith( - positiveInteractionThreshold: value, + interactionCycleThreshold: value, ), ); widget.onConfigChanged( @@ -140,7 +140,7 @@ class _AppReviewSettingsFormState extends State { ), ); }, - controller: _positiveInteractionThresholdController, + controller: _interactionCycleThresholdController, ), AppConfigIntField( label: l10n.initialPromptCooldownLabel, @@ -168,6 +168,61 @@ class _AppReviewSettingsFormState extends State { }, ), ), + Padding( + padding: const EdgeInsetsDirectional.only( + start: AppSpacing.lg, + ), + child: LayoutBuilder( + builder: (context, constraints) { + final isMobile = constraints.maxWidth < 600; + return ExpansionTile( + title: Text(l10n.eligiblePositiveInteractionsTitle), + initiallyExpanded: !isMobile, + childrenPadding: const EdgeInsetsDirectional.only( + start: AppSpacing.lg, + top: AppSpacing.md, + bottom: AppSpacing.md, + ), + expandedCrossAxisAlignment: CrossAxisAlignment.start, + children: [ + ...PositiveInteractionType.values.map( + (interactionType) => SwitchListTile( + title: Text(interactionType.l10n(context)), + value: appReviewConfig + .eligiblePositiveInteractions + .contains(interactionType), + onChanged: (value) { + final currentInteractions = List< + PositiveInteractionType>.from( + appReviewConfig.eligiblePositiveInteractions, + ); + if (value) { + currentInteractions.add(interactionType); + } else { + currentInteractions.remove(interactionType); + } + final newAppReviewConfig = + appReviewConfig.copyWith( + eligiblePositiveInteractions: + currentInteractions, + ); + widget.onConfigChanged( + widget.remoteConfig.copyWith( + features: widget.remoteConfig.features + .copyWith( + community: communityConfig.copyWith( + appReview: newAppReviewConfig), + ), + ), + ); + }, + ), + ), + ], + ); + }, + ), + ), Padding( padding: const EdgeInsetsDirectional.only( start: AppSpacing.lg, @@ -244,3 +299,19 @@ class _AppReviewSettingsFormState extends State { ); } } + +extension on PositiveInteractionType { + String l10n(BuildContext context) { + final l10n = AppLocalizationsX(context).l10n; + switch (this) { + case PositiveInteractionType.saveItem: + return l10n.positiveInteractionTypeSaveItem; + case PositiveInteractionType.followItem: + return l10n.positiveInteractionTypeFollowItem; + case PositiveInteractionType.shareContent: + return l10n.positiveInteractionTypeShareContent; + case PositiveInteractionType.saveFilter: + return l10n.positiveInteractionTypeSaveFilter; + } + } +} From 7ed754eac83c4e7a517175e1ece86904562c50f3 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 05:16:51 +0100 Subject: [PATCH 05/12] fix: correct color mapping for comment reports - Update the color mapping for ReportableEntity.comment in the _ReportsDataSource class - --- lib/community_management/view/reports_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/community_management/view/reports_page.dart b/lib/community_management/view/reports_page.dart index 93af6eeb..05b47dee 100644 --- a/lib/community_management/view/reports_page.dart +++ b/lib/community_management/view/reports_page.dart @@ -227,7 +227,7 @@ class _ReportsDataSource extends DataTableSource { return colorScheme.primaryContainer.withOpacity(0.5); case ReportableEntity.source: return colorScheme.secondaryContainer.withOpacity(0.5); - case ReportableEntity.engagement: + case ReportableEntity.comment: return colorScheme.tertiaryContainer.withOpacity(0.5); } } From 60af73ed1a261ac6494ed25a3b0ef04dc82293d1 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 05:17:24 +0100 Subject: [PATCH 06/12] fix(localization): update ReportableEntity extension for correct localization - Change ReportableEntity.engagement to ReportableEntity.comment - Ensure proper localization key is used for comment entity --- lib/shared/extensions/reportable_entity_extension.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/shared/extensions/reportable_entity_extension.dart b/lib/shared/extensions/reportable_entity_extension.dart index 8cccce57..54ec6538 100644 --- a/lib/shared/extensions/reportable_entity_extension.dart +++ b/lib/shared/extensions/reportable_entity_extension.dart @@ -11,7 +11,7 @@ extension ReportableEntityX on ReportableEntity { return l10n.reportableEntityHeadline; case ReportableEntity.source: return l10n.reportableEntitySource; - case ReportableEntity.engagement: + case ReportableEntity.comment: return l10n.reportableEntityComment; } } From af571aff7e9fcdc06734aad4280a57ec830cc056 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 05:20:07 +0100 Subject: [PATCH 07/12] fix(community_management): handle null reaction and localize reaction types - Add null check for engagement.reaction and display "N/A" if null - Implement extension method to provide localized names for reaction types - Update UI to use localized reaction type names --- .../view/engagements_page.dart | 45 +++++++++++++++---- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/lib/community_management/view/engagements_page.dart b/lib/community_management/view/engagements_page.dart index 5abf789f..21f502e4 100644 --- a/lib/community_management/view/engagements_page.dart +++ b/lib/community_management/view/engagements_page.dart @@ -198,15 +198,22 @@ class _EngagementsDataSource extends DataTableSource { return DataRow2( cells: [ DataCell( - Chip( - label: Text(engagement.reaction.reactionType.name), - backgroundColor: _getReactionColor( - context, - engagement.reaction.reactionType, - ), - side: BorderSide.none, - visualDensity: VisualDensity.compact, - ), + engagement.reaction != null + ? Chip( + label: Text( + engagement.reaction!.reactionType.l10n(context), + ), + backgroundColor: _getReactionColor( + context, + engagement.reaction!.reactionType, + ), + side: BorderSide.none, + visualDensity: VisualDensity.compact, + ) + : Text( + l10n.notAvailable, + style: Theme.of(context).textTheme.bodySmall, + ), ), DataCell( Text(DateFormat('dd-MM-yyyy').format(engagement.createdAt.toLocal())), @@ -243,3 +250,23 @@ class _EngagementsDataSource extends DataTableSource { } } } + +extension on ReactionType { + String l10n(BuildContext context) { + final l10n = AppLocalizationsX(context).l10n; + switch (this) { + case ReactionType.like: + return l10n.reactionTypeLike; + case ReactionType.insightful: + return l10n.reactionTypeInsightful; + case ReactionType.amusing: + return l10n.reactionTypeAmusing; + case ReactionType.sad: + return l10n.reactionTypeSad; + case ReactionType.angry: + return l10n.reactionTypeAngry; + case ReactionType.skeptical: + return l10n.reactionTypeSkeptical; + } + } +} From dceb29885c73f61a98ebc9bfc7c5e073f6c23741 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 05:20:22 +0100 Subject: [PATCH 08/12] style: format --- .../widgets/app_review_settings_form.dart | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/app_configuration/widgets/app_review_settings_form.dart b/lib/app_configuration/widgets/app_review_settings_form.dart index 6df9e295..5e724210 100644 --- a/lib/app_configuration/widgets/app_review_settings_form.dart +++ b/lib/app_configuration/widgets/app_review_settings_form.dart @@ -1,7 +1,6 @@ import 'package:core/core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_news_app_web_dashboard_full_source_code/app_configuration/widgets/app_config_form_fields.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:ui_kit/ui_kit.dart'; @@ -57,8 +56,9 @@ class _AppReviewSettingsFormState extends State { void _updateControllers() { final appReviewConfig = widget.remoteConfig.features.community.appReview; - _interactionCycleThresholdController.text = - appReviewConfig.interactionCycleThreshold.toString(); + _interactionCycleThresholdController.text = appReviewConfig + .interactionCycleThreshold + .toString(); _initialPromptCooldownController.text = appReviewConfig .initialPromptCooldownDays .toString(); @@ -192,26 +192,28 @@ class _AppReviewSettingsFormState extends State { .eligiblePositiveInteractions .contains(interactionType), onChanged: (value) { - final currentInteractions = List< - PositiveInteractionType>.from( - appReviewConfig.eligiblePositiveInteractions, - ); + final currentInteractions = + List.from( + appReviewConfig + .eligiblePositiveInteractions, + ); if (value) { currentInteractions.add(interactionType); } else { currentInteractions.remove(interactionType); } - final newAppReviewConfig = - appReviewConfig.copyWith( - eligiblePositiveInteractions: - currentInteractions, - ); + final newAppReviewConfig = appReviewConfig + .copyWith( + eligiblePositiveInteractions: + currentInteractions, + ); widget.onConfigChanged( widget.remoteConfig.copyWith( features: widget.remoteConfig.features .copyWith( community: communityConfig.copyWith( - appReview: newAppReviewConfig), + appReview: newAppReviewConfig, + ), ), ), ); From b30e9a3f166ce5c2b03d6e6a0282fe43a70b2ae8 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 05:35:07 +0100 Subject: [PATCH 09/12] chore(l10n): update --- lib/l10n/arb/app_ar.arb | 4 ++-- lib/l10n/arb/app_en.arb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/l10n/arb/app_ar.arb b/lib/l10n/arb/app_ar.arb index 93c25749..f6dfd1d9 100644 --- a/lib/l10n/arb/app_ar.arb +++ b/lib/l10n/arb/app_ar.arb @@ -2201,7 +2201,7 @@ "enableAppFeedbackSystemDescription": "ينشط النظام الداخلي الذي يسأل المستخدمين بشكل دوري عما إذا كانوا يستمتعون بالتطبيق.", "@enableAppFeedbackSystemDescription": { "description": "وصف المفتاح الرئيسي لتفعيل نظام ملاحظات التطبيق." - }, + }, "interactionCycleThresholdLabel": "عتبة دورة التفاعل", "@interactionCycleThresholdLabel": { "description": "تسمية حقل إدخال عتبة دورة التفاعل." @@ -2214,7 +2214,7 @@ "@initialPromptCooldownLabel": { "description": "تسمية حقل إدخال فترة تهدئة الموجه الأولي." }, - "initialPromptCooldownDescription": "إذا رفض المستخدم الموجه، انتظر هذا العدد من الأيام قبل أن يكون مؤهلاً لرؤيته مرة أخرى. ملاحظة: تتحكم زينة 'تقييم التطبيق' في قسم الموجز في تردد عرضها المنفصل.", + "initialPromptCooldownDescription": "عدد الأيام التي يجب الانتظار فيها قبل إظهار مطالبة الاستمتاع للمرة الأولى. تضمن فترة التهدئة هذه عدم سؤال المستخدمين حتى يستخدموا التطبيق بما فيه الكفاية.", "@initialPromptCooldownDescription": { "description": "وصف حقل إدخال فترة تهدئة الموجه الأولي." }, diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 6873d9e4..e0dce8e8 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -2197,7 +2197,7 @@ "enableAppFeedbackSystemDescription": "Activates the internal system that periodically asks users if they are enjoying the app.", "@enableAppFeedbackSystemDescription": { "description": "Description for the master switch to enable the app feedback system." - }, + }, "interactionCycleThresholdLabel": "Interaction Cycle Threshold", "@interactionCycleThresholdLabel": { "description": "Label for the interaction cycle threshold input field." @@ -2210,7 +2210,7 @@ "@initialPromptCooldownLabel": { "description": "Label for the initial prompt cooldown input field." }, - "initialPromptCooldownDescription": "If a user dismisses the prompt, wait this many days before they are eligible to see it again. Note: The 'Rate App' decorator in the Feed section controls its own separate display frequency.", + "initialPromptCooldownDescription": "The number of days to wait before showing the enjoyment prompt for the first time, This cooldown ensures users are not asked until they used the app enough.", "@initialPromptCooldownDescription": { "description": "Description for the initial prompt cooldown input field." }, From 10a92b6d25a2b6065e81570e01c6f341eb2512f5 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 05:35:18 +0100 Subject: [PATCH 10/12] build(l10n): sync --- lib/l10n/app_localizations.dart | 2 +- lib/l10n/app_localizations_ar.dart | 2 +- lib/l10n/app_localizations_en.dart | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index e35a9726..7613024d 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -3293,7 +3293,7 @@ abstract class AppLocalizations { /// Description for the initial prompt cooldown input field. /// /// In en, this message translates to: - /// **'If a user dismisses the prompt, wait this many days before they are eligible to see it again. Note: The \'Rate App\' decorator in the Feed section controls its own separate display frequency.'** + /// **'The number of days to wait before showing the enjoyment prompt for the first time, This cooldown ensures users are not asked until they used the app enough.'** String get initialPromptCooldownDescription; /// Label for the switch to request a store review after positive feedback. diff --git a/lib/l10n/app_localizations_ar.dart b/lib/l10n/app_localizations_ar.dart index a54255c8..7d47caca 100644 --- a/lib/l10n/app_localizations_ar.dart +++ b/lib/l10n/app_localizations_ar.dart @@ -1774,7 +1774,7 @@ class AppLocalizationsAr extends AppLocalizations { @override String get initialPromptCooldownDescription => - 'إذا رفض المستخدم الموجه، انتظر هذا العدد من الأيام قبل أن يكون مؤهلاً لرؤيته مرة أخرى. ملاحظة: تتحكم زينة \'تقييم التطبيق\' في قسم الموجز في تردد عرضها المنفصل.'; + 'عدد الأيام التي يجب الانتظار فيها قبل إظهار مطالبة الاستمتاع للمرة الأولى. تضمن فترة التهدئة هذه عدم سؤال المستخدمين حتى يستخدموا التطبيق بما فيه الكفاية.'; @override String get requestStoreReviewLabel => 'طلب مراجعة المتجر بعد \'نعم\''; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 6db20c49..0c5af7b8 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -1777,7 +1777,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get initialPromptCooldownDescription => - 'If a user dismisses the prompt, wait this many days before they are eligible to see it again. Note: The \'Rate App\' decorator in the Feed section controls its own separate display frequency.'; + 'The number of days to wait before showing the enjoyment prompt for the first time, This cooldown ensures users are not asked until they used the app enough.'; @override String get requestStoreReviewLabel => 'Request Store Review After \'Yes\''; From 4a5a1b89c44182a40188ee918190a1fae1442458 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 05:36:44 +0100 Subject: [PATCH 11/12] style: update not available text color in engagements page - Modify the style of the 'not available' text in the engagements page - Use onSurface color with 60% opacity for better visibility --- lib/community_management/view/engagements_page.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/community_management/view/engagements_page.dart b/lib/community_management/view/engagements_page.dart index 21f502e4..27e25dba 100644 --- a/lib/community_management/view/engagements_page.dart +++ b/lib/community_management/view/engagements_page.dart @@ -212,7 +212,9 @@ class _EngagementsDataSource extends DataTableSource { ) : Text( l10n.notAvailable, - style: Theme.of(context).textTheme.bodySmall, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6), + ), ), ), DataCell( From 92f91f6c9914c522d47e9274bf2534925a664a0d Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 05:37:08 +0100 Subject: [PATCH 12/12] style: format --- lib/community_management/view/engagements_page.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/community_management/view/engagements_page.dart b/lib/community_management/view/engagements_page.dart index 27e25dba..c164792d 100644 --- a/lib/community_management/view/engagements_page.dart +++ b/lib/community_management/view/engagements_page.dart @@ -213,8 +213,10 @@ class _EngagementsDataSource extends DataTableSource { : Text( l10n.notAvailable, style: Theme.of(context).textTheme.bodySmall?.copyWith( - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6), - ), + color: Theme.of( + context, + ).colorScheme.onSurface.withOpacity(0.6), + ), ), ), DataCell(