spring_boot_starter_flutter 0.6.2
spring_boot_starter_flutter: ^0.6.2 copied to clipboard
Spring Boot for Flutter apps: SpringApplicationWidget, beans in widgets, state beans that rebuild widgets, lifecycle, platform profiles, themes from properties.
0.6.2 #
Changes #
- Files of the app (0.6.2):
FileTemplate(beansfileTemplateandplatformFileStore, each only when the app declares none) writes and reads text, bytes and objects (JSON through theObjectMapper) in the placessupport(default),cacheanddocuments(files.cache.write(...)), withexists,delete,list(prefix)andmodifiedAt. Writes are atomic (temporary file, then rename), paths stay inside their place (..and absolute paths are refused).temp((file) async {...})andtempDir(...)give a unique temporary file or folder deleted after the block (an error too);createTemp()leaves the deleting to the caller; leftovers are removed when the context closes and, for runs that died, at the next start (<system temp>/spring/<run id>/). The bytes go through a replaceableFileStore(LocalFileStoreonpath_provider's directories, IndexedDB in a browser; temporary files in memory there, with no path). New dependency:spring_web_dart(see below). - One set of app directories (0.6.2): SQLite's
locationandFileTemplate's places share one mapping. On Windowssupportis%LOCALAPPDATA%\<company>\<product>(the machine's own) for both, andcacheis thecachefolder inside it (path_provider's cache directory is the local root itself, so it would have been the same folder assupport); the other platforms are unchanged. - The theme from a URL (0.6.2):
spring.flutter.theme.themes.<name>.source(anhttpsURL orgithub:owner/repo/path@ref),source-sha256andrefresh. The theme is cached throughFileTemplate(support,spring/themes/<sha256 of source and pin>/theme.ymlandmeta.json) and survives restarts: withoutrefreshdownloaded once and read from the cache for ever; withrefreshthe cache is used at once and read again in the background (If-None-Match/If-Modified-Since) when older, and a new theme is shown live. Anothersourceorsource-sha256downloads again; caches of sources no longer configured are removed at start; offline or on any error the cache, else the theme of the app's own files; size limit 1 MiB, timeout 10 s,httpsonly (redirects too). Only the theme's keys are taken from the file, the rest is ignored with a warning.SpringThemes.applySourcesets the properties of one such theme. The HTTP client is the app'sHttpTransportbean orspring_web_dart's platform client: the package depends onspring_web_dartnow. - The whole theme (0.6.2):
spring.flutter.theme.components.*sets every component theme ofThemeData(48: app bar, badge, banner, bottom app bar, bottom navigation bar, bottom sheet, the buttons, card, carousel, checkbox, chip, data table, date and time pickers, dialog, divider, drawer, dropdown menu, expansion tile, icon themes, input decoration, list tile, menu, menu bar, menu button, navigation bar, drawer and rail, popup menu, progress indicator, radio, scrollbar, search bar and view, slider, snack bar, switch, tab bar, text selection, toggle buttons, tooltip) with Flutter's own property names in kebab case, read by the type of the value (color, shape, border side, insets, size, constraints, text style, icon theme, number, elevation, enum, duration, mouse cursor, alignment, decoration, input border);cupertino.*setsCupertinoThemeData(primary and contrasting colors, backgrounds, handles,text-theme.*). EveryWidgetStatePropertytakes one value or a map per state (default,hovered,focused,pressed,dragged,selected,scrolled-under,disabled,error; the strongest wins in that order of strength: disabled, error, pressed, dragged, hovered, focused, selected, scrolled-under, default). Colors take an opacity (primary@12%), shapes a map (type,radius,side), text styles a map over a base style. An unknown component or property, or a wrong value, stops the start naming the valid ones, with a "did you mean". The 16 earlier components keep their keys. One fix: whenbuttonand a button kind (filled-button, ...) set the same property, the kind's value now wins (it was the shared one). The component reference ofdocs/configuration.mdis generated from the mapping and a test keeps it in step. ThemeKeyReader(context.themeof the generatedlib/spring_keys.dart): the typed theme keys read the theme shown now throughSpringTheme.of(context). Seespring_core_dart_generator.- The theme files and the property-file lookup use
resources:(resources:themes/*.yml);classpath:still works with a warning (seespring_core_dart).
0.6.1 #
Changes #
- The desktop window from properties (0.6.1):
spring.flutter.desktop.window.title-bar(default,transparent,hidden),title(the window's title; blank is none),initial-size,min-sizeandmax-size(1280x800, logical pixels; min <= initial <= max, else the start stops naming the values;max-sizeis macOScontentMaxSize, WindowsptMaxTrackSizeand GTKGDK_HINT_MAX_SIZE).SpringApplicationWidgetreads them when the environment is ready and makes one call to the new platform code, before the first frame is shown (the frame is held back until the window is set, at most five seconds). A malformed value, or sizes that contradict each other, stops the start; phones and the web ignore the keys.DesktopWindow/DesktopWindowInsetsgive the space the window buttons take,WindowDragAreamoves the window and maximizes it on a double click. The starter becomes a Flutter plugin for macOS (Swift:NSWindow), Windows (C++: DWM,WM_GETMINMAXINFO,WM_NCCALCSIZE) and Linux (GTK): its own code, no third-party package; it needs Flutter 3.47.
0.6.0 #
Changes #
- Where a SQLite database lives: with a SQL database in the properties (
spring.datasource.url, orspring.datasources.<name>.url),SpringApplicationWidgetreads the app's directories frompath_providerbefore the application starts and, once the configuration files are read, setsspring.datasource.sqlite.base-directoryto the directory ofspring.datasource.sqlite.location(support, the default;cache;documents; any other value stops the start) andspring.datasource.sqlite.isolate=true, with the lowest precedence (the app's own properties win), for the primary data source and each named one.supportis Android'sdatabases/directory, iOS's and macOS's Application Support, Windows'%LOCALAPPDATA%\<company>\<product>(not the roaming directory) and Linux's$XDG_DATA_HOME/<app id>. The directory is created when it is missing. Nothing is set on the web or in a widget test (nopath_providerplugin). The starter depends onpath_provider(flutter.dev) and its platform interface, and only sets properties: it does not depend on the data starter. BeanReadsPointcut.annotationTypesandNotifyListenersPointcut.annotationTypeslist the annotations the pointcuts match (@ChangeNotifierComponent,@NotifyListeners); the generator reads them to give a proxy class only to the beans that carry one (smaller generated code; regenerate the.spring.dartfiles).
0.5.0 #
Changes #
SpringApplicationWidgetcloses the application context when a check fails after the start, and a hot reload's restart that fails closes both contexts, so runners and scheduled tasks no longer run behind the failure screen, and each retry no longer leaves another context running.
0.4.3 #
- Flutter security (#15)
- feat(security): spring_boot_starter_flutter_security — app login on e… (#13)
- feat: single sign-on with OAuth 2.0 / OpenID Connect (spring_boot_sta… (#11)
- docs: the READMEs and docs/ rewritten: what it is, why and when you need it, an example, then Spring (#10)
0.4.2 #
- Docs (#9)
0.4.1 #
- feat: guides replace the examples; optional parameters from Dart nullability; coloured logs
0.4.0 #
- feat: spring_security_core, spring_boot_starter_security and a CI quality gate
0.3.2 #
- feat: hot reload on the Dart VM, flutter_notes example, fixes for example resources and workspace builds
0.3.1 #
- The example is a Spring Boot application written by the generator: a
@ChangeNotifierComponentcounter and Spring widgets. spring_auto_configuration.dartre-exports the logging starter's (and through itspring_boot_dart's) auto-configuration, so a test namingspringBootAutoConfiguration(ApplicationContextRunner) needs no other dependency.
0.3.0 #
- Reading is free: a
SpringStatelessWidgetorSpringStatelistens to a@ChangeNotifierComponentor@NotifyListenersbean of its record only when itsbuildread the bean's state (a getter, a field, through the proxy); calling its methods (onPressed: counter.increment) no longer rebuilds the widget. A read outside the widget's build (an item builder, aBuilderbelow it, a callback) keeps it listening; aChangeNotifierbean without either annotation is listened to always, as before. - The
flutter_counterexample uses Spring widgets for every widget that takes beans (CounterPage,AboutPage). - Breaking:
spring.flutter.app.theme-modeis gone (the theme shown isspring.flutter.theme.active), and so areFlutterAppSettings.themeMode,color,theme,darkThemeandcupertinoTheme(the theme comes fromSpringThemes;ThemeDatabeanstheme/darkThemeand aCupertinoThemeDatabean still replace the made ones). - Themes from properties (
spring.flutter.theme.*): a shared part, the standardlight/darkthemes and named custom ones (themes.<name>,extends), the fullColorScheme(seed, variant, contrast, any role), the 15TextThemestyles pluscode, the Material 3 shape scale, elevations, density, splash, page transitions, motion, spacing, 19 components and the app's own tokens; checked at the start (values and the keys themselves: a misspelled key fails too), each made once into aSpringThemeData, a MaterialThemeDataand aCupertinoThemeData.ThemeSelection(active,system-light,system-dark,select) switches at run time;SpringThemes.loadYamladds themes from a server;SpringTheme.of(context)for the app's own widgets;ThemeCustomizer/CupertinoThemeCustomizerbeans;ThemeDatabeanstheme/darkThemestill replace the made ones. Replacesspring.flutter.app.theme-mode(nowspring.flutter.theme.active). - Fonts from the assets: every
.ttf/.otfunderflutter: assets:, in any directory, is loaded before the first frame in the family its file names (spring.flutter.fonts.auto-load,spring.flutter.fonts.exclude); a family the theme names but nothing provides is logged.
0.2.3 #
SpringApplicationWidget(home: ...)builds the app widget from the configuration (SpringApp):spring.flutter.app.type(widgetsby default,material,cupertino),title,debug-banner,theme-mode,locales(by default the languages of the messages files), theThemeDatabeanstheme/darkThemeand aCupertinoThemeDatabean,NavigatorObserverbeans,FlutterAppCustomizerbeans; Flutter's localization delegates come with the starter (flutter_localizations).child:keeps working for an app's ownMaterialApp.- An example (
example/): the counter app in one runnable file, and the way with the generator step by step.
0.2.2 #
- Breaking:
SpringStatelessWidget.buildtakes only theBuildContext; the widget reads its beans asbeans, like aSpringState(inbuildand the callbacks made there). Tests build it with fakes throughbuildWith(context, beans). - README: the generator's check of
@Value('asset:...').
0.2.1 #
- First version:
SpringApplicationWidget(starts the application, splash and failure screens, restarts the context on a hot reload when the generated code changed, switched off withspring.devtools.restart.enabled=false, closes the context when removed),SpringScope,context.bean<T>(), getters generated for@BuildContextAccessbeans,SpringStatelessWidget<(...)>andSpringStatefulWidget<(...)>withSpringState<W, (...)>, beans checked at startup,AppLifecycleStateEventwith the context paused in the background and restarted in the foreground (spring.flutter.lifecycle.pause-in-background), platform profiles (android,ios,web,macos,windows,linux,mobile,desktop), the OS environment off unlessspring.flutter.scan-os-environment,context.messagein the app's locale. @ChangeNotifierComponent(exclude: [...]): a stereotype for a plain class whose proxy mixesChangeNotifierin and notifies after every public method and setter;listenableOf(bean).SpringStatelessWidgetandSpringStaterebuild when aListenablebean of their record notifies.@NotifyListeners(exclude: [...])on aChangeNotifierbean (or some of its methods):notifyListeners()after each call through the AOP proxy, after a returnedFuturecompletes, also after an error.asset:resources:@Value('asset:assets/intro.mp4') Resource videoinjects anAssetResourceof the app's asset bundle (keyfor Flutter's APIs,exists()from the asset manifest), likeclasspath:forlib/resources/.- Brings
spring_boot_starter_logging, switched on (console output in Boot's format,logging.*,LogBuffer). - Exports
spring_core_dart,spring_boot_dartandspring_boot_starter_logging(withoutBannerandSize, which clash with Flutter's; the constraint isSizeConstraint), so an app depends only onspring_boot_starter_flutter.