Skip to content

Wire Share My Connection toggle in Dart UI (PR 4/4)#8730

Open
myleshorton wants to merge 3 commits intofisk/peer-ffifrom
fisk/peer-dart
Open

Wire Share My Connection toggle in Dart UI (PR 4/4)#8730
myleshorton wants to merge 3 commits intofisk/peer-ffifrom
fisk/peer-dart

Conversation

@myleshorton
Copy link
Copy Markdown
Contributor

Final PR in the four-PR client-side stack for Share My Connection. Stacks on #8729 (FFI exports); base = `fisk/peer-ffi`. Re-target to `main` after #8729 merges.

Combined with the rest of the stack — radiance #458 / #460 and lantern-cloud #2678#2681 — this ships a feature-complete Phase 1 for desktop (macOS + Linux + Windows).

End-to-end flow

```
Dart toggle → RadianceSettings.setPeerProxy(bool)
→ LanternService.setPeerProxyEnabled
→ FFI: setPeerProxyEnabled(int) -> *char
→ LanternCore.SetPeerShareEnabled(bool)
→ ipc.Client.PatchSettings({PeerShareEnabledKey: ...})
→ radiance LocalBackend.PatchSettings dispatch
→ peer.Client.Start / Stop
→ UPnP MapPort + register + sing-box samizdat + heartbeat
```

What's in here (152 LOC, 9 files)

  • `lantern_generated_bindings.dart` — adds `setPeerProxyEnabled` + `isPeerProxyEnabled` declarations. Note: these were inserted manually rather than via a local `make ffigen` run. The committed bindings are generated from `bin/windows-amd64/liblantern.h` (in CI); regenerating from a local macOS header drops ~5K lines of Windows-only stubs (`__va_start`, `__security_init_cookie`, etc.) that we want to keep. The two new declarations match the existing `setBlockAdsEnabled` shape exactly.
  • `LanternCoreService` / `LanternFFIService` / `LanternPlatformService` / `LanternService` — `setPeerProxyEnabled` + `isPeerProxyEnabled` across all four service layers, mirroring `setBlockAdsEnabled`. FFI path on `isFFISupported` platforms (Windows + Linux); MethodChannel fallback on macOS / mobile.
  • `RadianceSettingsState` — new `peerProxy` bool field; `copyWith` and equality updated.
  • `RadianceSettings` notifier — `setPeerProxy` method using the existing pessimistic pattern (call FFI → log on failure → update state on success), matching `setBlockAds`. `_refresh` now fetches `peerProxy` alongside the others.
  • `vpn_setting.dart` — SwitchButton tile gated to `PlatformUtils.isDesktop`, with i18n strings `share_my_connection` and `share_my_connection_subtitle` in `en.po`. Other locales will pick up via the normal translation flow.

Tests

`flutter analyze` clean across all changed files.

Out of scope (Phase 2+)

  • Status indicator below the toggle (e.g. "Sharing on <external_ip>:<port>") — radiance already exposes `/peer/status` and `/peer/status/events` SSE in Write a complete spec of Lantern in preparation for a security audit #460, so this is a small follow-up.
  • iOS / Android — UPnP doesn't apply on cellular; tablet-class devices behind home NAT could be a follow-up.
  • Native MethodChannel handlers for non-FFI platforms (macOS via Swift, etc.) — the toggle works on Windows + Linux out of the box; macOS will need a Swift handler before the toggle does anything (currently the call would fail silently with a `MissingPluginException`).

Test plan

  • `flutter analyze`
  • Manual end-to-end on a UPnP-capable network: flip toggle → watch radiance logs for `peer client started` → watch lantern-cloud staging for `peerRegister` succeeded → second client routes through advertised port → flip off → `peer client stopped` + row deprecated server-side.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings May 5, 2026 12:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 wires the new “Share My Connection” / peer-proxy preference through the Dart client so the UI can read and toggle the underlying native setting, extending the existing radiance-backed settings flow.

Changes:

  • Added setPeerProxyEnabled / isPeerProxyEnabled across the Dart service stack (LanternCoreService, service router, FFI service, platform service, generated bindings).
  • Extended RadianceSettingsState and RadianceSettings provider to fetch, store, and mutate the new peerProxy preference.
  • Added a desktop-only VPN settings tile plus English locale strings for the new toggle.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
lib/lantern/lantern_service.dart Routes peer-proxy calls to FFI or platform services.
lib/lantern/lantern_platform_service.dart Adds MethodChannel-based peer-proxy getters/setters.
lib/lantern/lantern_generated_bindings.dart Declares the new FFI exports in generated bindings.
lib/lantern/lantern_ffi_service.dart Wraps the new FFI peer-proxy APIs for Dart callers.
lib/lantern/lantern_core_service.dart Extends the core service interface with peer-proxy methods.
lib/features/setting/vpn_setting.dart Adds the Share My Connection toggle to the VPN settings UI.
lib/features/home/provider/radiance_settings_providers.dart Fetches and updates peer-proxy state in the radiance settings notifier.
lib/core/models/radiance_settings_state.dart Stores peer-proxy in immutable settings state and equality/hash logic.
assets/locales/en.po Adds English strings for the new settings tile.

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

Comment thread lib/lantern/lantern_platform_service.dart
Comment thread lib/features/setting/vpn_setting.dart
Comment thread lib/features/home/provider/radiance_settings_providers.dart Outdated
Adam Fisk and others added 3 commits May 5, 2026 17:00
Final PR in the four-PR stack. Stacks on lantern #8729 (FFI exports);
combined with radiance #458 / #460 / lantern-cloud #2678-#2681 this
ships a feature-complete Phase 1 of "Share My Connection" for desktop
(macOS + Linux + Windows).

* lantern_generated_bindings.dart: add setPeerProxyEnabled +
  isPeerProxyEnabled. Manually inserted to match the existing pattern
  rather than regenerating the whole file (a local ffigen run from
  the macOS header would drop ~5K lines of Windows-only declarations
  the upstream generator emits).
* LanternCoreService / LanternFFIService / LanternPlatformService /
  LanternService: add setPeerProxyEnabled / isPeerProxyEnabled across
  all four service layers, mirroring the setBlockAdsEnabled pattern.
  FFI path on isFFISupported platforms (Windows + Linux), MethodChannel
  fallback on macOS / mobile.
* RadianceSettingsState: new peerProxy bool field with copyWith and
  equality.
* RadianceSettings notifier: new setPeerProxy method (pessimistic —
  call FFI, log on failure, update state on success — matching
  setBlockAds). _refresh now reads peerProxy alongside the others.
* vpn_setting.dart: SwitchButton tile gated to PlatformUtils.isDesktop
  with i18n strings share_my_connection / share_my_connection_subtitle
  in en.po. Other locales will pick up via the standard translation
  flow.

Lifecycle end-to-end:

  Dart toggle → RadianceSettings.setPeerProxy(bool)
  → LanternService.setPeerProxyEnabled
  → FFI: setPeerProxyEnabled(int) -> *char
  → Core.SetPeerShareEnabled(bool)
  → ipc.Client.PatchSettings({PeerShareEnabledKey: ...})
  → radiance LocalBackend.PatchSettings dispatch
  → peer.Client.Start / Stop
  → UPnP MapPort + register + sing-box samizdat inbound + heartbeat

flutter analyze: clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three review comments converged on the same root cause: the toggle was
gated to PlatformUtils.isDesktop and the platform-service shims invoked
MethodChannel methods that have no native handlers anywhere
(Android/iOS/macOS), so on any non-FFI platform the toggle would
render but the call would fail with MissingPluginException.

* vpn_setting.dart: gate to PlatformUtils.isFFISupported (Windows +
  Linux), where the FFI path actually drives the toggle.
* radiance_settings_providers.dart: skip the isPeerProxyEnabled probe
  in _refresh on non-FFI platforms so we don't log a failure on every
  settings init.
* lantern_platform_service.dart: replace the MethodChannel passthroughs
  with explicit "not supported on this platform" stubs. They exist
  only for LanternCoreService interface conformance; the UI gate
  prevents them from ever being called.

macOS / iOS / Android support requires a native handler (Swift /
Kotlin) calling into the Go core; that's a follow-up.

flutter analyze: clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
macOS routes through MethodChannel → Swift → MobileSetPeerShareEnabled
(gomobile-bind) rather than the FFI path that Windows + Linux use.
The previous review fix gated the toggle to PlatformUtils.isFFISupported
to avoid a MissingPluginException on macOS, but per Phase 1 plan macOS
should be supported.

* macos/Runner/Handlers/MethodHandler.swift: new setPeerProxyEnabled
  case + setPeerProxyEnabled function calling MobileSetPeerShareEnabled,
  plus an isPeerProxyEnabled case calling MobileIsPeerShareEnabled.
  Mirrors the existing setBlockAdsEnabled handler exactly. (The
  MobileSet/IsPeerShareEnabled gomobile bindings come from the
  SetPeerShareEnabled / IsPeerShareEnabled methods added to
  lantern-core/mobile/mobile.go in PR 8729; the Liblantern xcframework
  needs a rebuild via `make macos-framework` to pick them up.)

* lantern_platform_service.dart: restore the MethodChannel passthrough
  for setPeerProxyEnabled / isPeerProxyEnabled. The "not supported on
  this platform" stubs from the prior review fix are no longer
  appropriate now that there's a native handler.

* vpn_setting.dart: widen the toggle gate from isFFISupported (Windows
  + Linux) to isDesktop (Windows + Linux + macOS).

* radiance_settings_providers.dart: same widening for the
  isPeerProxyEnabled probe in _refresh.

Verified locally: `make macos-framework` rebuilds successfully and
exports MobileSetPeerShareEnabled / MobileIsPeerShareEnabled.
flutter analyze clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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