feat: Add fallback address for automatic LAN/VPN switching#57
Open
diggerburg wants to merge 6 commits into
Open
feat: Add fallback address for automatic LAN/VPN switching#57diggerburg wants to merge 6 commits into
diggerburg wants to merge 6 commits into
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.
What's new
Connection logic:
activeAddressIndextracks which address is current; stored addresses never swap (router ID stays stable)Login screen:
Manage Routers:
Bug fixes:
tryAutoLoginreturns immediately when no routers exist (no stale credential timeout)Screenshots
Technical details
Routermodel:alternateAddress(String?),alternateUseHttps(bool?),activeAddressIndex(int, default 0)activeAddress,activeUseHttps,inactiveAddress,hasFallback— all derived from indexloginWithFallback()onIAuthService— tries active address first, then fallback, returns which succeededfetchDashboardDatacatch block: on failure with fallback router, re-logins with other address and retries oncer.activeAddressinstead ofr.ipAddressTesting
activeAddressgetter,copyWithwith index change,hasFallback)Checklist
dart formatapplied)flutter analyzepasses (0 errors, 0 warnings)flutter testpasses (49/49)