| Name | Modified | Size | Downloads / 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.initcallsNyLive.install, which registers every built-in command as a service extension (ext.nylo.<command>) on the main isolate, unless the app callsnylo.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 newLiveStateInspector, which walks the element tree and reads a state's own fields through the VM service'sevaluatesince Flutter has no reflection), and event/toast triggering. Route changes and log entries stream live to Metro via the newNyLiveNavigatorObserverandNyLogger.addListener. An app registers its own commands and data seeders withnylo.addLiveCommands({...})/nylo.addSeeders({...}), written asLiveCommandsubclasses (builder/handle, with aCommandBuilder/CommandResultpair 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.resolveandDeepLinkTarget- Reports where an incoming URI would take the app - the readpath, whether it'sregistered, thetargetit actually resolves to (the registered path, orfallbackRoutewhen it isn't), the parsedqueryParameters, and a computedusedFallback- without navigating. The existing dispatch path calls this same method, so a link is reported exactly as it will be handledSeeder- Puts a running app into a known state and back out again. Writeup()to add data (sign in, mark onboarding complete, seed local records) using your models,AuthandNyStorage; every storage and Backpack value it touches is recorded automatically, so the defaultdown()(restore()) puts each one back exactly as it was, in reverse order, even across a hot restart. A seeder can run others withseed(), recorded as nested runs and rolled back with them. Create one withmetro make:seeder <name>, run it withmetro live:seed <name>, undo it withmetro 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, orSeeder.importSnapshotfor a snapshot bundled into a seeder as aSnapshotSeeder). AModel, 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/exceptglob patterns and abackpack: falseflag narrow what's captured- Typed page actions (
PageStateActions) -path.actions(the newRouteViewExt.actionsgetter) returns aPageStateActionsfor calling a page from outside it:showToast,refreshPage,pop,confirmAction,lockRelease,validate,changeLanguage, and a genericcall(name, data)(also reachable asHomePage.actions("shake_the_logo")now thatStateActionshas acalloperator). SubclassingPageStateActionsand declaring methods with no body turns each into a typed action, routed throughnoSuchMethodand sent as the method'sSymbolplus its arguments; the receivingNyPage/NyStateregisters a handler for that symbol instateActions(nowMap<Object, Function>) and dispatches to it withFunction.apply. ASymbolliteral (#shakeTheLogo) survivesflutter build --obfuscate - Built-in English translations for Nylo's own UI text -
NyLocalization.translatefalls back to the newnylo.*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 whoselang/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 singleonLogcallbackBackpack.keys- The keys currently held in Backpack, including internal ones (nylo,event_bus)MetroService.makeSeederand thelib/app/seedersconvention - Scaffolds a new seeder file; registering it with the app is left to the caller
Changed
NyFormWidget.submit,NyFormActions.submitandNyFormData.submitreturnFuture<void>- The Future completes onceonSuccessoronFailure(and any Future either one returns) has finished, so a button'sonPressedcan return it and stay locked for the whole submission; it completes with the error if either callback throws.NyFormWidget.submitalso tracks how many mounted form states are listening under each name, so a submit sent to a name with nothing mounted is reported once viaNyLogger.errorand 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 defaultmessage(e.g.FormRuleEmail,FormRuleMinLength), the default titles inStateAction's toast helpers,NyController.confirmAction'sdismissText,InputField.password/.emailAddresslabel text, andFormCollection's selection-error text now default to anylo.*key resolved through the new built-in translations, so behavior is unchanged for an app with no matchinglang/entry.FormRulegained amessageArgumentsmap for rule-specific placeholders ({{minLength}},{{age}}, etc.), andFormValidationResponse(and itsFormValidationError/FormValidationSuccesssubclasses) gained anattributefield and amessagegetter that runs the rule's message through translation with those arguments plus the field's own translated name NyLocalization.translateresolvesnylo.*keys even before_valuesis loaded, falling back to the built-in defaults instead of returning the raw key
Fixed
ButtonStateandNyFormWidget.submitnow lock for anasync-declared callback typed asvoid Function()- Whether the button locked was decided by checkingwidget.onSubmitagainst the static typeFuture Function(), which a method likevoid submit() async {}never matches even though calling it returns aFuture. 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 lockedlockReleasenow releases its lock howeverperformthrows - The lock was only released after thetry/on Exception catch, so anError(or anything not caught) propagated past it and left the name locked for good. Releasing the lock now happens in afinally, so it clears regardless of whatperformthrows, while the error still propagates as beforeNyPageandNyStateshare one implementation for state actions - Each previously kept its own copy of the restore-from-history and action-dispatch logic:NyPageguessed whether a handler took a parameter by string-matching itsruntimeType,NyStatecalled the handler and retried without arguments only after catching aNoSuchMethodError(which could also mask a real one thrown inside the handler). Both now shareNyBaseState.listenForStateUpdates/restoreStateFromHistory/handleStateAction, which checkshandler 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 FormRuleLowercasekeeps its default message - Its constructor tookmessageas a bare initializing formal (this.message) with no default, which set the field tonullwhenever no custom message was passed. It now follows the sameif (message != null) this.message = message;pattern as every other rule, so the default (nownylo.validation.lowercase) is keptNavigationHubtab titles follow a language change -didChangeDependenciesnow compares the hub'sLocalizationslocale against the onepageswas 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 -
LocalNotificationnow checkscanScheduleExactNotifications()first and automatically schedules with the nearest inexact equivalent instead of throwingexact_alarms_not_permitted, logging a warning
Deprecated
RouteViewExt.stateRefresh()- Replaced byactions.refreshPage()(see the newPageStateActionsabove)