flutter_dev_setup 0.2.3
flutter_dev_setup: ^0.2.3 copied to clipboard
A developer setup screen for Flutter apps: find dev servers on the local network, switch the API base URL at runtime, and keep the choice across launches.
Changelog #
0.2.3 #
- Screenshots on pub.dev and in the README. No code changes.
0.2.2 #
- The health check no longer follows redirects. A host could answer with a redirect to a healthy server, be listed as a dev server itself, and make the device request any URL it chose.
- On an emulator the host alias is listed whenever it doesn't answer, even when other servers did, and a scan the developer starts selects it ahead of any server that isn't pinned. Before, Local IP with your own server down and one colleague's server up selected the colleague's.
- An Android emulator's own address no longer names the LAN to sweep. Images that put Wi-Fi on 192.168.232.x had the router guess skipped and an empty network swept.
- Tapping Local IP while the opening scan runs takes that scan over and selects the alias if it has answered, instead of cancelling it.
DevSetupController.isManualScantells the two apart, and the Local IP control shows Cancel only for a scan the developer started.
0.2.1 #
- First release on pub.dev. No code changes from 0.2.0.
0.2.0 #
Breaking changes #
DevServerScanner.scantakes two more named parameters.knownHostslists hints for where to look, best first: the remembered LAN server (LanHost), then the pinned, saved and named hosts.onPreferredis called at most once per scan, with the server a scan the developer started should select when nothing is pinned. A custom scanner must add both to itsscanoverride, and may ignore them.
Features #
- An emulator or simulator no longer stops at the alias for the host machine. After checking it, the scanner sweeps up to two /24s of the LAN the host is on. It takes them from the host's own addresses, which its server can list in an
x-dev-lanheader, and then from the device's own LAN address unless it is in the Android emulator's NAT. When neither names a LAN, it uses the routers inrouterAddressesthat accept or refuse a connection on port 80 or 53, in the order listed, probed while the alias is checked. Last come the addresses the developer has used. Each sweep works like a phone's, centred on the first of those addresses in the subnet, and lists the host by its LAN address as well as by the alias. - A LAN server the developer used or a scan found is remembered as
LanHost, apart from the last server used, and is among the first addresses a scan takes. An emulator keeps sweeping that network after the developer selects its alias, unless networks that rank higher already fill both /24s. - The scan's label reads
emulator hostwhile the alias is checked and names the subnet during each sweep. Its final label names both, as inemulator host and 192.168.0.0/24. - A scan the developer starts on an emulator selects the alias the moment it answers, if nothing is pinned or the alias is itself the pinned server. Otherwise it waits for the end of the scan and selects the pinned server if it found it, or else the alias. The scan that runs when the screen opens still only lists.
Configuration #
DiscoveryConfig.lanAddressHeader(defaultx-dev-lan) names the response header a server can use to list its own LAN IPv4 addresses, separated by commas or on repeated lines.nullturns it off.DiscoveryConfig.emulatorConnectTimeout(default 1.5 s) is the sweep's TCP probe on an emulator, where every connection crosses the emulator's NAT and takes up to about a second.DiscoveryConfig.routerAddresses(defaultDiscoveryConfig.defaultRouterAddresses, common home, office and hotspot routers) is where an emulator looks for the host's router when nothing else names its LAN.DevSetupStorekeeps aLanHostkey, read and written withlanHost()andsetLanHost().
Probing #
- A failed TCP probe is read by its OS error code first. A refused connection counts as a live host, and an unreachable network or a host reported down as a dead one, however long either took. Any other failure falls back to the timing rule, an unreachable host included: Linux reports a firewall's administratively prohibited reject that way, from a host that may serve another port.
tcpProbetakes an optionaltimeout,connectTimeoutby default.
API #
DevServerDiscovery.emulatorSubnetsreturns the subnets an emulator sweeps, each with the octet its walk starts from, andDevServerDiscovery.classifyConnectErrorreads a failed connection.candidatePhasestakesknownHosts,excludefor hosts never to propose, andisLanfor which known hosts count.DevServerDiscoverytakesemulatorHost,isLanAddressandrouterProbeoverrides, and has a staticrouterAnswerswith aconnectoverride, all marked@visibleForTesting, so tests can run the emulator path against loopback without probing real routers.
Screen #
- The status card is more compact, and tapping anywhere on it copies the URL.
0.1.0 #
Initial release.
Features #
DevSetupScreenchooses the API base URL from the default, a server found on the local network, or a saved address. The choice is applied at runtime throughonBaseUrlChangedand kept across launches.DevServerDiscoverysweeps the device's /24: known hosts first, then the DHCP lease band, then the rest of the subnet working outward from the device. A host counts only ifisHealthyaccepts its health response, and the other ports are tried only on hosts already known to be up. On an emulator or simulator it checks the host machine's alias and lists it even before the server starts.- Servers are named by an
x-dev-hostresponse header or a reverse DNS lookup. A name the developer gives a server is kept on that device. - Saved addresses for VPNs, tunnels and other subnets, normalised to
scheme://host:portand re-checked on every scan. An IPv6 literal is accepted in brackets, as inhttp://[fd7a:115c::5]:8080, saved in its shortest form, and kept in brackets wherever it is saved, restored, checked or shown. Pins are per subnet for private LAN addresses and global for everything else. DevSetup.savedBaseUrl({keyPrefix})andDevSetup.isReachable(url, {config, timeout})restore the saved URL inmain(), before the first request.
Configuration #
DiscoveryConfig: ports, health path,isHealthy, name header, lease band, connect, verify and reverse-lookup timeouts, and concurrency.DevSetupStore(keyPrefix, config)keeps everything inSharedPreferencesunder<prefix>BaseUrl,BaseUrlSuffix,CustomServers,ServerLabels,ServerPins,DiscoveredHostandDiscoveredOctet. A key, or a single label or pin, holding a value of another type reads as unset. A pin stored under another key, such as the phone's subnet rather than the server's, moves to its server's key when read, unless that key already holds a pin, andsetPinswrites only those keys. A pin whose value isn't a bare host is dropped.DevSetupStringsholds all of the screen's text.enableDiscovery: falseturns scanning off and leaves saved addresses working.
Behaviour guarantees #
- The scan that runs when the screen opens only lists servers. A scan the developer starts selects the pinned server or the only one found, unless they picked a server or edited the URL while it ran.
- Typing never commits. A URL is committed by tapping a server, Default, Reset or Proceed, by adding an address, or by a developer-started scan selecting a server. Proceed is enabled only once the URL passes the health check.
- Selecting, pinning and renaming never reorder the list, and an address both saved and discovered is listed once.
- The health check uses the discovery probe on the port the HTTP client will use, so an interceptor can't make it disagree with the list. It pauses while another route covers the screen or the app is in the background.
Theming and accessibility #
DevSetupThemesets the screen's colours.fieldTextStyleis merged over the host theme'stextTheme.bodyLarge, so the app's font is inherited and the URL field and scheme picker always match. Status text is pulled towardtextPrimaryuntil it reaches 4.5:1 contrast.- Every control is at least 48dp to tap, and server rows report their selected state to screen readers.
- Dialogs stack their actions when they don't fit side by side, and scroll rather than overflow above a keyboard.
API #
DevSetupControlleris a widget-freeChangeNotifier. Its state (scan phase and progress, health status, scheme, server list) is exposed through read-only getters and changes through its methods. Pass one toDevSetupScreen(controller:)to drive the screen yourself.toggleScan()is the Local IP control: it cancels a running scan or starts a manual one.scan()always starts a fresh scan, replacing any that is running;scan(manual: false)only lists.pausePinging()andresumePinging()suspend and resume the periodic health check. The screen calls them itself, and resuming checks at once.ScanPhase.failed: a scanner that throws ends the scan as failed, and the error goes toFlutterError.reportError.DevServer.fromUrlreads a URL as an HTTP client will, so no port means 80 or 443.DevServer.parseandDevServer.normalizeread a typed address, where a barehttp://host gets the first configured port.DevServerScanneris the network interface behind the controller, so tests can fake it without sockets.
