Skip to content

feat: Add fallback address for automatic LAN/VPN switching#57

Open
diggerburg wants to merge 6 commits into
cogwheel0:mainfrom
diggerburg:feature/fallback-address
Open

feat: Add fallback address for automatic LAN/VPN switching#57
diggerburg wants to merge 6 commits into
cogwheel0:mainfrom
diggerburg:feature/fallback-address

Conversation

@diggerburg

@diggerburg diggerburg commented Mar 30, 2026

Copy link
Copy Markdown

Summary

Adds an optional fallback address to the Router model, enabling automatic switching between LAN and remote (VPN/Tailscale/WireGuard) connections without manual intervention.

All changes are backward-compatible — routers without a fallback address work exactly as before. The feature is useful for any OpenWrt user with both local and remote access to their router.

Note: This PR builds on top of #56 (GL.iNet router support). The fallback address feature itself is vendor-agnostic, but app_state.dart shares code paths with GL.iNet enrichment.

What's new

Connection logic:

  • On login failure, the app retries with the fallback address and remembers which one worked
  • Dashboard fetch includes automatic fallback retry — if the active address goes down mid-session, the app switches transparently
  • All API calls (dashboard, clients, throughput, wireless MACs) use the address that actually succeeded during login
  • activeAddressIndex tracks which address is current; stored addresses never swap (router ID stays stable)

Login screen:

  • Collapsible "Add fallback address" field below Router Address
  • Same credentials are used for both addresses
  • Duplicate address validation

Manage Routers:

  • Router card shows both addresses with active indicator (● / ○)
  • Add Router dialog includes fallback address field
  • Deleting all routers properly clears auth state and navigates to login

Bug fixes:

  • Fixed infinite navigation loop when all routers are deleted
  • tryAutoLogin returns immediately when no routers exist (no stale credential timeout)

Screenshots

Login Login (expanded) Manage Routers Add Router
Login Login expanded Manage Routers Add Router

Technical details

  • Router model: alternateAddress (String?), alternateUseHttps (bool?), activeAddressIndex (int, default 0)
  • Getters: activeAddress, activeUseHttps, inactiveAddress, hasFallback — all derived from index
  • loginWithFallback() on IAuthService — tries active address first, then fallback, returns which succeeded
  • fetchDashboardData catch block: on failure with fallback router, re-logins with other address and retries once
  • Aggregated client/MAC methods use r.activeAddress instead of r.ipAddress

Testing

  • 8 unit tests for fallback address (Router model serialization, activeAddress getter, copyWith with index change, hasFallback)
  • All existing tests continue to pass
  • 49 total tests, 0 analyzer warnings
  • Tested on real hardware: GL.iNet GL-BE9300 via LAN and Tailscale, with unreachable primary address triggering fallback

Checklist

  • Code follows Dart style guide (dart format applied)
  • flutter analyze passes (0 errors, 0 warnings)
  • flutter test passes (49/49)
  • Backward compatible — routers without fallback unaffected
  • No security vulnerabilities (passwords stored in existing secure storage)
  • Screenshots for UI changes

Screenshots will be attached via GitHub UI in the PR description.
Routers can now have an optional alternate address (e.g., Tailscale
hostname alongside LAN IP). When the active address fails, the app
automatically tries the other. An activeAddressIndex tracks which
address is currently working — addresses themselves never swap,
keeping the router ID stable.

Changes:
- Router model: add alternateAddress, alternateUseHttps, activeAddressIndex
- Auth service: add loginWithFallback() with primary-then-alternate flow
- App state: integrate fallback into login(), selectRouter()
- App state: fetchDashboardData uses authService.ipAddress (the address
  that actually succeeded) instead of router.ipAddress
- Login screen: collapsible 'Add fallback address' field with helper text
- 8 new tests for Router model fallback behavior
- 49 total tests passing
- Fix infinite navigation loop when all routers deleted
  (removed _checkAuthState from MainScreen, clear auth on last delete)
- tryAutoLogin returns immediately when no routers exist
- All API calls use the address that actually succeeded during login
  (dashboard, clients, throughput, wireless MACs, aggregated methods)
- Dashboard fetch retries with fallback address on failure
- Add Router dialog in Manage Routers now includes fallback address field
- Ensure routers are loaded before tryAutoLogin attempts connection
- Add unawaited() for navigation Future in manage_routers_screen
- Guard BuildContext usage across async gaps with mounted checks
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.

1 participant