Download Latest Version v7.31.2 source code.zip (932.1 kB) Google Add to Preferred Sources
Home / v7.30.0
Name Modified Size InfoDownloads / Week
Parent folder
README.md 2026-09-23 9.3 kB
v7.30.0 source code.tar.gz 2026-09-23 697.1 kB
v7.30.0 source code.zip 2026-09-23 876.7 kB
Totals: 3 Items   1.6 MB 0

Added

  • Nylo Live - While the app runs in debug or profile mode, Metro can reach into it over the Dart VM service: Nylo.init calls NyLive.install, which registers every built-in command as a service extension (ext.nylo.<command>) on the main isolate, unless the app calls nylo.useLive(false) first. Metro discovers the running app through the Dart Tooling Daemon and calls these extensions to drive routing (routes, route.current, route.push, route.back), deep links (deeplink.show, deeplink.open), storage and Backpack (storage.list/get/set/delete/clear/export, snapshot.import, backpack.list/get/set/delete), auth (auth.show/login/logout), locale and theme switching, on-screen page state (state.data, backed by the new LiveStateInspector, which walks the element tree and reads a state's own fields through the VM service's evaluate since Flutter has no reflection), and event/toast triggering. Route changes and log entries stream live to Metro via the new NyLiveNavigatorObserver and NyLogger.addListener. An app registers its own commands and data seeders with nylo.addLiveCommands({...}) / nylo.addSeeders({...}), written as LiveCommand subclasses (builder/handle, with a CommandBuilder/CommandResult pair mirroring Metro's own command API) and runs them from the terminal while the app is live. Read-only commands work in profile builds too; commands that change the app are debug-only, and nothing is registered in release builds
  • NyDeepLinkHandler.resolve and DeepLinkTarget - Reports where an incoming URI would take the app - the read path, whether it's registered, the target it actually resolves to (the registered path, or fallbackRoute when it isn't), the parsed queryParameters, and a computed usedFallback - without navigating. The existing dispatch path calls this same method, so a link is reported exactly as it will be handled
  • Seeder - Puts a running app into a known state and back out again. Write up() to add data (sign in, mark onboarding complete, seed local records) using your models, Auth and NyStorage; every storage and Backpack value it touches is recorded automatically, so the default down() (restore()) puts each one back exactly as it was, in reverse order, even across a hot restart. A seeder can run others with seed(), recorded as nested runs and rolled back with them. Create one with metro make:seeder <name>, run it with metro live:seed <name>, undo it with metro live:seed:rollback <name>
  • StorageSnapshot - Captures every storage and Backpack value (StorageSnapshot.capture, metro live:export) into a portable JSON shape and writes it back (apply, metro live:import, or Seeder.importSnapshot for a snapshot bundled into a seeder as a SnapshotSeeder). A Model, or any class with a registered decoder, is tagged by class name so it comes back through its own decoder rather than as a plain map; only/except glob patterns and a backpack: false flag narrow what's captured
  • Typed page actions (PageStateActions) - path.actions (the new RouteViewExt.actions getter) returns a PageStateActions for calling a page from outside it: showToast, refreshPage, pop, confirmAction, lockRelease, validate, changeLanguage, and a generic call(name, data) (also reachable as HomePage.actions("shake_the_logo") now that StateActions has a call operator). Subclassing PageStateActions and declaring methods with no body turns each into a typed action, routed through noSuchMethod and sent as the method's Symbol plus its arguments; the receiving NyPage/NyState registers a handler for that symbol in stateActions (now Map<Object, Function>) and dispatches to it with Function.apply. A Symbol literal (#shakeTheLogo) survives flutter build --obfuscate
  • Built-in English translations for Nylo's own UI text - NyLocalization.translate falls back to the new nylo.* keys (toasts, confirm dialogs, form validation messages, input field labels, form collection prompts, page-not-found, offline banner, language switcher, journey step labels, collection view states) when a key is missing from both the active and fallback language files, so an app whose lang/ files predate a key still sees correct English text instead of the raw key
  • NyLogger.addListener / removeListener - Registers any number of listeners that receive every log entry alongside the single onLog callback
  • Backpack.keys - The keys currently held in Backpack, including internal ones (nylo, event_bus)
  • MetroService.makeSeeder and the lib/app/seeders convention - Scaffolds a new seeder file; registering it with the app is left to the caller

Changed

  • NyFormWidget.submit, NyFormActions.submit and NyFormData.submit return Future<void> - The Future completes once onSuccess or onFailure (and any Future either one returns) has finished, so a button's onPressed can return it and stay locked for the whole submission; it completes with the error if either callback throws. NyFormWidget.submit also tracks how many mounted form states are listening under each name, so a submit sent to a name with nothing mounted is reported once via NyLogger.error and its Future completes immediately instead of waiting on an event nothing will answer
  • Built-in dialogs, toasts, form validation and input defaults resolve through translation keys - Every built-in FormRule's default message (e.g. FormRuleEmail, FormRuleMinLength), the default titles in StateAction's toast helpers, NyController.confirmAction's dismissText, InputField.password/.emailAddress label text, and FormCollection's selection-error text now default to a nylo.* key resolved through the new built-in translations, so behavior is unchanged for an app with no matching lang/ entry. FormRule gained a messageArguments map for rule-specific placeholders ({{minLength}}, {{age}}, etc.), and FormValidationResponse (and its FormValidationError/FormValidationSuccess subclasses) gained an attribute field and a message getter that runs the rule's message through translation with those arguments plus the field's own translated name
  • NyLocalization.translate resolves nylo.* keys even before _values is loaded, falling back to the built-in defaults instead of returning the raw key

Fixed

  • ButtonState and NyFormWidget.submit now lock for an async-declared callback typed as void Function() - Whether the button locked was decided by checking widget.onSubmit against the static type Future Function(), which a method like void submit() async {} never matches even though calling it returns a Future. The button now locks based on what the callback actually returns (result is Future), and drops a second call outright while already locked, covering a tap that lands before the button redraws as locked
  • lockRelease now releases its lock however perform throws - The lock was only released after the try/on Exception catch, so an Error (or anything not caught) propagated past it and left the name locked for good. Releasing the lock now happens in a finally, so it clears regardless of what perform throws, while the error still propagates as before
  • NyPage and NyState share one implementation for state actions - Each previously kept its own copy of the restore-from-history and action-dispatch logic: NyPage guessed whether a handler took a parameter by string-matching its runtimeType, NyState called the handler and retried without arguments only after catching a NoSuchMethodError (which could also mask a real one thrown inside the handler). Both now share NyBaseState.listenForStateUpdates/restoreStateFromHistory/handleStateAction, which checks handler is Function(Never) / Function() directly
  • A dotted translation key now stops as soon as it runs past a string value - NyLocalization's nested lookup kept the last resolved string when a later segment of a key (e.g. "hello.world" where "hello" is itself a string) couldn't be indexed further, so an unrelated key could resolve to it
  • FormRuleLowercase keeps its default message - Its constructor took message as a bare initializing formal (this.message) with no default, which set the field to null whenever no custom message was passed. It now follows the same if (message != null) this.message = message; pattern as every other rule, so the default (now nylo.validation.lowercase) is kept
  • NavigationHub tab titles follow a language change - didChangeDependencies now compares the hub's Localizations locale against the one pages was last built with and regenerates the tabs when it changes, so titles built with .tr() update immediately on a language switch
  • Scheduling an exact notification on Android 14+ without the exact-alarm permission - LocalNotification now checks canScheduleExactNotifications() first and automatically schedules with the nearest inexact equivalent instead of throwing exact_alarms_not_permitted, logging a warning

Deprecated

  • RouteViewExt.stateRefresh() - Replaced by actions.refreshPage() (see the new PageStateActions above)
Source: README.md, updated 2026-09-23