Skip to content

Referral UI updates#8916

Merged
jigar-f merged 13 commits into
mainfrom
jigar/referral-ui-updates
Jul 23, 2026
Merged

Referral UI updates#8916
jigar-f merged 13 commits into
mainfrom
jigar/referral-ui-updates

Conversation

@jigar-f

@jigar-f jigar-f commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

This pull request introduces a comprehensive referral rewards system, including backend model changes, UI updates, and local storage enhancements. The main focus is to allow users to earn and track free months of Lantern Pro when their referrals convert, and to display this information in the app. The changes span localization, data models, persistent storage, and user interface components.

Referral rewards system implementation:

  • Added ReferralModel to user.dart and integrated it into UserDataModel, including serialization/deserialization logic for storing and retrieving referral data. [1] [2] [3] [4] [5]
  • Introduced extension methods in user_data.dart to compute total referral bonus days and months earned, making it easy to display and use this information throughout the app.

Localization and UI updates:

  • Added new localized strings to en.po for referral program messaging, including descriptions, reward notifications, and download link instructions.
  • Enhanced the account screen to display the number of free months earned from referrals as a subtitle in the plan section. [1] [2]
  • Updated the "Invite Friends" screen with a new description, improved layout, and integration of referral code and bonus months display. [1] [2]

Persistent storage and reward dialog:

  • Added methods to LocalStorageService to track which converted referrals have already triggered the reward dialog, ensuring users are notified only once per referral. [1] [2]
  • Implemented logic in home.dart to listen for new converted referrals and show a congratulatory dialog when appropriate. [1] [2]

Direct download links:

  • Added direct download URLs for Android, Windows, and Mac installers to app_urls.dart, to facilitate sharing with friends during the referral process.

Summary by CodeRabbit

  • New Features

    • Enhanced invite/referral experience with earned-month tracking, conversion messaging, and localized completion/instructions.
    • Added a one-time “friend upgraded to Pro” reward dialog with a share-referral-code action.
    • Introduced a download links sheet with platform selection, copy-to-clipboard, direct installer links, and Android QR code support.
  • Improvements

    • Referral bonus month messaging now appears in the account and referral checkout flows when applicable.
    • “Get 30 days of pro free” is hidden on store-distributed versions.
  • Localization

    • Updated referral/invite text (including “+ 1 additional month free”).

Copilot AI review requested due to automatic review settings July 20, 2026 16:07
@jigar-f jigar-f self-assigned this Jul 20, 2026
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Referral data is added to user models and local storage, with derived bonus totals. The invite page gains download-link and QR-code actions, while home displays conversion rewards. Account, settings, and plan messaging update referral presentation and store-version visibility.

Changes

Referral and invite flow

Layer / File(s) Summary
Referral data and persistence
lib/core/models/user.dart, lib/core/extensions/user_data.dart, lib/core/services/local_storage_service.dart
Referral records are serialized on user data, converted referrals produce earned-day and month totals, and seen conversion IDs are persisted locally.
Invite and download flow
lib/features/setting/invite_friends.dart, lib/core/common/app_urls.dart, pubspec.yaml, assets/locales/en.po
The invite page adds bonus-month display, download actions, platform URLs, copying feedback, Android QR rendering, and supporting localized strings.
Referral reward notification
lib/features/setting/referral_reward_dialog.dart, lib/features/home/home.dart, lib/core/common/app_dialog.dart
Home checks converted referrals after initialization and opens a localized reward dialog for unseen conversions, including referral-code sharing; custom dialogs now expose their completion future.
Account and settings gating
lib/features/account/account.dart, lib/features/setting/setting.dart
The account subscription tile displays earned referral months, and the free-Pro tile is hidden on store versions.
Referral plan messaging
lib/core/common/common.dart, assets/locales/en.po, lib/features/auth/choose_payment_method.dart, lib/features/plans/plans_list.dart, lib/features/plans/plan_item.dart
Referral messaging now uses the one-month localized copy through a parameterless helper, with callers updated accordingly.

Radiance dependency update

Layer / File(s) Summary
Radiance version update
go.mod
The required github.com/getlantern/radiance pseudo-version is updated.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Home
  participant homeProvider
  participant checkAndShowReferralReward
  participant LocalStorageService
  participant ReferralRewardDialog
  participant SharePlus
  homeProvider->>Home: user update
  Home->>checkAndShowReferralReward: schedule post-frame check
  checkAndShowReferralReward->>LocalStorageService: load seen referral IDs
  checkAndShowReferralReward->>LocalStorageService: save converted referral IDs
  checkAndShowReferralReward->>ReferralRewardDialog: show reward dialog
  ReferralRewardDialog->>SharePlus: share referral message
Loading

Possibly related PRs

Suggested reviewers: atavism, copilot, atavism

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is related to the PR, but it is too vague to convey the main change beyond generic referral UI work. Use a more specific title that mentions the referral rewards flow, such as adding referral reward tracking and dialogs.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jigar/referral-ui-updates

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a referral rewards experience to Lantern, spanning user-data modeling, persistent “seen” tracking for one-time reward notifications, and UI updates to surface earned referral months and share download links.

Changes:

  • Introduces referral data modeling (ReferralModel) and computed referral bonus helpers (referralBonusDays / referralBonusMonths).
  • Adds one-time “referral converted” reward dialog logic backed by local storage state.
  • Updates Account + Invite Friends UI and adds direct download links (plus QR rendering dependency) to support referral sharing.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
pubspec.yaml Adds qr_flutter dependency for QR rendering.
pubspec.lock Locks transitive qr + qr_flutter versions.
lib/features/setting/setting.dart Hides the “Get 30 days of Pro free” tile in store builds.
lib/features/setting/referral_reward_dialog.dart Implements converted-referral reward dialog and “seen” gating.
lib/features/setting/invite_friends.dart Refreshes Invite Friends UI, adds earned-months display and download-links sheet with QR.
lib/features/home/home.dart Hooks into user refreshes to trigger referral reward dialog post-frame.
lib/features/account/account.dart Displays earned referral months as a plan subtitle.
lib/core/services/local_storage_service.dart Adds persistence for “seen converted referrals”.
lib/core/models/user.dart Adds ReferralModel and includes it in UserDataModel JSON parsing/serialization.
lib/core/extensions/user_data.dart Adds referral bonus day/month computed helpers.
lib/core/common/app_urls.dart Adds direct download URLs for Android/Windows/macOS installers.
assets/locales/en.po Adds referral-related localized strings used by the updated UI/dialog.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/core/models/user.dart Outdated
Comment thread lib/features/setting/referral_reward_dialog.dart
Comment thread lib/features/setting/invite_friends.dart
Comment thread lib/features/setting/invite_friends.dart Outdated
Comment thread assets/locales/en.po

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/features/setting/invite_friends.dart (1)

112-120: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Guard against setting a disposed ValueNotifier after the copy delay.

Both _onCopyTap implementations await Future.delayed(...) then mutate isCopied.value. If the widget/sheet is disposed before the delay elapses, this throws A ValueNotifier<bool> was used after being disposed. in debug/profile builds. Use useIsMounted() from flutter_hooks to guard the post-delay write.

🔒 Proposed fix using useIsMounted
-  Future<void> _onCopyTap(
-    ValueNotifier<bool> isCopied,
-    String referralCode,
-  ) async {
+  Future<void> _onCopyTap(
+    ValueNotifier<bool> isCopied,
+    String referralCode,
+    bool Function() isMounted,
+  ) async {
     copyToClipboard(referralCode);
     isCopied.value = true;
     await Future.delayed(Duration(seconds: 1));
-    isCopied.value = false;
+    if (isMounted()) isCopied.value = false;
   }

Also applies to: 356-364

🤖 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/setting/invite_friends.dart` around lines 112 - 120, Update both
_onCopyTap implementations to obtain the flutter_hooks useIsMounted guard and
check it after the one-second delay before assigning isCopied.value = false;
keep the immediate copied-state update and clipboard behavior unchanged.
🧹 Nitpick comments (1)
lib/features/setting/invite_friends.dart (1)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated "split %s into bold TextSpans" logic across two new files. Both _reminderCallout and _messageSpans independently reimplement the same fragile pattern of manually splitting a localized string on the literal '%s' to interleave bold spans.

  • lib/features/setting/invite_friends.dart#L318-354: extract a shared helper (e.g. buildRichTextWithPlaceholders(template, values, boldStyle)) that both this and _messageSpans can use, rather than duplicating the split logic.
  • lib/features/setting/referral_reward_dialog.dart#L112-130: switch _messageSpans to use the same shared helper once extracted.
🤖 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/setting/invite_friends.dart` at line 1, Extract the duplicated
placeholder-splitting and bold-span construction from _reminderCallout and
_messageSpans into a shared helper, such as buildRichTextWithPlaceholders,
preserving the existing template, values, and boldStyle behavior. Update both
methods in invite_friends.dart and referral_reward_dialog.dart to call the
helper instead of manually splitting localized strings on '%s'.
🤖 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 `@lib/core/models/user.dart`:
- Around line 82-109: Update ReferralModel.fromJson so the converted field
evaluates with a strict true check rather than preserving arbitrary JSON types;
use the converted == true pattern so null, strings, numbers, and other
unexpected values become false while actual true remains true.

In `@lib/features/setting/invite_friends.dart`:
- Line 21: Update the referral flow around the bonusMonths calculation to use
the existing referralBonusMonths value instead of legacyUserData.bonusMonths,
keeping the displayed total consistent with other referral surfaces. Fix the
months_earned label to use singular wording when the value is 1 and plural
wording otherwise.

In `@lib/features/setting/referral_reward_dialog.dart`:
- Around line 18-51: Update checkAndShowReferralReward and
_showReferralRewardDialog to preserve exactly-once behavior: persist the union
of previously seen IDs and all currently converted referral IDs, reserve the
dialog-visible state before any await to prevent overlapping calls, and reset
_rewardDialogVisible whenever the dialog future completes, including
outside/back dismissal rather than only button callbacks.

---

Outside diff comments:
In `@lib/features/setting/invite_friends.dart`:
- Around line 112-120: Update both _onCopyTap implementations to obtain the
flutter_hooks useIsMounted guard and check it after the one-second delay before
assigning isCopied.value = false; keep the immediate copied-state update and
clipboard behavior unchanged.

---

Nitpick comments:
In `@lib/features/setting/invite_friends.dart`:
- Line 1: Extract the duplicated placeholder-splitting and bold-span
construction from _reminderCallout and _messageSpans into a shared helper, such
as buildRichTextWithPlaceholders, preserving the existing template, values, and
boldStyle behavior. Update both methods in invite_friends.dart and
referral_reward_dialog.dart to call the helper instead of manually splitting
localized strings on '%s'.
🪄 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: 2b6b06bb-2f18-41f2-a7ba-3b2b5349c85f

📥 Commits

Reviewing files that changed from the base of the PR and between 1728722 and 1fc25e4.

⛔ Files ignored due to path filters (1)
  • pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • assets/locales/en.po
  • lib/core/common/app_urls.dart
  • lib/core/extensions/user_data.dart
  • lib/core/models/user.dart
  • lib/core/services/local_storage_service.dart
  • lib/features/account/account.dart
  • lib/features/home/home.dart
  • lib/features/setting/invite_friends.dart
  • lib/features/setting/referral_reward_dialog.dart
  • lib/features/setting/setting.dart
  • pubspec.yaml

Comment thread lib/core/models/user.dart
Comment thread lib/features/setting/invite_friends.dart Outdated
Comment thread lib/features/setting/referral_reward_dialog.dart

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
lib/core/common/app_dialog.dart (1)

175-181: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make callers explicitly handle the returned Future.

lib/features/account/account.dart:404 still calls customDialog from a synchronous method without await or unawaited. Make that caller async and await the dialog, or explicitly use unawaited(...) if fire-and-forget behavior is intentional.

🤖 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/core/common/app_dialog.dart` around lines 175 - 181, Update the caller of
customDialog in the account flow to explicitly handle its returned Future: make
the surrounding method asynchronous and await customDialog, or use
unawaited(customDialog(...)) if the dialog should remain fire-and-forget. Ensure
the chosen handling preserves the intended behavior and satisfies async error
propagation.
🤖 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.

Nitpick comments:
In `@lib/core/common/app_dialog.dart`:
- Around line 175-181: Update the caller of customDialog in the account flow to
explicitly handle its returned Future: make the surrounding method asynchronous
and await customDialog, or use unawaited(customDialog(...)) if the dialog should
remain fire-and-forget. Ensure the chosen handling preserves the intended
behavior and satisfies async error propagation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ee185b79-5f62-4ece-a769-24675e10d9ae

📥 Commits

Reviewing files that changed from the base of the PR and between 1fc25e4 and d99051b.

📒 Files selected for processing (6)
  • assets/locales/en.po
  • lib/core/common/app_dialog.dart
  • lib/core/models/user.dart
  • lib/features/account/account.dart
  • lib/features/setting/invite_friends.dart
  • lib/features/setting/referral_reward_dialog.dart
🚧 Files skipped from review as they are similar to previous changes (5)
  • assets/locales/en.po
  • lib/core/models/user.dart
  • lib/features/setting/referral_reward_dialog.dart
  • lib/features/setting/invite_friends.dart
  • lib/features/account/account.dart

@jigar-f
jigar-f requested a review from atavism July 21, 2026 12:55
Copilot AI review requested due to automatic review settings July 22, 2026 08:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 15 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

lib/features/setting/referral_reward_dialog.dart:37

  • checkAndShowReferralReward persists converted referral IDs as "seen" before confirming the dialog can be shown. If the widget is disposed/unmounted before the dialog appears (or if showing the dialog throws), the referral can be permanently marked seen and the user will never be notified. Also, _rewardDialogVisible isn't guarded by a try/finally, so an exception could leave it stuck true.
  _rewardDialogVisible = true;

  // Mark as seen before showing so the dialog can't repeat. Merge with the
  // already-seen ids so referrals missing from this response stay seen.
  await storage.saveSeenConvertedReferrals(

Comment thread lib/core/common/app_dialog.dart
Comment thread lib/features/setting/invite_friends.dart Outdated
Copilot AI review requested due to automatic review settings July 22, 2026 08:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 15 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (2)

lib/features/setting/referral_reward_dialog.dart:37

  • Seen referral IDs are persisted before verifying context.mounted and before the dialog is actually shown. If the widget unmounts (or the dialog throws) after saving, the user may never see the reward dialog, and _rewardDialogVisible can remain stuck true if an exception occurs. Consider only persisting after the dialog successfully shows, and use try/finally to always reset the visibility flag.
  _rewardDialogVisible = true;

  // Mark as seen before showing so the dialog can't repeat. Merge with the
  // already-seen ids so referrals missing from this response stay seen.
  await storage.saveSeenConvertedReferrals(

lib/features/setting/invite_friends.dart:30

  • BaseScreen does not provide scrolling (it inserts the body directly into a Scaffold), but this screen now uses a non-scrollable Column with a Spacer(). On smaller devices / large text settings this is likely to overflow vertically with no way to scroll to the buttons. Consider restoring a SingleChildScrollView or restructuring as Column(children: [Expanded(SingleChildScrollView(...)), buttons]).
    return BaseScreen(
      title: 'invite_friends'.i18n,
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[

Comment thread assets/locales/en.po
Copilot AI review requested due to automatic review settings July 22, 2026 12:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 17 out of 19 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (4)

lib/features/setting/referral_reward_dialog.dart:39

  • The reward dialog is marked visible and referrals are persisted as "seen" before confirming the dialog can actually be shown. If the widget unmounts (or an exception occurs) before the dialog is displayed, the user can permanently miss the notification, and _rewardDialogVisible may never reset. Consider using try/finally to always reset the flag, checking context.mounted before showing, and persisting "seen" only after the dialog is successfully shown/dismissed. Also avoid forcing newMonths to at least 1 if bonusDaysEarned is unexpectedly < 30 to keep behavior consistent with referralBonusMonths.
  _rewardDialogVisible = true;

  // Mark as seen before showing so the dialog can't repeat. Merge with the
  // already-seen ids so referrals missing from this response stay seen.
  await storage.saveSeenConvertedReferrals(
    {...seen, ...converted.map((r) => r.userId)}.toList(),
  );

lib/features/auth/choose_payment_method.dart:540

  • getReferralMessage() is localized, but the UI removes the English word "free" via replaceAll('free', ''). In non-English locales this won’t strip anything, so you can end up displaying the localized word for “free” twice (once in the message and once in the right column), and it can also leave trailing whitespace in English. Prefer rendering the full localized message as-is and drop the separate "free" column (or introduce a dedicated i18n key that does not include the word “free”).
                    Text(
                      getReferralMessage().replaceAll('free', '').toTitleCase(),
                      style: theme.bodyMedium,
                    ),
                    Text(
                      'free'.i18n,
                      style: theme.bodyMedium!.copyWith(
                        color: context.textDisabled,
                      ),
                    ),

lib/features/setting/invite_friends.dart:33

  • BaseScreen doesn’t provide scrolling, and this screen’s body is a plain Column with fixed bottom buttons. With longer localized strings and/or smaller screens (e.g., landscape), this can overflow vertically. Consider making the content scrollable (e.g., SingleChildScrollView, or CustomScrollView/SliverFillRemaining to keep buttons reachable) to avoid render overflow.
    return BaseScreen(
      title: 'invite_friends'.i18n,
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16.0),
            child: Text(

assets/locales/en.po:1285

  • referral_message_2y uses singular “month” but should be plural for 2 months.
msgid "referral_message_1m"
msgstr "+ 1 additional month free"

msgid "referral_message_1y"
msgstr "+ 1 additional month free"

msgid "referral_message_2y"
msgstr "+ 2 additional month free"

Comment thread lib/features/setting/invite_friends.dart
Comment thread assets/locales/en.po
atavism and others added 2 commits July 23, 2026 14:00
* Fix Android user data startup race (#8915)

* Fix Android user data startup race

* code review updates

* code review updates

* Bump radiance for non-blocking fronted-config startup (#8920)

Bumps radiance to b72b27d, carrying the fronted-config init fix into the
client. domainfront (=> 2862f7a) moves with it as an indirect dep.

radiance no longer fetches the fronting config (fronted.yaml.gz) from
raw.githubusercontent.com synchronously on the init critical path — a fetch
that stalled startup for 30s per cold start where GitHub is blocked (China),
contributing to the Android "Pro users shown as logged-out" cluster
(getlantern/engineering#3716, symptom fixed in #8915). domainfront now owns
the config lifecycle (fetch off the critical path → persist → bootstrap from
the persisted copy), so startup does no blocking network I/O.

go.mod / go.sum only; ran `go mod tidy`. `go build ./...` passes.

Co-authored-by: Adam Fisk <a@lantern.io>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* Provide a writable WebView2 user-data folder on Windows (#8921)

* Provide webview path for Windows.

* go mod tidy: drop stray go-arg/go-scalar from go.sum

These entries were added to go.sum with no corresponding go.mod require and
nothing imports them, so go mod tidy removes them. Orphaned go.sum entries
can cause Go tooling (notably gomobile) to resolve transitive deps to older
hashed versions, so keep go.sum consistent with go.mod.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* windows/webview: bail on unexpanded path or failed folder creation

Address review on EnsureWebView2UserDataFolder:
- If %LOCALAPPDATA% (or any referenced var) is undefined, ExpandEnvironmentStringsW
  leaves it literal in the output; bail rather than create a garbage relative
  folder and set WEBVIEW2_USER_DATA_FOLDER to an unusable value.
- Only set WEBVIEW2_USER_DATA_FOLDER after confirming the target exists as a
  directory (via GetFileAttributesW); if CreateDirectoryW failed, leave WebView2
  to its default instead of pointing it at a nonexistent folder.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* windows/webview: narrow unexpanded-path guard to leading '%'

'%' is legal elsewhere in a Windows folder name (e.g. a username), so bailing
on any '%' could reject a valid expanded path. An undefined %LOCALAPPDATA%
leaves the template literal, so the result starts with '%' — check only the
leading char.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* windows/webview: treat empty WEBVIEW2_USER_DATA_FOLDER as unset

The null-buffer size probe returns >0 for a set-but-empty variable, so an
empty override would be respected and leave WebView2 with an unusable folder.
Read into a buffer instead: GetEnvironmentVariableW returns 0 when the var is
unset or empty, so we only bail on a real non-empty override.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: jigar-f <jigar@getlantern.org>
Co-authored-by: Adam Fisk <a@lantern.io>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* Bump radiance for multi-URL config racing (#8924)

Bumps radiance to 838849783d37 (kindling + domainfront move with it), carrying
the variadic WithConfigURL / multi-URL config racing capability
(getlantern/domainfront#17) into the client. No behavior change yet: the client
still fetches from the single GitHub config URL; the China-reachable mirror URL
will be added to the raced set once it's publishing (getlantern/engineering#3721).

go.mod / go.sum only; ran go mod tidy; go build ./... passes.

Co-authored-by: Adam Fisk <a@lantern.io>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* Fix referral reward UI edge cases

* code review changes

---------

Co-authored-by: Myles Horton <afisk@getlantern.org>
Co-authored-by: Adam Fisk <a@lantern.io>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: jigar-f <jigar@getlantern.org>
Copilot AI review requested due to automatic review settings July 23, 2026 08:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 19 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

lib/features/setting/referral_reward_dialog.dart:45

  • _showReferralRewardDialog(...) is not awaited. That makes _rewardDialogVisible reset (and referral IDs persist) before the dialog is dismissed, which can allow multiple dialogs to stack and defeats the “persist only after dismiss” behavior described in the comment.
    _showReferralRewardDialog(
      context: context,
      newMonths: newMonths,
      totalMonths: totalMonths,
      referralCode: user.legacyUserData.referral.toUpperCase(),

Comment thread lib/features/setting/referral_reward_dialog.dart Outdated
Comment thread lib/features/setting/invite_friends.dart Outdated
Copilot AI review requested due to automatic review settings July 23, 2026 09:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 19 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

lib/features/setting/referral_reward_dialog.dart:45

  • The reward dialog is not awaited, so saveSeenConvertedReferrals runs immediately and can mark referrals as “seen” even if the dialog fails to show or before the user dismisses it. This contradicts the comment above and makes it easier to miss notifications.
    _showReferralRewardDialog(
      context: context,
      newMonths: newMonths,
      totalMonths: totalMonths,
      referralCode: user.legacyUserData.referral.toUpperCase(),

Comment thread lib/features/setting/referral_reward_dialog.dart
Comment thread lib/features/home/home.dart
Copilot AI review requested due to automatic review settings July 23, 2026 09:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 19 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

lib/features/setting/referral_reward_dialog.dart:55

  • _showReferralRewardDialog() isn't awaited, so seen-referrals are persisted immediately (despite the comment) and _rewardDialogVisible is reset before the dialog is dismissed. This can lead to the reward dialog re-triggering on subsequent user refreshes and/or referrals being marked seen even if the dialog fails to display.
    _showReferralRewardDialog(
      context: context,
      newMonths: newMonths,
      totalMonths: totalMonths,
      referralCode: user.legacyUserData.referral.toUpperCase(),
    );

    // Persist only after the user dismisses the dialog. If the route cannot be
    // shown or the app exits first, the notification is retried next time.
    await storage.saveSeenConvertedReferrals(
      {...seen, ...converted.map((r) => r.userId)}.toList(),
    );

Comment thread lib/features/home/home.dart
Comment thread assets/locales/en.po
@jigar-f
jigar-f merged commit d1524d3 into main Jul 23, 2026
10 checks passed
@jigar-f
jigar-f deleted the jigar/referral-ui-updates branch July 23, 2026 09:29
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.

3 participants