NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #4958 most downloaded on pub.dev
Support library for the Nylo framework. This library supports routing, widgets, localization, cli, storage and more.
Last release 8 days ago
30 Sep 2026
Ships fairly regularly
a new release about every 2 weeks
Nearly every release is documented
notes for 55 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
276 releases · first in 2021
One column per quarter.
Boot completes while the keychain is locked - With monitorAppUsage() on, every boot records the launch in secure storage through NyAppUsage.appLaunche
monitorAppUsage() on, every boot records the launch in secure storage through NyAppUsage.appLaunched. iOS refuses keychain access while the device is locked (errSecInteractionNotAllowed), which happens when a push notification launches the app in the background, and the PlatformException from that write was thrown out of the boot. The launch now goes unrecorded and the error is logged instead. appLaunchCount still throws while the keychain is lockedsetLoading works after its page has closed - Async work that finished after its state was disposed, such as CollectionView's refreshData still fetching when the page closed, called setState on the disposed state and threw. Once the state is disposed, setLoading stores the value without rebuildinghandleFailure works when the request throws - Dio throws for a status outside 2xx, so most failed requests reach handleFailure through a DioException
handleFailure works when the request throws - Dio throws for a status outside 2xx, so most failed requests reach handleFailure through a DioException. On that path network and networkResponse returned the callback's result as the response itself, so a callback that returned nothing (one that only shows a toast, say), plain or async, or one that returned a fallback value ended in a TypeError. The callback is now awaited when it's async, and what it returns is used the same way as for handleSuccess: nothing keeps the error response, a NyResponse replaces it, and any other value becomes its data, which is what network returnsFile storage - Named disks for keeping files, in the style of Laravel's Storage facade: disk('documents').put('reports/q3.pdf', bytes) , or FileStorag
Storage facade: disk('documents').put('reports/q3.pdf', bytes), or FileStorage.put('notes.txt', 'Hello') for the default disk. Five disks are ready without any configuration: local (the default, in the app's support folder under nylo/), documents, cache, temp (pruned after a day) and assets (the app bundle under assets/, read-only). nylo.configure(disks: ..., defaultDisk: ...) and nylo.addDisks(...) add or replace disks, built with DiskConfig.local (in a DiskRoot: support, documents, cache, temporary, library, downloads or external), DiskConfig.path, DiskConfig.assets, DiskConfig.memory, DiskConfig.scoped (a folder inside another disk) or DiskConfig.custom (your own DiskDriver), and FileStorage.build(config) makes one on demand. On the web, local disks live in memory. Everything is exported from package:nylo_support/ny_core.dart, along with XFileDisk - Reads files with get, bytes, json<T> (decoding models through modelDecoders) and readStream, and writes them with put (a String, bytes or a byte stream), putJson, append and prepend. putFile stores an XFile from image_picker, file_picker or camera, a File, a path or bytes under a random 40-character name with the extension its contents show, streaming it rather than loading it into memory; putFileAs takes the name. Also copy, move, copyToDisk, moveToDisk, delete (one path or many), download (through NyApiService, so your interceptors apply, with onProgress and cancelToken; an existing file is replaced only once the download finishes), exists, missing, directoryExists, size, lastModified, mimeType (from the file's first bytes and its extension), checksum (md5 by default, or sha1, sha224, sha256, sha384 or sha512), path and url for plugins that need a real file, list, files, allFiles, directories, allDirectories, makeDirectory, deleteDirectory, scope (a disk rooted at a folder, e.g. one per user), usage and prune. Paths are relative to the disk, always use /, and .. can never climb above the disk's root. Every failure throws a DiskException that names the disk and path: DiskFileNotFoundException, DiskReadOnlyException, DiskPathTraversalException, DiskCorruptedPathException or DiskNotConfiguredExceptionDiskImage - An ImageProvider for an image on a disk, e.g. CircleAvatar(backgroundImage: DiskImage('avatars/me.jpg')). It reads through the disk, so it works with every driver and with fakes, and writing the file through its disk evicts the cached image, so the new picture shows on the next frameDiskDriver - The interface behind every disk, with LocalDiskDriver, AssetDiskDriver and MemoryDiskDriver built in. testDiskDriver(description, create) runs the contract every built-in writable driver passes against a driver of your ownFileStorage.fake('photos') swaps a disk for an empty in-memory FakeDisk with assertExists, assertMissing, assertCount, assertDirectoryEmpty and assertEmpty. FakeFile.image('avatar.png', width: 64, height: 64) makes a real, decodable PNG as an XFile, and FakeFile.create('invoice.pdf', kilobytes: 120) a file of that many zero bytes with the MIME type its name suggests; both live in memory, so they work inside testWidgets. NyTest.init() makes every writable disk an in-memory fake on first use (read-only disks such as assets stay real), NyTest.reset() empties them and NyTest.dump() lists their files. All exported from package:nylo_support/testing/ny_testing.dartlockRelease(onError:) - An Exception thrown by perform goes to onError(error, stackTrace) once the lock is released, so the caller can react: show what went wrong, undo an optimistic change, or try again. Available on NyBaseState, NyController, StateAction and PageStateActions. Without onError the exception is logged as before, now with its stack tracecross_file (^0.3.5+5, the line image_picker, file_picker and share_plus depend on), mime, crypto and path, for file storageField.date stays empty - The field showed today (or the style's firstDate) while its value was still null, so the form submitted nothing for the date on screen. It now shows nothing until a date is chosen, and the picker still opens on today. It also shows a date set after it opened through setValue, clear empties both what it shows and its value, and it keeps the field's label under a style decoration that has no label or hint of its ownField.picker grows to fit its text - The box had a fixed containerHeight, so a long choice or a large text size was clipped. containerHeight is now the minimum height, and the field name keeps to one line and the choice to two, ending in an ellipsisField.chips shows which chips are selected in dark mode - Selected and unselected chips were both drawn in the dark surface color. Selected chips now use the selected color (white by default), and a label or checkmark that would be hard to read on its chip (below 4.5:1 contrast) switches to black or whiteInputField's show/hide password icon is now an IconButton, at least 48pt square, with a "Show password" / "Hide password" tooltip that screen readers announce (the new nylo.input_field.show_password and nylo.input_field.hide_password keys)Nylo Live dartdoc names the commands as nylo_framework 7.2.0 ships them - Seeder , StorageSnapshot , SnapshotSeeder , LiveCommand.seed , SeedRecorder
Seeder, StorageSnapshot, SnapshotSeeder, LiveCommand.seed, SeedRecorder and Nylo.addSeeders pointed at metro live:seed, metro live:seed:rollback, metro live:export and metro live:import, which aren't top-level commands. Seeding, rolling back and exporting run inside the metro live shell (seed <name>, seed:rollback <name>, export), and a snapshot file loads with seed <file>. LiveCommand.description is now documented as shown by the command's --help, since there is no metro live:commands. The 7.30.0 entry below uses the old names; read them as the shell commandsNylo 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 regi
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 buildsNyDeepLinkHandler.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 handledSeeder - 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 capturedPageStateActions) - 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 --obfuscateNyLocalization.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 keyNyLogger.addListener / removeListener - Registers any number of listeners that receive every log entry alongside the single onLog callbackBackpack.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 callerNyFormWidget.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 answerFormRule'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 nameNyLocalization.translate resolves nylo.* keys even before _values is loaded, falling back to the built-in defaults instead of returning the raw keyButtonState 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 lockedlockRelease 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 beforeNyPage 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() directlyNyLocalization'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 itFormRuleLowercase 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 keptNavigationHub 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 switchLocalNotification now checks canScheduleExactNotifications() first and automatically schedules with the nearest inexact equivalent instead of throwing exact_alarms_not_permitted, logging a warningRouteViewExt.stateRefresh() - Replaced by actions.refreshPage() (see the new PageStateActions above)Metro commands contributed by packages - A dependency can ship a metro_commands.json in its package root (entries shaped like commands.json , but scri
metro_commands.json in its package root (entries shaped like commands.json, but script must name a Dart file directly inside the package's own bin/ folder, e.g. "my_command.dart"), and Metro now discovers it automatically through .dart_tool/package_config.json via the new MetroService.discoverPackageCommands. Each discovered command runs as dart run <package>:<executable> from the project's working directory, so its imports resolve through the project rather than the package. MetroService.discoverCustomCommands now merges the project's own commands.json with every package's commands through the new MetroService.mergeCommands, with reservedCommands (built-ins) taking precedence over the project, and the project over packages; a shadowed command is dropped with a console warning naming whether "your project" or which package already claims it. NyCommand gained package (null for project commands), description, a computed fullName (category:name), and isFromPackage. The new MetroService.customCommandsMenu renders the menu text, listing project commands under [Custom Commands] and each package's under [<package> Commands], with descriptions aligned in columnsMetroService.runProcessWithArguments - Runs an executable with its arguments passed as a list rather than joined into one shell string, so an argument containing spaces survives, and returns the child process's exit code while sharing the terminal's stdioMetroService.runCommand returns the command's exit code - Its return type changed from Future<void> to Future<int>; an action whose result is not an int is treated as success (0). Existing callers that await the call without using its result are unaffectedMetroService.discoverCommands gained scriptDirectory, package, defaultCategory, and workingDirectory parameters - All optional, so existing calls are unaffected; they let package-contributed commands resolve their scripts from the package's own bin/ folder and run from the project's directory instead of the built-in lib/app/commands conventionMetroService.discoverCommands treating same-named commands in different categories as duplicates - Duplicate detection compared name alone, so {category: "app", name: "sync"} and {category: "demo", name: "sync"} in the same commands.json collapsed to one entry. The check now keys on category:name, matching the identity fullName and the menu already usename and path constructor parameters on NavigationHub - NavigationHub(this.pages, {super.name, super.path}) forwards both to NyPage , so a hub can dec
name and path constructor parameters on NavigationHub - NavigationHub(this.pages, {super.name, super.path}) forwards both to NyPage, so a hub can declare the state name it is addressed by. This lets a hub and the NavigationHubStateActions that drive it agree on one name, e.g. MyHub({super.key}) : super(child: () => _MyHubState(), stateName: path.stateName()); alongside static NavigationHubStateActions stateActions = NavigationHubStateActions(path.stateName());NyStatefulWidget.declaredStateName - Holds the stateName passed to the constructor, when one was given. The existing state member becomes a computed getter that returns declaredStateName when set and otherwise derives the name from the widget's own class, so the name a widget listens on is always available even where no stateName was declaredWidget - a tear-off of a named function, or a variable typed as the RouteView signature - carries that declared type at runtime instead of the page class, so the page behind it cannot be read back from the route and the derived state name reaches nothing. NyLogger.error now names such a route once, with both ways to address it: build the route from a closure that returns the page, ("/my-page", (_) => MyPage()), or give the page a name of its own via super(child: () => _MyPageState(), stateName: "/my-page"). Previously the state update was dropped by the event bus in silenceNavigationHub - NavigationHubStateActions.nextPage() and previousPage() now report once, via NyLogger.error, when no hub is listening on the name they address, detected from the absence of the ${state}_current_tab key a hub writes as the first thing its init does. A journey that could not advance previously did so without a tracelib/helpers/src/state_name.dart), so the listening end (NyPage, NyState) and the sending end (RouteViewExt.stateName, updateState with a RouteView, stateAction) build the same string from the same class. The widget class is the anchor because it is the only class both ends can see - a sender holds a RouteView, which knows the widget it builds and nothing about the state behind it. For the naming convention Metro scaffolds (MyPage with _MyPageState) the resulting name is unchanged; a state class named outside that convention now resolves to Closure: () => _${WidgetClass}State on both ends rather than to its own class nameNyState points its controller at the page it is used from - _controller.state is now assigned the resolved stateName on every initState, rather than only when it still held the initial "/". A controller registered as a singleton is shared by every page that asks for it, so controller.refreshPage() and the other controller state helpers now address the page they are called from instead of the name an earlier page left behindchild.runtimeType) while senders read the widget class from the route builder's return type. flutter build --obfuscate renames a widget and its state to two unrelated symbols, so the two ends produced names that no longer matched and every update sent to the page was dropped. Both ends now read the widget class, which a compiler that renames classes renames for both at once. updateState's history lookup contributed the same failure through element.event.runtimeType.toString() != 'UpdateState', a comparison against a class name that obfuscation rewrites; it now tests event is! UpdateState and reads the event's data field rather than props[1]NyPage adopting another page's state data on init - Restoring from the event bus history took the last UpdateState entry regardless of which state it was sent to, so a page could open holding a payload addressed to a different page. The lookup now matches stateName before taking the most recent entryJourneyState.isLastStep reporting the last step where a journey has no steps - With totalSteps at 0 the comparison read 0 >= -1 and answered true, so a step whose hub data had not been read yet was treated as the end of the journey. The getter now requires totalSteps > 0CollectionView passing the deprecated cacheExtent parameter to its internal ListView s - Flutter deprecated cacheExtent in favour of scrollCacheExtent…
intl from ^0.20.2 to ^0.20.3, flutter_local_notifications from ^22.2.0 to ^22.3.0, app_badge_plus from ^1.3.2 to ^1.3.4, win32 from ^6.3.0 to ^6.4.0, and patrol (dev) from ^4.8.0 to ^4.9.0 - routine compatibility refreshesbuild/, android/, ios/, web/, windows/, macos/, linux/) from static analysis in analysis_options.yaml - keeps the analyzer focused on the package's Dart sourcesMetroService.discoverCustomCommands returning an unawaited Future inside its try block - an asynchronous failure from discoverCommands would escape the surrounding catch instead of surfacing the "Error loading custom commands" console message; the return is now awaited in lib/metro/src/metro_service.dartCollectionView passing the deprecated cacheExtent parameter to its internal ListViews - Flutter deprecated cacheExtent in favour of scrollCacheExtent after v3.41.0-0.0.pre. The three list builders in lib/widgets/src/collection_view.dart now pass scrollCacheExtent, converting the widget's double? cacheExtent to ScrollCacheExtent.pixels(...) - the same pixel semantics as before, so the public CollectionView.cacheExtent API is unchangedBumped dio from ^5.10.0 to ^5.11.0 , connectivity_plus from ^7.2.0 to ^7.3.1 , flutter_local_notifications from ^22.0.1 to ^22.2.0 , uuid from ^4.5.3
dio from ^5.10.0 to ^5.11.0, connectivity_plus from ^7.2.0 to ^7.3.1, flutter_local_notifications from ^22.0.1 to ^22.2.0, uuid from ^4.5.3 to ^4.6.0, app_links from ^7.2.0 to ^7.2.1, app_badge_plus from ^1.3.1 to ^1.3.2, get_time_ago from ^2.4.0 to ^2.4.1, error_stack from ^2.1.4 to ^2.1.5, and patrol (dev) from ^4.6.1 to ^4.8.0 - routine compatibility refreshesRe-tightened collection from ^1.18.0 to ^1.19.1 and characters from ^1.4.0 to ^1.4.1 - both packages are vendored by the Flutter SDK, and the >=3.44.0
collection from ^1.18.0 to ^1.19.1 and characters from ^1.4.0 to ^1.4.1 - both packages are vendored by the Flutter SDK, and the >=3.44.0 floor adopted in 7.27.2 ships collection 1.19.1 and characters 1.4.1, so the constraints now match the versions the minimum supported Flutter providesdio from ^5.9.2 to ^5.10.0, connectivity_plus from ^7.1.1 to ^7.2.0, app_links from ^7.1.1 to ^7.2.0, equatable from ^2.0.8 to ^2.1.0, get_time_ago from ^2.3.2 to ^2.4.0, flutter_local_notifications from ^22.0.0 to ^22.0.1, path_provider from ^2.1.5 to ^2.1.6, timezone from ^0.11.0 to ^0.11.1, and app_badge_plus from ^1.3.0 to ^1.3.1 - routine compatibility refreshesBumped flutter_local_notifications from ^21.0.0 to ^22.0.0 - the v22 line ships a dedicated web implementation (the new flutter_local_notifications_we
flutter_local_notifications from ^21.0.0 to ^22.0.0 - the v22 line ships a dedicated web implementation (the new flutter_local_notifications_web) and advances the platform interface to 12.0.0app_links from ^7.0.0 to ^7.1.1, flutter_timezone from ^5.0.2 to ^5.1.0, app_badge_plus from ^1.2.10 to ^1.3.0, flutter_secure_storage from ^10.3.0 to ^10.3.1, and patrol (dev) from ^4.6.0 to ^4.6.1 - routine compatibility refreshesenvironment constraints to sdk: ^3.12.0 and flutter: ">=3.44.0" - the upgraded dependencies lift the resolved floor to Dart 3.12.0 / Flutter 3.44.0, so the declared minimums now state the true requirementNetworkLogger crashing the Flutter tool's log reader on multi-byte characters - The interceptor wrapped long request/response lines with String.substr
NetworkLogger crashing the Flutter tool's log reader on multi-byte characters - The interceptor wrapped long request/response lines with String.substring, which slices on UTF-16 code-unit boundaries and can cut a surrogate pair (any non-BMP character, e.g. an emoji) in half. The resulting lone surrogates are encoded as U+FFFD on stdout, which crashed the Flutter tool's log reader. Line wrapping now iterates grapheme clusters via package:characters, keeping emoji - along with composed sequences like flags and ZWJ emoji - whole. This affects both _printBlock and the key/value pretty-printer in lib/networking/src/interceptors/network_logger.dartMulti-instance NyStateManaged widgets - NyStateManaged now exposes a baseState (widget-type identifier) and an id (instance identifier) constructor pa
NyStateManaged widgets - NyStateManaged now exposes a baseState (widget-type identifier) and an id (instance identifier) constructor parameter, plus a composed stateKey getter that resolves to baseState when id is null and "${baseState}_$id" otherwise. Multiple instances of the same managed widget can now receive scoped state updates rather than sharing a single routing keystateAction(action, state:, id:) - The state-action helper accepts a new optional id argument; when state is a String and id is supplied, the dispatch key becomes "${state}_$id", delivering the action to the matching NyStateManaged instance onlyname constructor parameter on NyBaseState, NyState, NyPage, and JourneyState - Provides an explicit state-name override. When set it takes precedence over the existing path argument (stateName = name ?? path). NyState.initState additionally adopts the parent NyStateManaged.stateKey as its stateName when the managed widget declares a baseState, so the routing key flows from the widget down to its state automaticallyNyStateManaged.stateName (constructor parameter and getter) - Superseded by id. The constructor still accepts stateName and forwards it to id (id = id ?? stateName), and the stateName getter now returns id, so existing call sites keep compiling. New code should pass baseState + id and read stateKey for the composed routing keyBumped error_stack from ^2.1.3 to ^2.1.4 - routine compatibility refresh
error_stack from ^2.1.3 to ^2.1.4 - routine compatibility refreshBumped win32 from ^5.15.0 to ^6.3.0 - the v6 API tightens the FFI surface: console handles are now exposed as the typed HANDLE struct (with .value ret
win32 from ^5.15.0 to ^6.3.0 - the v6 API tightens the FFI surface: console handles are now exposed as the typed HANDLE struct (with .value returning the raw int), SetConsoleMode accepts a CONSOLE_MODE wrapper around its mode bitmask, and CONSOLE_CURSOR_INFO.bVisible is a bool instead of a 0/1 integer. TermLibWindows (lib/dart_console/src/ffi/win/termlib_win.dart) has been updated for each of these: inputHandle/outputHandle are now HANDLE, populated via GetStdHandle(...).value; disableRawMode() wraps its bitmask in CONSOLE_MODE(...); disabledRawModeMask is now typed CONSOLE_MODE; and hideCursor/showCursor set bVisible = false/bVisible = trueapp_links from ^6.3.2 to ^7.0.0 - keeps the deep-link plumbing introduced in 7.26.0 (Nylo.useDeepLinks, Nylo.onIncomingLink, NyDeepLinkHandler) aligned with the latest pluginflutter_secure_storage from ^10.0.0 to ^10.3.0, error_stack from ^2.1.2 to ^2.1.3, flutter_multi_formatter from ^2.13.10 to ^2.13.11, app_badge_plus from ^1.2.9 to ^1.2.10, and patrol from ^4.5.0 to ^4.6.0 - routine compatibility refreshesDeep linking support - New Nylo.useDeepLinks({String? fallbackRoute}) opts the app into platform deep-link capture (Android App Links, iOS Universal L
Nylo.useDeepLinks({String? fallbackRoute}) opts the app into platform deep-link capture (Android App Links, iOS Universal Links, custom URL schemes, and web URLs) through the new app_links dependency. Captured URIs are routed through the registered NyRouter; a path that is not registered routes to fallbackRoute when one is supplied, otherwise it falls through to the existing unknown-route handlerNylo.onIncomingLink((Uri uri) async => bool) - Registers a callback invoked for every captured deep link before routing. Return true to let Nylo route automatically, or false to handle the URI yourselfNyDeepLinkHandler - Exported from router/ny_router.dart; encapsulates cold-start and warm-start URI capture and dispatch, with injectable AppLinks and dispatcher seams for testingcollection from ^1.19.1 to ^1.18.0 - collection is also vendored by the Flutter SDK; the looser floor removes the same class of resolution conflict as the characters fix belowenvironment Flutter constraint from >=3.24.0 to >=3.38.4 - the previous value could not be satisfied alongside the sdk: ^3.10.7 Dart constraint (Flutter 3.24 ships Dart 3.5), so it now states the true minimumNylo.onDeepLink(callback) - Superseded by Nylo.onIncomingLink. The old form fires on every named route, not just deep links; it will be removed in 8.0NyLogger._colorize() accessed stdout.supportsAnsiEscapes, which throws Unsupported operation on web because dart:io is unavailable in the browser. stdout access is now guarded behind a kIsWeb check.dd() no longer throws UnsupportedError on Flutter web - the dd() ("dump and die") extensions on String, int, double, bool, Map, List, and DateTime called dart:io's exit(0), which is unavailable on web. Dump-and-exit now routes through the new NyLogger.dd() helper, which skips the exit() step on web and behaves like dump() thereflutter pub get now resolves across all supported Flutter releases - characters was constrained to ^1.4.1, but the Flutter SDK vendors characters at an exact version and the 3.38 stable line ships 1.4.0. Dependency resolution therefore failed on any Flutter release that bundles characters 1.4.0. The constraint is now ^1.4.0, which resolves whether the SDK bundles 1.4.0 or 1.4.1CupertinoPageTransitionsBuilder from the material library to the cupertino library. The router transition files (ny_page_transition_settings.dart, page_transition.dart, transition_type.dart) now import package:flutter/cupertino.dart so the class resolves on current Flutter releasesClosure-based validator on `InputField` - New validate parameter accepts (FormValidator validate, dynamic data) { ... }, letting you build rules inlin
InputField - New validate parameter accepts (FormValidator validate, dynamic data) { ... }, letting you build rules inline without constructing a FormValidator up front. Use validate.that(data, "Field").minLength(3) inside the closure. Mutually exclusive with the existing formValidator parameter (enforced via assertion)FormValidator.that(data, [attribute]) - New chainable configuration method that sets the value and attribute in a single call and returns this, designed for use inside InputField.validate closuresFormValidatorCallback typedef - Public signature void Function(FormValidator validate, dynamic data) for the closure used by InputField.validatepaddingOnly, paddingSymmetric, and visibleWhen extensions on StatefulWidget - Previously only available on StatelessWidget; StyledText and other StatefulWidgets can now be wrapped via these fluent helpers (e.g. StyledText.template(...).paddingOnly(top: 20))InputField.handleValidationError now fires when validation results change - The callback was declared but never invoked by the internal _validate flow. Results are now reported on each transition (first run and whenever the error message changes), deferred to the next frame so handlers can safely call setState`MetroService.runProcess` no longer breaks the parent CLI's stdin - the helper used to wire stdin.pipe(process.stdin) to the child, which left the par
MetroService.runProcess no longer breaks the parent CLI's stdin - the helper used to wire stdin.pipe(process.stdin) to the child, which left the parent's stdin in a consumed state once the child exited. Subsequent readLineSync-based prompts (e.g. in scaffold-ui's auth/iap dialogs) returned null and the unhandled !-on-null tore down the program. The child now inherits the parent's file descriptors directly via ProcessStartMode.inheritStdio, leaving the parent's stdin untoucheddart_console.disableRawMode() no longer zeroes the Windows console mode - the disabled-mode bitmask was built with & instead of |, so the OR-only-makes-sense flags resolved to 0 and SetConsoleMode(handle, 0) killed line input, echo, and processed input. As a result, stdin.readLineSync on Windows could not detect Enter after a Console.readKey call. The mask is now correctly OR-combined`CollectionView` no longer crashes mid-refresh on long lists - _onRefresh previously assigned _data = [] synchronously *before* awaiting the new data,
CollectionView no longer crashes mid-refresh on long lists - _onRefresh previously assigned _data = [] synchronously before awaiting the new data, which could leave the live SliverList pointing at an empty list mid-frame and throw RangeError when cached children relayed out. _data is now mutated only inside setState after the new data resolvesCollectionView accepts List<dynamic> returned from JSON-decoded API responses - previously a List<dynamic> (the typical shape from jsonDecode) would trip an internal List<T> assertion. The widget now lazily casts via List.cast<T>(), so callers no longer have to call .cast<T>() themselvesCollectionView.stateActions(name).refreshData() no longer clears the list mid-fetch - _data was being cleared synchronously before the new data resolved, briefly showing an empty state. The list is now preserved until the new data is readypaginatedData on pull-to-refresh now preserves the existing list instead of incorrectly calling loadNoData(). The refresh indicator settles and the previous data remains visible`Str` helper class - New static utility class for string manipulation. Includes search/position helpers (after, before, between, contains, startsWith,
Str helper class - New static utility class for string manipulation. Includes search/position helpers (after, before, between, contains, startsWith, endsWith, is_, position, match, excerpt), case conversions (camel, snake, kebab, studly, title, headline), trimming/capping (limit, words, finish, start, wrap, unwrap, squish), replace/transform (replace, remove, swap, deduplicate, ucsplit), slug generation, padding (padBoth, padLeft, padRight, padNumber), substring/chars (substr, take, charAt, reverse, repeat), masking, random/IDs (random, password, uuid, uuid7, ulid), and validation (isAscii, isJson, isUrl, isUuid, isUlid)Number helper class - New static utility class for working with numbers. Includes formatting (format, currency, percentage, fileSize, forHumans, abbreviate), ordinal/spelling (ordinal, spell, spellOrdinal), parsing (parseInt, parseFloat), math/utility (clamp, trim, pairs, between, round, floor, ceil, lerp, scale, gcd, lcm, degrees, radians), random generation, file-size inverse/duration (toBytes, duration), and range/aggregates (range, sum, average, median, min, max). Configurable default locale and currencyArr helper class - New static utility class for working with lists. Includes type checks (accessible, isList, isAssoc), construction (wrap, flatten, collapse, crossJoin), filtering (first, last, where, reject, whereNotNull, unique, exceptValues, onlyValues), slicing/chunking (take, chunk, prepend, push, interleave), ordering (shuffle, sort, sortDesc, sortRecursive), random selection, iteration (map, mapWithKeys, flatMap, indexed, partition, groupBy), immutable mutations (replaceAt, move, swap), aggregates (every, some, sole, join, sum, average, median, min, max, countBy), and map-list operations (pluck, keyBy, select)Obj helper class - New static utility class for working with maps using dot notation. Includes read (get, has, hasAny, hasAll, exists), typed read (getString, getInt, getDouble, getBool, getList, getMap), mutating writes (set, add, forget, pull), subset (only, except, prependKeysWith, divide), filter (whereNotNull, whereNotEmpty), transform (mapKeys, mapValues, flip), flatten/inflate (dot, undot), and merge/compare/query helpers (merge, deepEquals, query)Bumped error_stack dependency from ^2.1.1 to ^2.1.2
error_stack dependency from ^2.1.1 to ^2.1.2`NyStateManaged` widget - A new StatefulWidget that accepts a child (either a State instance or a function returning one) and an optional stateName, a
NyStateManaged widget - A new StatefulWidget that accepts a child (either a State instance or a function returning one) and an optional stateName, allowing pre-built states to be wired into the widget tree directly via createState. Exported from package:nylo_support/widgets/ny_widgets.dartToast helper methods now accept `duration` and `data` parameters - showToastSorry, showToastWarning, showToastInfo, showToastDanger, showToastOops, an
duration and data parameters - showToastSorry, showToastWarning, showToastInfo, showToastDanger, showToastOops, and showToastSuccess now forward optional duration (custom display time) and data (custom payload) arguments to the underlying showToast calldescription parameter on toast helpers is now optional - showToastSorry, showToastWarning, showToastInfo, showToastDanger, showToastOops, and showToastSuccess no longer require description, aligning their signatures with the underlying showToast method. Existing call sites continue to work unchangedMetro CLI theme scaffolding commands removed - The make:theme and make:theme_colors Metro commands have been removed along with their underlying metho
make:theme and make:theme_colors Metro commands have been removed along with their underlying methods (MetroService.makeTheme, MetroService.makeThemeColors, MetroService.addToTheme). The themesFolder, themeColorsFolder, and themeDarkFlag constants have also been removed. Themes can still be created manually in lib/resources/themes/Bumped error_stack dependency from ^2.0.1 to ^2.1.1
error_stack dependency from ^2.0.1 to ^2.1.1`NyScheduler.getKeyTaskOnce(name)` now returns the full prefixed storage key (ny_scheduler_${name}_once) instead of the unprefixed ${name}_once. This
NyScheduler.getKeyTaskOnce(name) now returns the full prefixed storage key (ny_scheduler_${name}_once) instead of the unprefixed ${name}_once. This makes the documented reset pattern await NyStorage.delete(NyScheduler.getKeyTaskOnce("welcome_to_app")) actually delete the stored flagNyScheduler.clearTaskOnce(name) convenience method that clears a once-task's executed state without needing to compute the storage key manuallyapp_badge_plus dependency from ^1.2.8 to ^1.2.9New `useSafeArea` option on `NavigationHubLayout.journey()` - Controls whether journey content is wrapped in a SafeArea. Defaults to true (existing be
useSafeArea option on NavigationHubLayout.journey() - Controls whether journey content is wrapped in a SafeArea. Defaults to true (existing behavior). Set to false for edge-to-edge journey pages where backgrounds should extend under system UI (status bar, home indicator)`Connective` widget redesigned - Flipped semantics from "show when connected" to "show when missing". Removed onWifi, onMobile, onEthernet, onVpn, onB
Connective widget redesigned - Flipped semantics from "show when connected" to "show when missing". Removed onWifi, onMobile, onEthernet, onVpn, onBluetooth, onSatellite, onOther, onNone parameters in favour of a single noInternet parameter that displays a fallback when the device has no internet (wifi, mobile, or ethernet). Migration: replace onNone: widget with noInternet: widget. Use Connective.builder() for any custom connectivity handlingshowLoadingOnInit and loadingWidget from Connective - the initial connectivity check is near-instant, making a loading state unnecessaryOfflineBanner now checks for internet absence (wifi/mobile/ethernet) rather than NyConnectivityState.none, correctly showing the banner when the device only has non-internet connectionsNyConnectivity.hasInternet() helper - Checks specifically for wifi, mobile, or ethernet connectivity. Stricter than isOnline() which passes for any non-none resultCollectionView.refreshData state action - Re-fetches data explicitly for both pullable and regular modes instead of relying on reboot(), resetting pagination, loading state, and footer state correctlyCollectionView not updating when parent rebuilds with new data - Sync data callbacks (e.g. data: () => _filteredList) were only read once due to _sync
data: () => _filteredList) were only read once due to _syncDataInitialized flag introduced in v7.16.0, breaking filtering/search patterns. Added didUpdateWidget override to reset the flag on parent rebuilds while preserving stateActions behaviorCollectionItem helpers, sync/async data, empty states, headers, spacing, transform/sort, separated/grid layouts, parent-driven data updates, and configuration optionsNew `actingAsGuest()` test helper - Semantic alias for logout() that reads better in test setup
actingAsGuest() test helper - Semantic alias for logout() that reads better in test setupexpectApiCalledWith() test helper - Assert that an API endpoint was called with specific request data, checking both endpoint and request body via deep equalityexpectWidgetCount() test helper - Assert that a widget of a given type appears exactly N timesexpectTextVisible() / expectTextNotVisible() test helpers - Assert text presence or absence in the widget treeexpectVisible() / expectNotVisible() test helpers - Assert widget presence or absence using any FinderassertOnRoute() test helper - Assert the current route matches a given route without implying navigation just occurrednavigateBack() test helper - Pop the current route and settle, simulating the back buttontapText() test helper - Find a widget by text, tap it, and settle in one callfillField() test helper - Tap a form field, enter text, and settle in one callscrollTo() test helper - Scroll until a widget is visible in the nearest ScrollableNew `visit()` test helper - Pump a route with full Nylo navigation support, setting up MaterialApp with the NyRouter's route generator, navigator key,
visit() test helper - Pump a route with full Nylo navigation support, setting up MaterialApp with the NyRouter's route generator, navigator key, and route history observer so that routeTo navigation works correctly in testsassertNavigatedTo() test helper - Assert that the app navigated to a given route by checking Nylo.getCurrentRouteName() matches the expected route pathsettle() test helper - A readable alias for pumpAndSettle that waits for all animations, frame callbacks, and pending UI updates to completeCollectionView `stateActions` not working with synchronous data - State actions like addItem, insertItem, removeFromIndex, and updateItemAtIndex were
stateActions not working with synchronous data - State actions like addItem, insertItem, removeFromIndex, and updateItemAtIndex were being overwritten on every rebuild because _buildRegularView re-called the data callback. Now synchronous data is only fetched once and preserved across rebuildsNyPage controller state name assignment - Controller now receives the correct state nameInputField state actions - focus(), unfocus(), and toggleObscure() for programmatic control of text fieldsLanguageSwitcher.stateActions() - refresh() and setLanguage() methods for programmatic language switchingapp_badge_plus to ^1.2.8connectivity_plus to ^7.1.1Environment variable interpolation in `NyEnvRegistry` - String env values now support ${VAR_NAME} syntax to reference other env keys. For example, APP
NyEnvRegistry - String env values now support ${VAR_NAME} syntax to reference other env keys. For example, APP_URL=https://${APP_DOMAIN} will resolve by looking up APP_DOMAIN. Supports chained references, non-string value conversion, and circular reference protection`bottomToTop` and `topToBottom` page transitions animating the previous route - Added canTransitionFrom override to PageTransition that returns false
bottomToTop and topToBottom page transitions animating the previous route - Added canTransitionFrom override to PageTransition that returns false for bottomToTop and topToBottom transition types, preventing the outgoing page from sliding away during modal-style transitions`isDismissible` and `enableDrag` parameters for `NyBaseModal.show()` - New optional parameters to control whether the modal can be dismissed by tappin
isDismissible and enableDrag parameters for NyBaseModal.show() - New optional parameters to control whether the modal can be dismissed by tapping the barrier (isDismissible, defaults to true) and whether the modal supports drag-to-dismiss gestures (enableDrag, defaults to true). Both are passed through to the underlying showModalBottomSheetSatellite connectivity support for `Connective` widget and `NyConnectivityState` - Added satellite value to the NyConnectivityState enum with mapping
Connective widget and NyConnectivityState - Added satellite value to the NyConnectivityState enum with mapping from ConnectivityResult.satellite, and added onSatellite widget parameter to Connective for rendering satellite-specific UI* key for StyledText.template styles and onTap - When no exact or pipe-delimited key matches a placeholder, the styles/onTap map now falls back to a * wildcard key, allowing a single style or tap handler to apply to all placeholdersconnectivity_plus ^7.1.0`creationPath` support for Metro scaffolding commands - Provider, route guard, form, and event scaffolding commands now support creationPath using cre
creationPath support for Metro scaffolding commands - Provider, route guard, form, and event scaffolding commands now support creationPath using createPathForDartFile and createDirectoriesFromCreationPath for consistent nested directory path handlingsetState callback parameter for NyFieldBuilder - The NyFieldBuilder typedef now includes a setState callback parameter. A NyFieldBuilderLegacy typedef is available for backward compatibility. Field.builder accepts both signaturesflutter_timezone ^5.0.2, patrol ^4.5.0Response data unavailable in `handleSuccess`/`handleFailure` callbacks - When skipMorph was true (a callback was provided), morphedData was left null,
handleSuccess/handleFailure callbacks - When skipMorph was true (a callback was provided), morphedData was left null, so nyResponse.data was inaccessible inside the callback. The raw response data is now passed through to morphedData when the type matches, allowing callbacks to access nyResponse.data`toast-oops` calling wrong toast method - The toast-oops state action was incorrectly calling showToastInfo() instead of showToastOops(), causing oops
toast-oops calling wrong toast method - The toast-oops state action was incorrectly calling showToastInfo() instead of showToastOops(), causing oops-style toasts to display as info-style toastsField.password() not respecting viewable parameter - The viewable parameter was not being passed through to FieldStyleTextField.password(), so the password visibility toggle setting was ignored when constructing password fieldsNyPage.initState() state name resolution - The state name for NyStatefulWidget is now resolved unconditionally in initState(), rather than only when stateManaged is true. The event bus subscription logic is now a single stateManaged && allowStateUpdates check with reduced nestingflutter_local_notifications ^21.0.0, timezone ^0.11.0, patrol ^4.3.0`action()` method on `StateActions` - New convenience method to call stateAction() directly from any StateActions instance, accepting an action name a
action() method on StateActions - New convenience method to call stateAction() directly from any StateActions instance, accepting an action name and optional data parameterinit() in NyPage and NyState - The controller is now eagerly constructed with the current context if it hasn't been initialized yet, and the widget's state name is propagated to the controller before use. This fixes issues where the controller was not ready during early lifecycle methods`enableInteractiveSelection` for `InputField` and `FieldStyleTextField` - New parameter to control whether text selection handles and toolbar are show
enableInteractiveSelection for InputField and FieldStyleTextField - New parameter to control whether text selection handles and toolbar are shown. Available on InputField, InputField.compact, InputField.password, InputField.email, InputField.fromFieldStyleText, and FieldStyleTextFieldFieldStyleTextField.copyWith losing existing values - Parameters like textCapitalization, maxLengthEnforcement, onAppPrivateCommand, inputFormatters, cursorWidth, dragStartBehavior, and clipBehavior now correctly fall back to this.xxx instead of overriding with hardcoded defaultsForm submit button not calling `onSubmit` - Fixed ButtonState passing NyFormData.stateName (already prefixed with form_) to NyFormWidget.submit(), whi
onSubmit - Fixed ButtonState passing NyFormData.stateName (already prefixed with form_) to NyFormWidget.submit(), which added the prefix again resulting in form_form_FormName. Now correctly passes NyFormData.name so the state name resolves properlyData-aware toast notification styles - Toast styles can now receive dynamic data at call time via a new ToastStyleDataFactory typedef. Register data-a
ToastStyleDataFactory typedef. Register data-aware styles with registerWithData() or pass both static and data-aware factories to registerAll() and addToastNotifications()data parameter for toast helpers - Added optional data parameter to showToastNotification(), NyBaseState.showToast(), NyBaseState.showToastCustom(), NyController.showToastCustom(), and StateAction.showToastCustom() to pass custom key-value pairs to data-aware toast stylesToastNotificationRegistry.resolve() - New method that resolves a toast style by ID and passes data to data-aware factories, replacing direct get() calls internallyenablePullDown parameter for CollectionView - Added enablePullDown option to all CollectionView constructors (.list, .separated, .grid, .pullable, .pullableSeparated, .pullableGrid) to control whether pull-to-refresh is enabledqueryParamPage renamed to paramPage and queryParamPerPage/queryNamePerPage renamed to paramPerPage in nyApi() and api() helpers for consistencyNyFormWidget state methods use stateAction() - Refactored stateSetValue(), stateSetOptions(), clearField(), and submit() to use stateAction() instead of updateState() for cleaner form state managementUpdated dependency constraints: dio ^5.9.2, skeletonizer ^2.1.3, error_stack ^2.0.1, app_badge_plus ^1.2.7, uuid ^4.5.3, characters ^1.4.1, ffi ^2.2.0
dio ^5.9.2, skeletonizer ^2.1.3, error_stack ^2.0.1, app_badge_plus ^1.2.7, uuid ^4.5.3, characters ^1.4.1, ffi ^2.2.0, patrol ^4.1.1`NavigationHubStateActions.refreshTab()` - Refresh a specific tab by index, forcing it to rebuild with a new UniqueKey
NavigationHubStateActions.refreshTab() - Refresh a specific tab by index, forcing it to rebuild with a new UniqueKeyNavigationHubStateActions.refresh() - Refresh all tabs in the navigation hub, forcing them all to rebuildrootNavigator parameter for pop() - Added rootNavigator option to NyBaseState.pop(), NyController.pop(), StateAction.pop(), and BuildContext.pop() to support popping from the root navigator when using nested navigation`ArgumentsWrapper` JSON serialization crash - Route arguments containing non-serializable objects (e.g. model instances, enums) would throw a JsonUnsu
ArgumentsWrapper JSON serialization crash - Route arguments containing non-serializable objects (e.g. model instances, enums) would throw a JsonUnsupportedObjectError when Flutter's NavigatorState called jsonEncode during state restoration or post-navigation logging. A new _safeEncode() helper now recursively converts non-primitive values to safe representations before encodingtoJson() on ArgumentsWrapper - Added toJson() method required by Flutter's NavigatorState for JSON encoding route arguments`Field.builder` constructor - New constructor that lets developers create custom form fields inline using a builder function, without needing to subcl
Field.builder constructor - New constructor that lets developers create custom form fields inline using a builder function, without needing to subclass NyFieldStatefulWidget. Includes NyFormBuilder widget and FormBuilderStateActions with clear and setValue supportFormValidator.nullable() method - Mark a validator as nullable so that null or empty values automatically pass validation; non-empty values still have all rules appliedLanguageSwitcherAnimationStyle - New configuration class for controlling animations on the LanguageSwitcher inline popup trigger and bottom modal list items, with preset factories: none(), subtle(), bouncy(), and fadeIn()useRootNavigator parameter for LanguageSwitcher.showBottomModal - Allows the bottom modal to be presented above all navigators when using nested navigationInputField autocorrect property not forwarded - The autocorrect parameter was accepted by the widget but never passed to the underlying TextFieldNyFormPicker selected value layout from a Stack with Positioned widgets to a Column, improving readability and consistencyLanguageSwitcher inline popup now supports trigger scale animation, popup content fade-in via _PopupContentFade, and configurable animation durations and curves for list item transitions`Backpack.read ()` Map deserialization - When a value stored in the Backpack is a raw Map (e.g. from syncKeys), calling read () with a typed parameter
Backpack.read<T>() Map deserialization - When a value stored in the Backpack is a raw Map<String, dynamic> (e.g. from syncKeys), calling read<T>() with a typed parameter now automatically deserializes it into the corresponding model and caches the result for subsequent readsLanguageSwitcher list items - Tapping a language in LanguageSwitcher.showBottomModal now displays a CircularProgressIndicator on the selected item while the language switch processes, providing clear visual feedbackCollectionView findChildIndexCallback renamed to findItemIndexCallback - Updated the ListView.separated builder to use the renamed Flutter SDK parameter, fixing compatibility with recent Flutter versionsLanguageSwitcher modal not closing immediately on selection - Moved navigator.pop() to execute before storeLanguage and onLanguageChange so the bottom sheet dismisses instantly rather than waiting for async operations to completeT.toString() != 'dynamic' and _isType<T, U>() helper calls with direct T != dynamic / T == Type comparisons in Backpack and NyStorage for cleaner, more idiomatic type checking_LanguageListItem.onTap type from VoidCallback to Future<void> Function() to support async tap handling with loading state`contentPadding` and `actionsPadding` for `NyBaseModal.show()` and `NyModalLayout` - New optional padding parameters that allow fine-grained control o
contentPadding and actionsPadding for NyBaseModal.show() and NyModalLayout - New optional padding parameters that allow fine-grained control over the modal's content area and actions section spacingFieldStyleTextField.password() suffixIcon always rendered - The password field style factory now conditionally sets the visibility toggle icon based on passwordViewable, returning null when disabled instead of always rendering a non-functional IconButtonInputField suffixIcon overriding password toggle - Custom suffixIcon is now only applied when passwordViewable is not true, preventing it from replacing the password visibility toggle buttonshowToastSorry, showToastWarning, showToastInfo, showToastDanger, showToastOops, showToastSuccess, showToastCustom). The title parameter now passes through as-is, allowing the toast notification registry to handle default titles consistently with the i18n approach`onLanguageChange` callback for `LanguageSwitcher.showBottomModal` - New optional callback parameter that fires when the user selects a different lang
onLanguageChange callback for LanguageSwitcher.showBottomModal - New optional callback parameter that fires when the user selects a different language, providing the selected language keyLanguageSwitcher.showBottomModal future completing immediately - Added missing return before showModalBottomSheet so the method's future now correctly waits for the modal to close before completingApp lifecycle not assigned in `Nylo.init()` - The appLifecycle parameter was accepted but never assigned to _appLifecycle, causing nylo.appLifecycleSt
Nylo.init() - The appLifecycle parameter was accepted but never assigned to _appLifecycle, causing nylo.appLifecycleStates to always return null. Now correctly assigns the value during initialization_formCasts field and related methods (addFormCasts, getFormCasts) from the Nylo classformCasts parameter from Nylo.configure()flutter_local_notifications constraint to ^20.1.0timezone constraint to ^0.10.0Localization fallback locale support - When a translation key is missing in the current locale, NyLocalization now automatically falls back to the def
NyLocalization now automatically falls back to the default language before returning the raw key. Supports both top-level and nested (dot-notated) keysNyLocalization.setValuesForTesting() - New test helper method for directly setting translation values and fallback values in unit testsinitializeDateFormatting() call in Nylo.init() to ensure all locale-specific date format data is available, preventing failures when formatting dates in non-default localesNyBaseModal now applies bottom padding matching MediaQuery.viewInsets.bottom when isScrollControlled is true, preventing the on-screen keyboard from covering modal content`FieldDefinition` class and `define()` helper - Set both a value and options for form fields in NyFormWidget.init, enabling deferred option loading fr
FieldDefinition class and define() helper - Set both a value and options for form fields in NyFormWidget.init, enabling deferred option loading from APIsPickerListTileStyle - Style configuration for picker bottom sheet list tiles with radio, checkmark, and custom builder presets via PickerListTileIndicatorFieldStylePicker alignment properties - Added placeholderAlignment, selectedValueAlignment, and selectedValuePadding for fine-grained picker layout controlFieldStyleDateTimePicker clear controls - Added canClear and clearIconData properties to control date/time field clearing behaviorFieldStyleSwitchBox extended properties - Added activeTrackColor, inactiveThumbColor, inactiveTrackColor, thumbColor, trackColor, trackOutlineColor, thumbIcon, dragStartBehavior, and thumb image propertiesInputField suffixIcon support - Added suffixIcon parameter across all InputField constructors and copyWithStyledText.template key:text syntax - New {{key:text}} placeholder syntax for localization-friendly styled text where the display text is separate from the style lookup keyFormCollection.empty() constructor - New const constructor for empty form collections, useful as a default for fields with deferred optionsField.datetime / Field.date direct parameters - Added firstDate, lastDate, dateFormat, and initialPickerDateTime directly on field constructorsField.picker / Field.radio / Field.chips optional options - The options parameter is no longer required; defaults to FormCollection.empty() for deferred loading via define()styled_text_test.dart test suite for StyledText.template with key:text and pipe-key syntaxunselectedLabelStyle and unselectedItemColor to inactive tabspage.value.icon before text widget when no activeIcon is setsetValue to restoreValue in clear/setValue actions to prevent redundant UI update cyclesNyResponse.ifSuccessful / when null safety - Fixed type promotion with local variable for proper null-safetyField.currency initial value - Now uses dummyData as fallback for initial value when value is nullInputField format-on-init - Initial text values now pass through input formatters so programmatic values (e.g. from define()) display formattedInputField setValue with formatters - The setValue state action now applies input formatters to the valueWidgetsFlutterBinding.ensureInitialized() to Nylo.configure() to ensure binding before configurationdynamic parameter types across multiple methods for lint compliancenon_constant_identifier_names and camel_case_types from analysis_options.yaml; moved to targeted ignore_for_file commentserrorResponses now uses whereType<FormValidationError>() instead of where().cast().r/.g/.b/.a/.toARGB32())Namespaced translation keys - All hardcoded English strings in widgets now use namespaced translation keys for better i18n support. Keys added:
nylo.page_not_found.title, nylo.page_not_found.message, nylo.page_not_found.go_backnylo.collection_view.no_results, nylo.collection_view.pull_up, nylo.collection_view.failed, nylo.collection_view.releasenylo.offline_banner.messagenylo.form_picker.select, nylo.form_picker.clearnylo.language_switcher.titlenylo.journey.of, nylo.journey.step, nylo.journey.back, nylo.journey.next, nylo.journey.finishnylo.confirm_action.cancel, nylo.confirm_action.confirmuseRootNavigator and modalBackgroundColor parameters to NyBaseModal.show() and NyModalLayoutalignLabelWithHint and textAlignVertical for multiline fields; passes through prefixIconConstraints from decorationCustomAnimationBuilder from flutter_styled_toast via ny_core.dartparams to data across NyListener, NyEventBus, NyEventCallbackListener, and NyEventExtension for clarityDioApiService.handleResponse now conditionally skips data morphing when handleSuccess or handleFailure callbacks are provided, and properly returns callback resultsDioApiService caching logic fixed to avoid null reference when saving cached responsesNyBaseModal.show() default for useSafeArea changed from true to falseJourneyContent uses Expanded instead of Flexible for main content areany_metro.dart imports with collection package in InputField and LanguageSwitchercollection package dependency (^1.19.1)Complete library restructuring - All modules have been reorganized from flat file layouts into src/ subdirectories with barrel file exports. Import pa
src/ subdirectories with barrel file exports. Import paths have changed across the entire library:
lib/alerts/ files moved to lib/alerts/src/ with barrel ny_alerts.dartlib/controllers/ files moved to lib/controllers/src/ with barrel ny_controllers.dartlib/event_bus/ files moved to lib/event_bus/src/ with barrel ny_event_bus.dartlib/events/ files moved to lib/events/src/ with barrel ny_events.dartlib/helpers/ files moved to lib/helpers/src/ with barrel ny_helpers.dartlib/local_notifications/ files moved to lib/local_notifications/src/ with barrel ny_local_notifications.dartlib/local_storage/ files moved to lib/local_storage/src/ with barrel ny_local_storage.dartlib/localization/ files moved to lib/localization/src/ with barrel ny_localization.dartlib/metro/ files moved to lib/metro/src/ with barrel ny_metro.dartlib/networking/ files moved to lib/networking/src/ with barrel ny_networking.dartlib/providers/ files moved to lib/providers/src/ with barrel ny_providers.dartlib/router/ files moved to lib/router/src/ with barrel ny_router.dartlib/themes/ files moved to lib/themes/src/ with barrel ny_themes.dartlib/widgets/ files moved to lib/widgets/src/ with barrel ny_widgets.dartlib/dart_console/ reorganized with barrel ny_dart_console.dartlib/ny_core.dart exports all modules in one importenv parameter as EnvGetter type and accepts BootConfig for setup. The setup and setupFinished callbacks have been replaced by the BootConfig class patternNyEnvRegistry.register(getter: Env.get) instead of reading .env files directlytheme_provider package with new NyThemeManager singleton, NyThemeProvider widget, and NyThemeStorage for persistence. Theme registration now uses nylo.addThemes() with optional initialThemeId parameterBaseColorStyles - Replaced by ThemeColor abstract class in lib/themes/src/theme_color.dartNyRichText renamed to StyledText (with StyledText.template() constructor)NyTextField renamed to InputFieldNyFutureBuilder renamed to FutureWidgetNyFader renamed to FadeOverlay (with .top(), .bottom(), .left(), .right() constructors)NyPullToRefresh and NyListView consolidated into CollectionView (with CollectionItem wrapper class)NyPullable renamed to PullableNyLanguageSwitcher renamed to LanguageSwitcherNyTextStyle - No longer part of the libraryValidationException - Validation exceptions moved to form-specific handlingNyLoginForm - Replaced by general NyForm capabilitiesevents.dart - Events now use dedicated ny_events.dart barrel with new architecturerouter.dart - Router now uses dedicated ny_router.dart barreldart_console.dart - Dart console now uses dedicated ny_dart_console.dart barrelvalidation/ directory - Validation rules (ny_validator.dart, rules.dart, validations.dart) have been moved into the form system^3.10.7>=3.24.0lib/testing/) - A comprehensive testing framework with PHPUnit/Pest-like syntax:
NyTest - Main test orchestrator with init(), actingAs(), travel(), travelForward(), travelBack(), freezeTime(), dump(), dd() methodsNyWidgetTest - Widget testing utilities with pumpNyWidget() and pumpNyWidgetSimple() for easy widget testingNyTime - Time manipulation for testing (freeze, advance, rewind)NyFactory / NyFaker - Laravel-style model factories for generating test dataNyMockApi - API mocking with type-based handlers and URL pattern matching (supports * and ** wildcards)NyMockChannels - Platform channel mocking for testsNyMockRouteGuard - Route guard mockingNyTestCache - In-memory cache for testsNyStateTestHelpers - State testing helpersnyTest(), nyGroup(), nyWidgetTest(), nySetUp(), nyTearDown(), nySetUpAll(), nyTearDownAll(), nySkip(), nyFailing(), nyCi()expectAuthenticated(), route assertions, backpack assertions, locale assertionslib/helpers/src/ny_connectivity.dart) - Network connectivity helper with isOnline(), isOffline(), isWifi(), isMobile(), isEthernet(), isVpn(), isBluetooth(), stream(), whenOnline(), when(), connectionTypeString()lib/widgets/src/connective.dart) - Reactive widget that rebuilds based on connectivity state. Includes Connective.builder(), OfflineBanner widget, and widget extensions .connectiveOr(), .onlyOnline(), .onlyOffline()lib/helpers/src/ny_env.dart) - New centralized environment variable management with register(), get(), containsKey(), isInitializedlib/providers/src/providers.dart) - New configuration class for bootstrapping Nylo applications with setup and boot lifecycle functionslib/helpers/src/button_animation_style.dart) - Composable button animation styles: clickable (Duolingo-style 3D press), bounce, pulse, squeeze, jelly, shine, ripple, morph, shakelib/helpers/src/button_splash_style.dart) - Customizable button splash effects: ripple, highlight, glow, ink, none, customlib/widgets/src/animated_button_wrapper.dart)lib/widgets/src/ny_base_modal.dart) - Base class for creating modal bottom sheets with customizable layouts, headers, action rows/columns, close buttons, and drag handleslib/networking/src/models/ny_response.dart) - Enhanced API response class with isSuccessful, isClientError, isServerError, isRedirect, isUnauthorized, isForbidden, isNotFound, isTimeout, isRateLimited, dataOrThrow(), dataOr(), ifSuccessful(), when(), errorMessagelib/networking/src/models/cache_policy.dart) - API request caching strategies: networkOnly, cacheFirst, networkFirst, cacheOnly, staleWhileRevalidatelib/networking/src/interceptors/network_logger.dart) - New Dio interceptor with log levels (verbose, minimal, none), color terminal output, structured JSON output, and UUID-based request ID trackinglib/helpers/src/mixins/api_service.dart) - Mixin for classes that need typed API service access with onApiSuccess() and onApiError() callbackslib/themes/src/ny_theme_manager.dart) - Singleton theme manager with reactive updates via themeNotifier, system theme following, theme change stream, typed color styles, multi-theme support with preferred themeslib/themes/src/ny_theme_provider.dart) - Widget providing theme context with AnimatedTheme for smooth transitionslib/themes/src/ny_theme_storage.dart) - Secure storage for theme persistence including preferred light/dark theme IDs and follow-system preferencelib/helpers/src/ny_url.dart) - URL launching helpers with UrlLaunchModeType enum (externalApplication, inAppWebView, inAppBrowserView, platformDefault)FadeOverlay.top(), .bottom(), .left(), .right() and configurable strength parameterisFirst, isLast, isEven, isOdd, index, totalItems helpers for list items in CollectionView{{placeholder}} syntax and pipe-separated style groupslib/local_storage/src/storage_exceptions.dart) - StorageException, StorageSerializationException, StorageDeserializationException, StorageKeyNotFoundException, StorageTimeoutExceptionFormSlider and FormRangeSlider form fields, new FormTextField field, new FieldStyle configuration classlib/dart_console/src/spinner.dart) - New spinner component for CLI outputRunnable serviceswipeAllStorageData() with added excludeKeys parametercontainsRoutes()Nylo.init() - Services parameter accepting List<FutureOr<Runnable>> with three lifecycle phases: onInit(), onReady(), onAppReady()onLog and onRouteChange callbackslib/widgets/src/ny_app.dart) - New app-level widgetlib/widgets/src/text_tr.dart) - Text widget with built-in translation supportlib/router/src/route_matcher.dart) - Dedicated route matching utilitylib/router/src/router_functions.dart) - Extracted router utility functionslib/router/src/ny_navigator.dart) - Extracted navigator classlib/widgets/src/navigation_hub/bottom_nav_style.dart) - Navigation hub bottom nav stylingtest/alerts/, test/controllers/, test/core/, test/dart_console/, test/event_bus/, test/events/, test/helpers/, test/local_notifications/, test/local_storage/, test/localization/, test/metro/, test/networking/, test/providers/, test/router/, test/testing/, test/themes/, test/widgets/)env: EnvGetter (required), setup: BootConfig?, appLifecycle, and services parametersToastNotificationRegistry and ToastStyleFactory - configure via nylo.addToastNotifications()StorageConfig, StorageManager, StorageUtils, StorageHelpers, and NyStorageAndroidNotificationConfig, IOSNotificationConfig, LocalNotification, NotificationAttachment, NotificationExceptionNyEvent interface, EventBus, EventSubscription, event extensions, and ListenerNyLogger now supports onLog callback for external logging integrationNyRouteHistoryObserver now supports onRouteChange callback for external route trackingNyLocalization refactored with NyLocalizationConfig class for configurationservice_runner dependencyflutter_local_notifications to ^20.0.0connectivity_plus to ^7.0.0pubspec.yaml repository URL updated to 7.x branchpubspec.yaml SDK constraint updated to ^3.10.7patrol as dev dependency for widget testingtheme_provider package dependency - replaced by built-in NyThemeManager/NyThemeProviderpretty_dio_logger package dependency - replaced by built-in NetworkLogger interceptorlib/validation/ directory (ny_validator.dart, rules.dart, validations.dart)lib/exceptions/validation_exception.dartlib/forms/ny_login_form.dartlib/helpers/ny_text_style.dartlib/widgets/styles/ny_radio_tile_style.dartlib/events/events.dart, lib/router/router.dart, lib/dart_console/dart_console.dart, lib/providers/providers.dart, lib/local_storage/local_storage.dart, lib/local_notifications/local_notifications.dart, lib/localization/app_localization.dart, lib/networking/ny_base_api_service.dart)Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →