Skip to content

Add in-app legal documents to Settings#424

Open
CherryCIC wants to merge 1 commit into
mainfrom
cherryprivacypolicybranch
Open

Add in-app legal documents to Settings#424
CherryCIC wants to merge 1 commit into
mainfrom
cherryprivacypolicybranch

Conversation

@CherryCIC
Copy link
Copy Markdown
Collaborator

@CherryCIC CherryCIC commented May 18, 2026

Summary

Screenshot 2026-05-18 at 13 49 46

Aims to fix: #389

Terms and Conditions pdf.pdf

Privacy Policy pdf.pdf

  • Adds a Legal information screen from Settings.
  • Adds Privacy Policy and Terms and Conditions rows under Legal information.
  • Renders both legal documents in-app from bundled text assets with structured headings, paragraphs, and bullets.
  • Refactors the legal document renderer so both screens share one native display component.
  • Registers the legal asset folder and updates the focused widget test for the Settings -> Legal information document flow.

Scope

This PR is limited to legal/settings compliance work from this chat. Checkout, payment-intent, donation, product, Android build, and unrelated generated mock changes are not included.

Testing

  • dart format --output=none --set-exit-if-changed on the touched Dart files
  • git diff --check
  • git diff --check origin/main...HEAD

Not completed locally:

  • flutter test --no-pub test/settings_legal_information_test.dart stalled during Flutter test loading before any tests ran
  • dart analyze previously stalled during analysis startup in this local toolchain

Review notes

  • The Privacy Policy text is sourced from the provided DOCX and still needs product/legal review before launch. It includes items such as 2024-13-11, [insert registered address], Facebook auth references, and MANGOPAY references that may not match the current app implementation.
  • The Terms and Conditions text is sourced from the provided DOCX. The PDF was checked but its extracted text was unreliable due to font mapping issues. The Terms copy also needs product/legal review before launch because it includes placeholders or potentially stale implementation details such as [here], details here, Facebook verification, PayPal, currency conversion, and cherry Platform Limited wording.
  • The implementation intentionally keeps both documents in-app rather than opening a browser, matching the compliance goal in issue Policies: Integrate Privacy Policy, Terms of Service & Support Details into App #389.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

📝 Walkthrough

Walkthrough

This PR adds in-app access to the app's Privacy Policy through a new legal information hub in settings. A comprehensive GDPR-compliant privacy policy document is bundled as an asset and displayed via a dedicated page with structured text parsing and theme-aware rendering. Navigation routes and settings wiring connect the user entry point to the full document display.

Changes

Privacy Policy & Legal Pages

Layer / File(s) Summary
Privacy Policy Document
assets/legal/privacy_policy.txt
Complete GDPR-based privacy policy covering data collection across account creation, authentication, profile visibility, messaging, reviews, payments, security, and third-party services with stated legal bases and retention periods.
Asset Configuration & UI Strings
pubspec.yaml, lib/core/config/app_strings.dart
Privacy policy asset directory registered; Privacy Policy screen title and error message string constants added.
Legal Information Landing Page
lib/features/settings/legal_information_page.dart
New LegalInformationPage renders settings-style index with Privacy Policy entry that navigates to the full policy document.
Privacy Policy Display with Text Parsing & Rendering
lib/features/settings/privacy_policy_page.dart
PrivacyPolicyPage loads privacy policy asset, parses text into blocks (title, metadata, numbered headings, paragraphs, bullets), and renders each with appropriate typography, heading spacing, and selectable text.
Navigation Routing & Settings Integration
lib/core/router/nav_routes.dart, lib/features/settings/settings_model.dart
Router registers /legal-information and /privacy-policy routes; settings model adds navigation callback and wires Privacy Policy link into account settings section.
Widget Tests for Legal Navigation Flow
test/settings_legal_information_test.dart
Tests verify settings-to-legal-information-to-privacy-policy navigation and assert expected content (title, date, section headings).

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested Reviewers

  • JaseElder

Poem

🐰 A privacy scroll unfurls with care,
GDPR's dance laid fair and square,
From payments to posts, each rule in place,
Users now see the policy face,
No more clicks beyond the app's embrace! 🍒

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR partially addresses the linked issue #389. It successfully implements the Privacy Policy in-app display and Settings integration, but does not cover Terms of Service acceptance during sign-up, dedicated Help & Support screen, or store metadata population, which are key acceptance criteria. Complete implementation of Terms of Service display with onboarding acceptance, add Help & Support screen with contact information, and verify store metadata includes Privacy Policy URL.
Out of Scope Changes check ⚠️ Warning The PR summary mentions checkout and payment-intent changes spanning multiple files, which appear to be outside the scope of the Privacy Policy feature defined by issue #389 and the PR title. Clarify whether checkout/payment-intent changes belong in this PR or should be split into a separate PR; ensure all changes directly support the Privacy Policy feature scope.
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title 'Add in-app legal documents to Settings' accurately and concisely describes the main change: integrating a Privacy Policy document into the Settings section accessible in-app.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cherryprivacypolicybranch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@CherryCIC CherryCIC requested a review from MattGoodwin0 May 18, 2026 13:55
@CherryCIC CherryCIC marked this pull request as ready for review May 18, 2026 14:00
@CherryCIC CherryCIC requested a review from JaseElder May 18, 2026 14:01
@CherryCIC CherryCIC self-assigned this May 18, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (3)
lib/features/settings/legal_information_page.dart (1)

9-12: ⚡ Quick win

Use named route navigation to keep routing centralized.

This bypasses AppRoutes.privacyPolicyPage and duplicates routing behavior locally. Prefer Navigator.pushNamed (or your navigation provider) for consistency with the rest of the settings flow.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/settings/legal_information_page.dart` around lines 9 - 12, The
_navigateToPrivacyPolicy function currently pushes a MaterialPageRoute directly
to PrivacyPolicyPage, bypassing centralized routing; replace that local route
creation with a named route call using AppRoutes.privacyPolicyPage (e.g., use
Navigator.pushNamed with the same context and route name) so routing is
consistent with the rest of the app and any route-level configuration or
middleware is applied; update any imports/usages as needed and remove the
MaterialPageRoute usage tied to PrivacyPolicyPage.
lib/features/settings/privacy_policy_page.dart (1)

22-24: ⚡ Quick win

Cache the asset-loading future instead of recreating it in build.

Creating loadString(_assetPath) inline means rebuilds can re-trigger reads. Store the future once (e.g., in initState) and reuse it in FutureBuilder.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/settings/privacy_policy_page.dart` around lines 22 - 24, The
FutureBuilder is calling DefaultAssetBundle.of(context).loadString(_assetPath)
directly in build which recreates the future on every rebuild; fix by creating a
state field (e.g., Future<String> _policyFuture) and initialize it once in
initState using DefaultAssetBundle.of(context)...loadString(_assetPath) (or load
via rootBundle if context not available in initState), then pass _policyFuture
into FutureBuilder instead of calling loadString inline so the asset read is
cached across rebuilds.
test/settings_legal_information_test.dart (1)

39-42: 💤 Low value

Replace custom pump loop with pumpAndSettle().

The manual pump loop is inconsistent with the test's own usage of pumpAndSettle() on line 35, which handles animations and async operations automatically. Since pumpAndSettle() works reliably elsewhere in the same test, this custom pattern should be refactored:

Suggested change
    await tester.tap(find.text(AppStrings.privacyPolicyText));
-   for (var i = 0; i < 10; i++) {
-     await tester.pump(const Duration(milliseconds: 100));
-   }
+   await tester.pumpAndSettle();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/settings_legal_information_test.dart` around lines 39 - 42, After
tapping the privacy policy link (the tester.tap call using
find.text(AppStrings.privacyPolicyText)), remove the manual for-loop with
repeated tester.pump(Duration(milliseconds: 100)) calls and replace it with a
single await tester.pumpAndSettle(); so the test waits for animations and async
work consistently (use the same pumpAndSettle pattern already used earlier
around line 35).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@assets/legal/privacy_policy.txt`:
- Line 3: Replace the invalid date string "Date last updated: 2024-13-11" in the
privacy policy header with a valid YYYY-MM-DD date (e.g., "Date last updated:
2024-11-13"); ensure the header uses an unambiguous ISO format and update any
matching occurrences of that exact header line if present elsewhere in the file.
- Around line 487-494: Remove the duplicate 2.4.6 section and keep a single
canonical "2.4.6. To delete or hide content that is illegal or violates our GTC"
paragraph (the version that includes the retention period and legal basis), then
update any cross-references or numbering elsewhere that pointed to the removed
duplicate to ensure there are no conflicting references to 2.4.6.
- Line 9: Replace the unresolved placeholder "[insert registered address]" in
the sentence that begins "The data controller for your personal data is cherry,
Ltd., headquartered at [insert registered address]." with the company's actual
registered address (the official registered office of cherry, Ltd.) so the
Privacy Policy contains the real legal address; ensure the replacement appears
exactly where the placeholder token is and keep the surrounding phrasing
unchanged.

In `@lib/features/checkout/checkout_page.dart`:
- Around line 191-194: The current validation always sets _errorMessage to
AppStrings.checkoutDeliveryAddressRequired when
viewModel.hasValidDeliveryDetails is false; update the logic inside the setState
branch that handles delivery validation to choose a pickup-specific message when
the order is a pickup and no locker is selected (use viewModel.isPickup or
equivalent and viewModel.selectedLocker/locker selection state) — e.g., set
_errorMessage to a new AppStrings.checkoutPickupLockerRequired (or an existing
pickup string) when pickup validation fails, otherwise keep
AppStrings.checkoutDeliveryAddressRequired.

In `@lib/features/checkout/checkout_view_model.dart`:
- Around line 72-74: The canRetryOrderCreation getter only allows retries when
_checkoutFlowState == CheckoutFlowState.orderCreationFailure, which prevents
retries after createOrder sets CheckoutFlowState.shipmentFailure; modify the
getter to also return true when _checkoutFlowState ==
CheckoutFlowState.shipmentFailure (e.g., include an OR check for
CheckoutFlowState.shipmentFailure) while still validating that
_lastPaymentIntentId?.trim().isNotEmpty is true so paid checkouts can be
recovered.

In `@lib/features/donation/widgets/donation_dropdown_field.dart`:
- Around line 32-38: The component currently copies widget.selectedValue into
selectedDropdownItem inside didUpdateWidget without checking that the value
still exists in the current dropdownList, which can leave a stale/invalid
selection; update didUpdateWidget (and the other assignment site around lines
79-80) to validate the incoming widget.selectedValue against widget.dropdownList
first, and if it is not present clear selectedDropdownItem (or set it to a
sensible fallback such as the first item) inside setState, and if your widget
exposes a callback (e.g. onChanged/onValueChanged) invoke it to propagate the
change to the parent so state stays consistent.

In `@test/settings_legal_information_test.dart`:
- Line 45: The test contains an invalid date string in the expectation: change
the text in expect(find.text('Date last updated: 2024-13-11'), findsOneWidget)
to a valid date (for example 'Date last updated: 2024-12-11' or 'Date last
updated: 2024-11-13') and ensure the corresponding privacy policy asset/content
that SettingsLegalInformation (or the widget under test) renders is updated to
match the same valid date so the expect(find.text(...), findsOneWidget)
assertion passes.

---

Nitpick comments:
In `@lib/features/settings/legal_information_page.dart`:
- Around line 9-12: The _navigateToPrivacyPolicy function currently pushes a
MaterialPageRoute directly to PrivacyPolicyPage, bypassing centralized routing;
replace that local route creation with a named route call using
AppRoutes.privacyPolicyPage (e.g., use Navigator.pushNamed with the same context
and route name) so routing is consistent with the rest of the app and any
route-level configuration or middleware is applied; update any imports/usages as
needed and remove the MaterialPageRoute usage tied to PrivacyPolicyPage.

In `@lib/features/settings/privacy_policy_page.dart`:
- Around line 22-24: The FutureBuilder is calling
DefaultAssetBundle.of(context).loadString(_assetPath) directly in build which
recreates the future on every rebuild; fix by creating a state field (e.g.,
Future<String> _policyFuture) and initialize it once in initState using
DefaultAssetBundle.of(context)...loadString(_assetPath) (or load via rootBundle
if context not available in initState), then pass _policyFuture into
FutureBuilder instead of calling loadString inline so the asset read is cached
across rebuilds.

In `@test/settings_legal_information_test.dart`:
- Around line 39-42: After tapping the privacy policy link (the tester.tap call
using find.text(AppStrings.privacyPolicyText)), remove the manual for-loop with
repeated tester.pump(Duration(milliseconds: 100)) calls and replace it with a
single await tester.pumpAndSettle(); so the test waits for animations and async
work consistently (use the same pumpAndSettle pattern already used earlier
around line 35).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f255b081-8c27-4c72-b799-ddf88940ab6d

📥 Commits

Reviewing files that changed from the base of the PR and between 132c18f and b2109d4.

📒 Files selected for processing (20)
  • android/app/build.gradle.kts
  • assets/legal/privacy_policy.txt
  • lib/core/config/app_strings.dart
  • lib/core/router/nav_routes.dart
  • lib/core/services/network/api_service.dart
  • lib/features/checkout/checkout_page.dart
  • lib/features/checkout/checkout_repository.dart
  • lib/features/checkout/checkout_view_model.dart
  • lib/features/checkout/models/payment_intent.dart
  • lib/features/checkout/models/payment_intent.g.dart
  • lib/features/donation/widgets/donation_dropdown_field.dart
  • lib/features/products/product_page.dart
  • lib/features/settings/legal_information_page.dart
  • lib/features/settings/privacy_policy_page.dart
  • lib/features/settings/settings_model.dart
  • pubspec.yaml
  • test/auth_ui_test.mocks.dart
  • test/checkout_view_model_test.dart
  • test/checkout_view_model_test.mocks.dart
  • test/settings_legal_information_test.dart

@@ -0,0 +1,695 @@
Privacy Policy

Date last updated: 2024-13-11
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix invalid “last updated” date format in policy header.

2024-13-11 is not a valid calendar date. Use a valid, unambiguous date (for example 2024-11-13 in YYYY-MM-DD format).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@assets/legal/privacy_policy.txt` at line 3, Replace the invalid date string
"Date last updated: 2024-13-11" in the privacy policy header with a valid
YYYY-MM-DD date (e.g., "Date last updated: 2024-11-13"); ensure the header uses
an unambiguous ISO format and update any matching occurrences of that exact
header line if present elsewhere in the file.


1. General
This Privacy Policy applies to the online platform cherry (the "Website") and the associated app (the "App") (collectively referred to as the "Platform").
The data controller for your personal data is cherry, Ltd., headquartered at [insert registered address]. The data controller is referred to as "we," "us," or "cherry." More details about how to contact us can be found at the end of this Privacy Policy.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove placeholder controller address before release.

[insert registered address] is unresolved placeholder text in a legal disclosure and should be replaced with the actual registered address.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@assets/legal/privacy_policy.txt` at line 9, Replace the unresolved
placeholder "[insert registered address]" in the sentence that begins "The data
controller for your personal data is cherry, Ltd., headquartered at [insert
registered address]." with the company's actual registered address (the official
registered office of cherry, Ltd.) so the Privacy Policy contains the real legal
address; ensure the replacement appears exactly where the placeholder token is
and keep the surrounding phrasing unchanged.

Comment on lines +487 to +494
2.4.6. To delete or hide content that is illegal or violates our GTC

If you upload content (e.g., listed items, profile descriptions, or messages) on our Platform that is illegal or violates our General Terms and Conditions (GTC), we will remove or hide such content. However, we will retain the deleted content as evidence of the violation.

The legal basis for this collection and use of personal data is the performance of a contract (GTC) to which you are a party (Art. 6 (1) (b) of the GDPR), or compliance with legal obligations to which cherry is subject (Art. 6 (1) (c) of the GDPR).

Deleted content will be retained for 7 months from the date of removal.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Eliminate duplicated section 2.4.6 to avoid legal ambiguity.

Section 2.4.6 appears twice with near-duplicate content. Keep a single canonical section to prevent conflicting references.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@assets/legal/privacy_policy.txt` around lines 487 - 494, Remove the duplicate
2.4.6 section and keep a single canonical "2.4.6. To delete or hide content that
is illegal or violates our GTC" paragraph (the version that includes the
retention period and legal basis), then update any cross-references or numbering
elsewhere that pointed to the removed duplicate to ensure there are no
conflicting references to 2.4.6.

Comment on lines 191 to 194
if (!viewModel.hasValidDeliveryDetails) {
setState(() {
_errorMessage = AppStrings.checkoutPaymentMethodRequired;
_errorMessage = AppStrings.checkoutDeliveryAddressRequired;
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use pickup-specific validation copy for pickup delivery failures.

Line 193 always shows checkoutDeliveryAddressRequired. For pickup without selected locker, this is misleading.

Suggested fix
                       if (!viewModel.hasValidDeliveryDetails) {
                         setState(() {
-                          _errorMessage = AppStrings.checkoutDeliveryAddressRequired;
+                          _errorMessage = viewModel.deliveryChoice == 'pickup'
+                              ? AppStrings.checkoutPickupLockerRequired
+                              : AppStrings.checkoutDeliveryAddressRequired;
                         });
                         return;
                       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!viewModel.hasValidDeliveryDetails) {
setState(() {
_errorMessage = AppStrings.checkoutPaymentMethodRequired;
_errorMessage = AppStrings.checkoutDeliveryAddressRequired;
});
if (!viewModel.hasValidDeliveryDetails) {
setState(() {
_errorMessage = viewModel.deliveryChoice == 'pickup'
? AppStrings.checkoutPickupLockerRequired
: AppStrings.checkoutDeliveryAddressRequired;
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/checkout/checkout_page.dart` around lines 191 - 194, The current
validation always sets _errorMessage to
AppStrings.checkoutDeliveryAddressRequired when
viewModel.hasValidDeliveryDetails is false; update the logic inside the setState
branch that handles delivery validation to choose a pickup-specific message when
the order is a pickup and no locker is selected (use viewModel.isPickup or
equivalent and viewModel.selectedLocker/locker selection state) — e.g., set
_errorMessage to a new AppStrings.checkoutPickupLockerRequired (or an existing
pickup string) when pickup validation fails, otherwise keep
AppStrings.checkoutDeliveryAddressRequired.

Comment on lines +72 to +74
bool get canRetryOrderCreation =>
_checkoutFlowState == CheckoutFlowState.orderCreationFailure &&
(_lastPaymentIntentId?.trim().isNotEmpty ?? false);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Retry is blocked after shipment failure, leaving paid checkouts unrecoverable.

When createOrder sets CheckoutFlowState.shipmentFailure (Line 541), this getter still returns false, so retry is never offered even with a valid _lastPaymentIntentId.

Suggested fix
   bool get canRetryOrderCreation =>
-      _checkoutFlowState == CheckoutFlowState.orderCreationFailure &&
+      (_checkoutFlowState == CheckoutFlowState.orderCreationFailure ||
+          _checkoutFlowState == CheckoutFlowState.shipmentFailure) &&
       (_lastPaymentIntentId?.trim().isNotEmpty ?? false);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/checkout/checkout_view_model.dart` around lines 72 - 74, The
canRetryOrderCreation getter only allows retries when _checkoutFlowState ==
CheckoutFlowState.orderCreationFailure, which prevents retries after createOrder
sets CheckoutFlowState.shipmentFailure; modify the getter to also return true
when _checkoutFlowState == CheckoutFlowState.shipmentFailure (e.g., include an
OR check for CheckoutFlowState.shipmentFailure) while still validating that
_lastPaymentIntentId?.trim().isNotEmpty is true so paid checkouts can be
recovered.

Comment on lines +32 to +38
@override
void didUpdateWidget(covariant DonationDropdownField oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.selectedValue != widget.selectedValue) {
selectedDropdownItem = widget.selectedValue;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Guard against stale selection when dropdown options change.

selectedDropdownItem is synced from parent value only, but not validated against the current dropdownList. If the selected value is removed from the list, the field can hold an invalid selection state.

Suggested fix
   `@override`
   void didUpdateWidget(covariant DonationDropdownField oldWidget) {
     super.didUpdateWidget(oldWidget);
-    if (oldWidget.selectedValue != widget.selectedValue) {
-      selectedDropdownItem = widget.selectedValue;
+    final incoming = widget.selectedValue;
+    if (oldWidget.selectedValue != incoming ||
+        !widget.dropdownList.contains(selectedDropdownItem)) {
+      selectedDropdownItem =
+          (incoming != null && widget.dropdownList.contains(incoming))
+              ? incoming
+              : null;
     }
   }

   `@override`
   Widget build(BuildContext context) {
+    final effectiveSelected =
+        (selectedDropdownItem != null &&
+            widget.dropdownList.contains(selectedDropdownItem))
+        ? selectedDropdownItem
+        : null;
+
     return Padding(
       padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
       child: DropdownButtonFormField<String>(
-        key: ValueKey(selectedDropdownItem),
-        initialValue: selectedDropdownItem,
+        key: ValueKey(effectiveSelected),
+        initialValue: effectiveSelected,

Also applies to: 79-80

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/donation/widgets/donation_dropdown_field.dart` around lines 32 -
38, The component currently copies widget.selectedValue into
selectedDropdownItem inside didUpdateWidget without checking that the value
still exists in the current dropdownList, which can leave a stale/invalid
selection; update didUpdateWidget (and the other assignment site around lines
79-80) to validate the incoming widget.selectedValue against widget.dropdownList
first, and if it is not present clear selectedDropdownItem (or set it to a
sensible fallback such as the first item) inside setState, and if your widget
exposes a callback (e.g. onChanged/onValueChanged) invoke it to propagate the
change to the parent so state stays consistent.

}

expect(find.text(AppStrings.privacyPolicyText), findsWidgets);
expect(find.text('Date last updated: 2024-13-11'), findsOneWidget);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Invalid date format: month 13 does not exist.

The date string '2024-13-11' contains an invalid month value (13). Months must be between 1 and 12. This will either cause the test to fail or verify incorrect placeholder content in the privacy policy asset.

Please correct to a valid date (e.g., '2024-12-11' or '2024-11-13') and ensure the corresponding asset content is also updated before production.

📅 Proposed fix
-    expect(find.text('Date last updated: 2024-13-11'), findsOneWidget);
+    expect(find.text('Date last updated: 2024-12-11'), findsOneWidget);

(Adjust the month/day as appropriate for your actual date.)

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
expect(find.text('Date last updated: 2024-13-11'), findsOneWidget);
expect(find.text('Date last updated: 2024-12-11'), findsOneWidget);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/settings_legal_information_test.dart` at line 45, The test contains an
invalid date string in the expectation: change the text in
expect(find.text('Date last updated: 2024-13-11'), findsOneWidget) to a valid
date (for example 'Date last updated: 2024-12-11' or 'Date last updated:
2024-11-13') and ensure the corresponding privacy policy asset/content that
SettingsLegalInformation (or the widget under test) renders is updated to match
the same valid date so the expect(find.text(...), findsOneWidget) assertion
passes.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b2109d419c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +718 to +720
_nestedMapValue(map['shipment'], 'status'),
_nestedMapValue(map['data'], 'shipmentStatus'),
_nestedMapValue(map['data'], 'shipment_status'),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Parse nested shipment status from wrapped order responses

Update shipment status extraction to handle data.shipment.status when the create-order API returns a wrapped payload. This commit changed createOrder to return the full response object, but _shipmentStatusFromResponse only checks top-level shipment and a few data scalar keys. If the backend responds like { "data": { "shipment": { "status": "pending"|"failed" }}}, the code falls through to the default success path, marking checkout as shipmentCreated and navigating users as if delivery succeeded.

Useful? React with 👍 / 👎.

@CherryCIC CherryCIC force-pushed the cherryprivacypolicybranch branch from b2109d4 to 1ddffb7 Compare May 18, 2026 15:33
@CherryCIC CherryCIC changed the title Add in-app Privacy Policy and checkout payment intent updates Add in-app Privacy Policy to Settings May 18, 2026
@CherryCIC
Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@assets/legal/privacy_policy.txt`:
- Around line 198-206: The subsection numbering is out of sequence (currently
labeled 2.2.13 where a 2.2.12 is missing) and the internal cross-reference to
2.2.12 (mentioned later) is therefore broken; renumber the affected subsection
headings in this block so the sequence includes 2.2.12 then 2.2.13 (e.g., change
the current "2.2.13. To improve our Platform" to "2.2.12." and shift subsequent
2.2.x headings accordingly), and update the internal reference that currently
points to "2.2.12" (the occurrence referenced in the review) to match the
corrected numbering so all cross-references are consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0e08712e-02de-4283-b3c9-c294ea442379

📥 Commits

Reviewing files that changed from the base of the PR and between b2109d4 and 1ddffb7.

📒 Files selected for processing (8)
  • assets/legal/privacy_policy.txt
  • lib/core/config/app_strings.dart
  • lib/core/router/nav_routes.dart
  • lib/features/settings/legal_information_page.dart
  • lib/features/settings/privacy_policy_page.dart
  • lib/features/settings/settings_model.dart
  • pubspec.yaml
  • test/settings_legal_information_test.dart
✅ Files skipped from review due to trivial changes (1)
  • lib/core/config/app_strings.dart
🚧 Files skipped from review as they are similar to previous changes (5)
  • pubspec.yaml
  • test/settings_legal_information_test.dart
  • lib/features/settings/settings_model.dart
  • lib/features/settings/privacy_policy_page.dart
  • lib/features/settings/legal_information_page.dart

Comment on lines +198 to +206
2.2.13. To improve our Platform

cherry is committed to the best performance of the Platform. When the Platform is being used, cherry gathers information about actions performed on the Platform (button clicks, visiting time, notifications read, other information depending on a particular business case) and other data described under 2.1, 2.2, 2.5, 2.6, and 4 of this Privacy Policy in order to help us make decisions on how to improve the Platform and make it a better experience for our members.

Legal basis for such collection and use is our legitimate interest to maintain performance and improve the Platform (Art. 6 (1) (f) of the GDPR).

We collect and use your personal data for this purpose until the deactivation of your cherry account or for 5 years of inactivity on your account.

2.2.14. To conduct surveys
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix subsection numbering and broken internal cross-reference.

Line 198 starts at 2.2.13, but earlier 2.2.x sections are not present in this document, and Line 578 references 2.2.12 (missing). This creates legal-text navigation ambiguity.

Proposed minimal fix
-2.2.13. To improve our Platform
+2.2.1. To improve our Platform

-2.2.14. To conduct surveys
+2.2.2. To conduct surveys

-2.2.15. To conduct interviews
+2.2.3. To conduct interviews

-2.2.16. To enable you to share your user journey
+2.2.4. To enable you to share your user journey

-2.2.17. To enable automatic content translation
+2.2.5. To enable automatic content translation

-This data may also be used to improve the Platform and enhance user experience (see 2.2.12).
+This data may also be used to improve the Platform and enhance user experience (see 2.2.1).

Also applies to: 578-578

🧰 Tools
🪛 LanguageTool

[style] ~200-~200: Consider a more concise word here.
Context: ... 2.5, 2.6, and 4 of this Privacy Policy in order to help us make decisions on how to improv...

(IN_ORDER_TO_PREMIUM)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@assets/legal/privacy_policy.txt` around lines 198 - 206, The subsection
numbering is out of sequence (currently labeled 2.2.13 where a 2.2.12 is
missing) and the internal cross-reference to 2.2.12 (mentioned later) is
therefore broken; renumber the affected subsection headings in this block so the
sequence includes 2.2.12 then 2.2.13 (e.g., change the current "2.2.13. To
improve our Platform" to "2.2.12." and shift subsequent 2.2.x headings
accordingly), and update the internal reference that currently points to
"2.2.12" (the occurrence referenced in the review) to match the corrected
numbering so all cross-references are consistent.

@CherryCIC CherryCIC force-pushed the cherryprivacypolicybranch branch from 1ddffb7 to 9fc18e1 Compare May 18, 2026 17:42
@CherryCIC CherryCIC changed the title Add in-app Privacy Policy to Settings Add in-app legal documents to Settings May 18, 2026
Add Legal information entries for Privacy Policy and Terms and Conditions, bundle both document assets, and share the native legal document renderer across both screens.

Type: UI, routing, asset, and test update. Scope is limited to legal/settings compliance screens; no checkout, payment, donation, product, or platform build files are changed.

Testing: dart format --output=none --set-exit-if-changed completed for touched Dart files; git diff --cached --check and git diff --check origin/main...HEAD passed. flutter test --no-pub test/settings_legal_information_test.dart stalled in Flutter loading before tests ran, so runtime widget verification is still incomplete.
@CherryCIC CherryCIC force-pushed the cherryprivacypolicybranch branch from 9fc18e1 to 71fb73d Compare May 18, 2026 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Policies: Integrate Privacy Policy, Terms of Service & Support Details into App

1 participant