Skip to content

Releases: flet-dev/flet

v0.86.1

Choose a tag to compare

@github-actions github-actions released this 17 Jul 15:59
e1eb3fd

Improvements

  • flet-mcp's get_api tool now covers top-level callables — the app entry point (run), reactive hooks (use_state, use_ref, use_effect, …), and decorators (component, memo, observable) — which previously returned not found because only classes were indexed. A new functions bucket in the API builder extracts each package's re-exported public callables and renders them with a signature: line. get_api also resolves enum member lookups inline: get_api("Colors", query="RED") now returns the matching members instead of erroring with a redirect to search_enum_members. Both changes remove wasted agent round-trips observed in production usage by @FeodorFitsner.

Bug fixes

  • Fix flet build windows failing on non-UTF-8 system locales (e.g. Simplified-Chinese Windows, code page 936/GBK) with warning C4819 escalated to error C2220 while compiling a plugin's Windows sources. A non-ASCII character in a plugin source (e.g. an em dash in a comment) couldn't be decoded under the system code page, and the build template's /WX (warnings-as-errors) turned it fatal. The Windows build template now compiles all targets with /utf-8, so every plugin — including third-party ones flet doesn't control (e.g. connectivity_plus) — reads its sources as UTF-8 regardless of the build machine's code page. Also bumps serious_python to 4.3.3, which removes the character from its own plugin at the source (#6686) by @FeodorFitsner.
  • Fix the cryptic shutil.ReadError: ... is not a zip file failure in web apps when the app package download fails. The Pyodide worker piped the pyfetch(app_package_url) response straight into unpack_archive() without a status check, so any non-2xx response (transient server 500, expired auth 401, deleted app 404) wrote the JSON/HTML error body to a temp file and crashed while unpacking it. The worker now checks response.ok and raises a readable Failed to download app package: HTTP <status> <url> — <body> error, including the first 200 chars of the error body. Applied to both the Flet web client and the flet build template (#6680) by @FeodorFitsner.
  • Remove unused BasePage return type and import from BaseControl and ControlEvent (#6606) by @Iaw4tch.
  • Fix GestureDetector.allowed_devices crashing with type 'List<dynamic>' is not a subtype of type 'List<String?>?' and preventing the control from rendering. Property values are deserialized from JSON as List<dynamic>, but the value was read via get<List<String?>>(...), whose reified cast fails because a List<dynamic> is not a List<String?>. It's now read as List<dynamic> and each entry is converted to a string before parsing, restoring supportedDevices filtering for Flutter's GestureDetector (#6684) by @TURBODRIVER.

New Contributors

Full Changelog: v0.86.0...v0.86.1

v0.86.0

Choose a tag to compare

@github-actions github-actions released this 14 Jul 21:50
0ccba31

New features

  • Add support for Python multiprocessing in packaged Flet desktop apps built with flet build macos, flet build windows, and flet build linux. multiprocessing APIs such as Process, ProcessPoolExecutor, the spawn/forkserver start methods, and the resource tracker now work in packaged desktop apps. Previously, worker processes re-executed sys.executable, which pointed to the app binary itself, causing each worker to launch another GUI app instance and hang. Flet desktop runners now detect CPython multiprocessing child command lines before Flutter starts and divert them to a headless embedded Python interpreter via dart_bridge 1.5.0+. The Python bootstrap also runs the app module as the real sys.modules["__main__"] with python -m semantics, so top-level worker functions in main.py can be pickled correctly. When using multiprocessing, your app must follow normal Python multiprocessing rules: guard ft.run(...) with if __name__ == "__main__":, define worker functions at module top level, and do not access Flet UI objects from worker processes. See the new Multiprocessing cookbook page. Mobile platforms remain unsupported because iOS and Android do not allow apps to spawn arbitrary child processes (#4283, #6577) by @ndonkoHenri.
  • Multi-version bundled CPython support in flet build and flet publish. Pick the runtime your app ships with via the new --python-version flag (3.12 / 3.13 / 3.14), or let it be derived from [project].requires-python in your pyproject.toml; defaults to the latest supported stable (currently 3.14). The matching CPython-standalone build, Pyodide release (0.27.7 / 0.29.4 / 314.0.1), and Emscripten wheel platform tag are all resolved from flet-dev/python-build's date-keyed manifest. Adding a future pre-release CPython line (e.g. 3.15 beta) is a one-row append with prerelease=True — opt-in only via an explicit --python-version 3.15 or requires-python = "==3.15.*", never the auto-resolved default. Requires serious_python >= 4.0.0, now pinned in the flet build template. See the new Choosing a Python version docs section (#6577) by @FeodorFitsner.
  • Add ft.DataChannel: dedicated byte channels for widgets that move bulk binary data (image frames, audio buffers, ML tensors) between Dart and Python, bypassing the MsgPack control protocol. The Dart side opens a channel via FletBackend.of(context).openDataChannel() and announces it to Python by firing a data_channel_open control event with {channel_name, channel_id}; the Python side declares on_data_channel_open: Optional[ft.EventHandler[ft.DataChannelOpenEvent]] and captures the channel via self.get_data_channel(e.channel_id). Backed by a dedicated PythonBridge per channel in embedded native mode (4–7 GiB/s on M2 Pro) and by the default ProtocolMuxedDataChannelFactory in dev / web modes (raw-byte frames muxed over the active Flet protocol transport with a 1-byte type discriminator). Pyodide gets zero-copy outbound sends via postMessage Transferable ArrayBuffer. First consumer: flet-charts MatplotlibChartCanvas, migrated from _invoke_method PNG dispatch to a 1-byte-opcode data channel by @FeodorFitsner.
  • In-process Python transport (dart_bridge FFI). package:flet gains a third protocol transport alongside the UDS / TCP socket servers: it can run Flet's MsgPack protocol over an in-process dart_bridge byte channel via a FletApp(channelBuilder: …) seam (the flet package stays Python-independent — it doesn't depend on serious_python or know about PythonBridge; the embedder wires the channel). serious_python >= 3.0.0 uses this seam to embed the Python interpreter in-process instead of talking to it over a localhost socket, and the flet build template migrates from sockets to the FFI transport. On Android, where the OS may keep the process alive across a back-button quit and restart only the Dart VM, the transport rebinds to the new VM's dart_bridge ports on a session-restart signal (libdart_bridge >= 1.3.0) — the Python process and its in-memory state are preserved and the Flet session is rebuilt from REGISTER_CLIENT by @FeodorFitsner.
  • Add flet clean command that deletes the build directory of a Flet app — the Flutter bootstrap project, cached artifacts, and generated output — in a single step (#6233) by @ndonkoHenri.
  • Add compression_quality to FilePicker.pick_files() for selecting the image compression quality used by supported platforms (#6573) by @ndonkoHenri.
  • Add ConsentManager to flet-ads for gathering user consent (e.g. GDPR/EEA) via Google's User Messaging Platform (UMP) before requesting ads (#6569, #6615) by @ndonkoHenri.
  • Add ft.RawImage: a high-bandwidth pixel-frame display control for Pillow output, NumPy arrays, camera frames and procedural graphics. Frames stream over a dedicated ft.DataChannel instead of the control protocol: raw premultiplied RGBA straight to a GPU texture on local transports (desktop, flet run, Pyodide), automatic PNG fallback on remote flet-web sessions. The awaitable render(pil_or_numpy) / render_rgba(w, h, bytes) / render_encoded(png_jpeg_webp_bytes) methods resolve when the client has displayed the frame, so a plain while True: await ri.render(...) loop self-paces to display speed. Premultiplied-alpha conversion runs in Pillow's C loops with an opaque fast-path; Pillow and NumPy remain optional. The last frame is retained and replayed on remount, mirroring Image.src. Ships with five gallery examples (photo viewer, plasma, Pillow paint, Mandelbrot explorer, Game of Life) and a docs page with RawImage vs Image guidance (#6674) by @FeodorFitsner.

Improvements

  • Swift Package Manager for iOS/macOS builds (on by default). flet build / flet debug now integrate the embedded Python runtime via SPM instead of CocoaPods (CocoaPods goes read-only in December 2026). Flet auto-falls back to CocoaPods when the app depends on a package that isn't SPM-ready — currently flet-video (media_kit) — since Flutter then builds the whole app with CocoaPods. Force CocoaPods for other non-SPM packages with --no-swift-package-manager (or swift_package_manager = false under [tool.flet]). Flet does not change Flutter's global SPM configuration; the setting only selects how serious_python stages the runtime to match. When SPM is used (it has no pod install hook), flet build sets SERIOUS_PYTHON_DARWIN_SPM so serious_python's package step stages the runtime (Python/dart_bridge xcframeworks, the iOS native extensions, and the stdlib/site-packages/app resources) into the plugin's Package.swift layout on the host before flutter build, and exports the SP_NATIVE_SET cache-bust key into the build. Requires the SPM-capable serious_python release.
  • Smaller Android apps with no native-packaging config. flet build apk/aab consume serious_python's new Android packaging: Python extension modules load memory-mapped directly from the APK (no extraction to disk), and pure Python ships in stored asset zips read via zipimport, so the standard library is no longer duplicated per ABI. Apps no longer need useLegacyPackaging / keepDebugSymbols — the flet build Android template drops them; just use minSdk 23+. New --android-extract-packages flag and [tool.flet.android].extract_packages ship "path-hungry" packages — those that read bundled data via __file__ / pkg_resources instead of importlib.resources — extracted to disk instead of inside the zip (most packages, including certifi, are zip-safe and need no entry). Requires serious_python with the native-mmap packaging (dart_bridge 1.4.0).
  • Pyodide is no longer pre-baked into the flet build template. Each flet build web / flet publish run downloads the matching pyodide-core-<version>.tar.bz2 (plus the runtime micropip and packaging wheels) into a per-version cache at ~/.flet/pyodide/<version>/ and copies the files into the build output. Subsequent builds reuse the cache; the older 0.27.5 bundle previously shipped in the cookiecutter template is gone (#6577) by @FeodorFitsner.
  • The supported Python / Pyodide / dart_bridge versions are loaded on demand from flet-dev/python-build's date-keyed manifest.json (fetched once and cached under ~/.flet/cache), the single source of truth shared with serious_python — replacing flet's hand-mirrored version table. flet build forwards only SERIOUS_PYTHON_VERSION and lets serious_python derive the full version / build date / dart_bridge version from its own committed snapshot. The module exposes get_supported_python_versions() / get_default_python_version() (the previous SUPPORTED_PYTHON_VERSIONS / DEFAULT_PYTHON_VERSION constants are removed) (#6577) by @FeodorFitsner.
  • flet --version shows just the Flet and Flutter versions; the static Pyodide: … line and the global flet.version.pyodide_version export are removed (the supported Python / Pyodide set now lives in python-build's manifest, not the CLI output) (#6577) by @FeodorFitsner.
  • flet --version --json emits a machine-readable document — Flet/Flutter versions and the Linux build dependencies — for CI to read via jq instead of importing Flet internals with `pyt...
Read more

v0.86.0.dev2

v0.86.0.dev2 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 09 Jul 23:45
4e70321

What's Changed

New Contributors

Full Changelog: v0.86.0.dev1...v0.86.0.dev2

v0.86.0.dev1

v0.86.0.dev1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Jul 19:47
ff08962

What's Changed

  • fix(ci): version flet-mcp like the other packages on publish by @FeodorFitsner in #6633
  • fix(build): preserve flutter-packages on incremental builds (--skip-site-packages) by @FeodorFitsner in #6634

Full Changelog: v0.86.0.dev0...v0.86.0.dev1

v0.86.0.dev0

v0.86.0.dev0 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Jul 18:28
967da28

What's Changed

  • Multi-version Python support (3.12 / 3.13 / 3.14) by @FeodorFitsner in #6577
  • fix(flet-secure-storage): bump flutter_secure_storage 10.0.0 -> 10.3.1 to fix macOS data-protection keychain (-34018) on unsigned/dev apps by @EH-MLS in #6591
  • feat(cli): flet clean command + deprecate --clear-cache flag of flet build by @ndonkoHenri in #6590
  • fix(typing): explicit handler signatures in PubSubClient by @Iaw4tch in #6564
  • chore: More docs + code improvements by @ndonkoHenri in #6589
  • fix(android): pickFirsts libc++_shared.so to unblock multi-plugin Flet apps by @ndonkoHenri in #6571
  • Update CONTRIBUTING.md hello.py example to use modern ft.run() and ft.Page/ft.Text instead of deprecated `flet.app by @Federicorao in #6582
  • feat(FilePicker): add compression_quality and cancel_upload_on_window_blur to pick_files() by @ndonkoHenri in #6573
  • feat: add flet-spinkit extension package wrapping flutter_spinkit ^5.2.2 by @InesaFitsner in #6596
  • Integrate dart-bridge into flet-0.86 (in-process FFI transport, multi-version Python, native-mmap, DataChannel) by @FeodorFitsner in #6601
  • Lift app packaging into serious_python + SPM-by-default darwin builds by @FeodorFitsner in #6608
  • Support Android TV in device info retrieval by @bl1nch in #6604
  • 在android_sdk.py中令cmdline-tools-url检测到windows使用arm64架构时返回与x64相同的下载链接 by @xiaocai2011 in #6617
  • Custom boot screen by @FeodorFitsner in #6616
  • feat(flet-ads): ConsentManager for AdMob UMP consent by @ndonkoHenri in #6615
  • Rich progress bars for client and pyodide downloads by @FeodorFitsner in #6618
  • feat: flet test on-device integration testing + CI matrix by @FeodorFitsner in #6623
  • Pin python-build 20260630 (armeabi-v7a for 3.13/3.14); serious_python 4.2.0 by @FeodorFitsner in #6628
  • Add flet-mcp: MCP server for LLM agents by @FeodorFitsner in #6624
  • ci: zizmor security checks by @ndonkoHenri in #6602
  • Bump serious_python 4.2.1 / python-build 20260701 by @FeodorFitsner in #6630

New Contributors

Full Changelog: v0.85.3...v0.86.0.dev0

v0.85.3

Choose a tag to compare

@github-actions github-actions released this 08 Jun 01:56
bb993fa

What's Changed

Improvements

  • Allow [tool.flet.android.permission] values to be TOML inline tables in addition to booleans — each key = "value" entry adds an android:<key>="<value>" attribute to the generated <uses-permission> element, unlocking modifiers like android:maxSdkVersion and android:usesPermissionFlags that real-world Android permissions (e.g. Bluetooth LE) require. The boolean form and the --android-permissions CLI flag are unchanged; a non-empty inline table is always emitted, an empty table ({}) is treated as false, and invalid value types fail the build with a clear error (#6550, #6551) by @FeodorFitsner.
  • Add [tool.flet.android.provider] for declaring custom <provider> entries in the generated AndroidManifest.xml. Each table key is the provider's android:name; entries become android:<key>="<value>" attributes on the generated element. A reserved meta_data sub-table emits nested <meta-data> children (scalar values render as android:value="…"; inline-table values render as android:<k>="<v>" so android:resource="@xml/…" works). false / {} skip the entry; true and invalid value types fail the build with a clear error. The built-in androidx.core.content.FileProvider block is unchanged (#6556, #6559) by @FeodorFitsner.
  • Upgrade the bundled Pyodide runtime in the flet build web template from 0.27.5 to 0.27.7 (includes micropip 0.9.0) (#6549) by @FeodorFitsner.
  • Drop generated web/canvaskit/ build artifacts (canvaskit.js/.wasm/.symbols and the chromium/ and skwasm/skwasm_st variants) from the flet build web template — these are produced by the Flutter web build and should not have been committed into the cookiecutter template (#6549) by @FeodorFitsner.
  • Cache the downloaded flet-build-template.zip across builds. The build template is bound to an exact Flet version and is immutable, so on every flet build / flet debug after the first, the CLI now uses a previously-downloaded zip from $FLET_CACHE_DIR/build-template/v<flet-version>/ (defaulting to ~/.flet/cache/build-template/v<flet-version>/) instead of re-fetching it via cookiecutter. The CLI also exports FLET_CACHE_DIR into the child Gradle process, so serious_python_android >= 1.0.1 lands its Python dist tarballs (python-android-dart-<py>-<abi>.tar.gz) in the same cache root by default — fixing the multi-minute "Creating app shell" / downloadDistArchive_* delay on every Android debug build. Custom --template URLs and the local-dev template path are unchanged (#6555, #6558) by @FeodorFitsner.
  • Bump the bundled build template's serious_python dependency from 1.0.0 to 1.0.1 so Android builds pick up the new persistent Python-tarball cache + conditional-GET revalidation introduced in serious_python 1.0.1 (#6558) by @FeodorFitsner.

Bug fixes

  • Fix flet.Router's default on_view_pop navigating to the wrong URL when an outlet=True layout sits between two views in manage_views=True mode. Popping such a view now targets the previous view entry's resolved URL — skipping outlet layouts and componentless grouping routes — instead of chain[-2], which could equal the current view's URL and strand the page route, making the next navigation to it a no-op (#6533) by @FeodorFitsner.
  • Fix flet-audio.Audio.play()/seek() timing out when replaying after playback had completed: under the default ReleaseMode.RELEASE the source is freed on completion and is now re-prepared on replay (#6536, #6538) by @ndonkoHenri.
  • Fix ft.run(view=ft.AppView.FLET_APP_HIDDEN) briefly flashing the native window in the top-left corner during Windows desktop startup. The Windows runner now respects FLET_HIDE_WINDOW_ON_START and skips the first-frame Show() call so the window stays hidden until page.window.visible = True, matching the Linux desktop behavior; the same fix is applied to the flet build windows template runner so generated apps behave consistently. On Linux, pre-show window placement actions (page.window.center(), page.window.alignment) are now deferred until the window first becomes visible to avoid an analogous flash, and the window's focused state is preserved when a prevent_close handler cancels a close attempt (#5897, #5914, #6527) by @ihmily.

Full Changelog: v0.85.2...v0.85.3

v0.85.3.dev1

v0.85.3.dev1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 06 Jun 22:03
95d105d

What's Changed

  • feat(build): cache flet-build-template.zip; share FLET_CACHE_DIR with Gradle by @FeodorFitsner in #6558
  • feat(build): support custom entries in AndroidManifest via pyproject.toml by @FeodorFitsner in #6559

Full Changelog: v0.85.3.dev0...v0.85.3.dev1

v0.85.3.dev0

v0.85.3.dev0 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 05 Jun 21:38
f885891

What's Changed

  • docs(studio): add Flet Studio landing page and docs section by @FeodorFitsner in #6523
  • docs(studio): give Studio its own footer column by @FeodorFitsner in #6524
  • Tests and screenshots for Featured apps; fix for palette editor color picker by @InesaFitsner in #6521
  • fix: add CMake definition to silence MSVC coroutine deprecation error by @ihmily in #6525
  • docs(studio): Flet Studio launch post + updated gallery links by @FeodorFitsner in #6534
  • Flet Studio update and skip builds for website/tools-only changes by @FeodorFitsner in #6537
  • fix(router): pop to previous view, not the outlet layout URL by @FeodorFitsner in #6533
  • Renamed titles of basic examples by @InesaFitsner in #6535
  • docs: inject example headings dynamically from pyproject.toml metadata by @InesaFitsner in #6544
  • Fix build web template: drop canvaskit artifacts, bump Pyodide to 0.27.7 by @FeodorFitsner in #6549
  • refactor: rename and normalize example folder and package names by @InesaFitsner in #6545
  • fix: honor AppView.FLET_APP_HIDDEN in Windows and Linux desktop runners by @ihmily in #6527
  • feat(build): allow attributes on Android entries by @FeodorFitsner in #6551
  • fix(flet-audio): replaying Audio after completion under ReleaseMode.RELEASE raises TimeoutException by @ndonkoHenri in #6538

Full Changelog: v0.85.2...v0.85.3.dev0

v0.85.2

Choose a tag to compare

@github-actions github-actions released this 25 May 17:32
bd5e16f

What's Changed

  • fix: reject session reuse when existing connection is still active by @ihmily in #6513
  • feat(router): add modal/recursive Route flags + chain-based pop by @FeodorFitsner in #6516
  • docs: add 0.85.2 changelog entry for #6513 session reuse fix by @FeodorFitsner in #6518
  • docs: add release migration-guide page for breaking changes and deprecations by @ndonkoHenri in #6517

New Contributors

Full Changelog: v0.85.1...v0.85.2

v0.85.1

Choose a tag to compare

@github-actions github-actions released this 13 May 16:35
88ac763

Bug fixes

  • Fix TooltipTheme.decoration so it applies to controls using ft.Tooltip(...) when the tooltip does not explicitly set decoration or bgcolor (#6432, #6482) by @ndonkoHenri.
  • Fix flet-geolocator.Geolocator reliability on web and desktop: get_last_known_position() no longer crashes with TypeError: argument after ** must be a mapping, not NoneType and now returns Optional[GeolocatorPosition]; get_current_position() no longer hangs forever on web (Dart-side workaround for the upstream geolocator_web 4.1.3 inMicroseconds/inMilliseconds timeout typo) and uses sensible web defaults (time_limit: 30s, maximum_age: 5m); the previously-dropped configuration argument now actually reaches getCurrentPosition on the Dart side; the position stream is gated behind a registered on_position_change/on_error handler (with cancel-on-update to prevent leaks); and platform exceptions (LocationServiceDisabledException, PermissionDeniedException, PermissionDefinitionsNotFoundException, PermissionRequestInProgressException, PositionUpdateException, TimeoutException) are now translated into actionable error messages and surfaced to Python as RuntimeError without the default Exception: prefix (#6487) by @FeodorFitsner.
  • Fix PEP 508 markers on flet's oauthlib/httpx deps not actually excluding those packages under Pyodide: the flet build web package platform has been renamed from Pyodide to Emscripten to match platform.system() inside the Pyodide runtime, and the markers now use platform_system != 'Emscripten', so the exclusion works both via flet build and a direct micropip.install("flet") in a Pyodide REPL. Requires serious_python >= 1.0.0, which is now pinned in the flet build template (#6492) by @FeodorFitsner.