Bug fixes
- Fix code edits not taking effect under
flet debug android: after re-running the command, the app kept executing the previously-unpacked, stale code instead of your changes.flet debugrebuilds and reinstalls the same-version APK on each iteration (flutter rundoes an update install that preserves app data), andserious_python's on-device extraction cache — keyed only onversionName+versionCode— never saw the version change, so it skipped re-unpacking the newapp.zip. Bumpsserious_pythonto 4.3.4, which folds the APK'slastUpdateTimeinto that cache key so every (re)install re-extracts the current code while ordinary relaunches still hit the cache.flet build apkwas never affected (#6682) by @FeodorFitsner. - Fix an embedded
FletApp(an app rendered inside another Flet app — e.g. a preview or gallery host that runs example apps in-process) not refreshing its UI in response to events. Auto-update mode was tracked ascomponents_modeon a single process-globalcontextsingleton, so a host app that rendered viapage.render/page.render_viewsturned components mode on process-wide andcontext.auto_update_enabled()then returnedFalsefor the embedded app too — any handler that mutated a control without calling.update()(the common imperative style, including allpage.servicessensor readings) silently never re-rendered. Event dispatch also ran in a fresh task whose page context var could carry a different session's page, so context-derived state resolved against the wrong session.components_modeis now stored per-Session, andSession.dispatch_eventbinds the page context to its own session before invoking handlers, so multiple Flet apps sharing one process keep independent update behavior by @FeodorFitsner. - Modernize examples for 0.86: replace the removed
TextField.error_textwitherror(chat tutorial,mind_queue,palette_editor), and declare the device permissions each sensor example needs to run on-device —NSMotionUsageDescriptionon iOS for the motion/barometer sensors andandroid.permission.VIBRATEfor HapticFeedback by @FeodorFitsner. - Fix opening a
flet run --ios/--androidapp URL in a desktop browser: the page loaded but stayed on the boot screen, endlessly retrying a WebSocket connection tows://<host>:<port>/ws. Mobile-mode apps are mounted under a non-root path (e.g./counter/main.py), so the real WebSocket route lives at/counter/main.py/ws- but since 1.0 Alpha the FastAPI wrapper always passed the bare defaultwsendpoint name intoFletStaticFiles, bypassing its mount-path-aware fallback, andindex.htmlgot patched withflet.webSocketEndpoint="ws", which the web client resolves against the server root. The native iOS/Android client derives the path from the page URL and was unaffected. A relative WebSocket endpoint is now resolved against the app mount path when patchingindex.html, fixing browser access to any Flet web app mounted under a non-root path (--ios/--android,flet run --name, or aflet_web.fastapiapp mounted at a sub-path) by @FeodorFitsner. - Fix web
RawImageandMatplotlibChartanimations flooding the console with uncatchable engine exceptions (and breaking the animation) after the browser tab was backgrounded for a while and then refocused. On Flet web the frame producer runs in a Pyodide worker (or on a remote server over a WebSocket) that the browser never throttles, while the client's Flutter frame pipeline is suspended whenever the tab is hidden - sosetStateschedules frames that never paint and the post-frame callbacks that dispose replacedui.Images never fire. Decoded images and pending disposals then pile up unbounded in the Dart heap and flush into the engine all at once on resume, one exception per queued frame. This is a client-side accumulation independent of transport, so it also affected native windows minimized with an animation running. Fixed in two layers: (1) a sharedFrameStreamVisibilityclient-side mixin - used by bothRawImageandflet-charts'MatplotlibChartCanvas- stops decoding/uploading and frees replaced images immediately while hidden (keeping only cheap offscreen state up to date, so incremental matplotlib diffs stay correct), then presents just the latest frame on resume; (2) a newpage.wait_until_visible()gate (driven byon_app_lifecycle_state_change, alongside apage.app_visibleproperty) that the streaming controls await internally, so producer loops park while hidden instead of rendering frames a suspended client can only discard (#6691) by @FeodorFitsner. - Fix
flet build/flet publishflooding non-interactive logs (CI, cloud build, any piped stdout) with thousands of progress-spinner frames, and fix the--no-rich-outputflag not actually producing plain output. The CLI's richConsolewas created withforce_terminal=Truewhenever theFLET_CLI_NO_RICH_OUTPUTenv var was unset, which forces theLivestatus spinner to repaint even when stdout isn't a TTY — so in a pipe every animation frame lands on its own line (e.g. hundreds of( ● ) Initializing web build...lines). And the--no-rich-outputCLI flag never reached that console at all: it's parsed per-command, after the module-levelconsoleis already built, so it only suppressed emojis while color and the spinner kept going. Now the console auto-detects the terminal (force_terminal=None) — interactive terminals keep the animated spinner while piped output stays quiet — and bothFLET_CLI_NO_RICH_OUTPUTand--no-rich-output(detected fromsys.argvat import) force fully plain output by @FeodorFitsner.
Improvements
- Flutter updated to 3.44.7.
- Fix
flet_video.Videoresetting itsvolume(andpitch,playback_rate,shuffle_playlist,playlist_mode,subtitle_track) to the player's defaults after togglingvisibleoff then on — e.g.volumejumped back to100. Hiding aVideodisposes its nativemedia_kitplayer and showing it recreates a fresh one at default settings; the "last-applied" tracking now lives with the player (not the persistent control model) and is reset on recreation, sobuild()re-applies every setting to the new player (#6683, #6694) by @ndonkoHenri. - Fix
SearchBar.on_tap_outside_barnot firing when the user tapped outside the open search view. That case now has a dedicatedSearchBar.on_tap_outside_viewevent (fired when tapping outside the open view, e.g. to dismiss it), andon_tap_outside_baris documented to match what it actually does: fire while the bar is focused and the view is closed, likeTextField.on_tap_outside(#6593, #6697) by @ndonkoHenri. - Add a
--android-legacy-packagingflag (and[tool.flet.android].legacy_packagingsetting) toflet build apk/aabfor opting into legacy Android native-library packaging. By default (modern packaging), native.sofiles are stored uncompressed and page-aligned in the APK and memory-mapped directly at runtime, which typically gives a smaller install and Play Store download but a larger raw.apkfile. Enabling this option setsuseLegacyPackaging = trueso the.soare compressed inside the APK and extracted to disk on install: the raw.apkfile is smaller (handy when side-loading), at the cost of a larger on-device install and slower native-library loading. The extraction directory is exposed to Python asANDROID_NATIVE_LIBRARY_DIR, which can help custom native-library consumers that require a real filesystem path. See Native library packaging by @FeodorFitsner.
Full Changelog: v0.86.1...v0.86.2