refactor!: Remove all deprecated APIs for a deprecation-free 1.0 - #6693
Merged
Merged
Conversation
…rols APIs Removes APIs deprecated in 0.85.0 as part of the pre-v1 deprecation cleanup: - DragTargetEvent.x/.y/.offset -> use local_position / global_position - Video.show_controls -> set controls=None to hide controls - Video.playlist_add()/playlist_remove() -> mutate Video.playlist directly Also simplifies the flet_video Dart control (the show_controls gate is now dead code) and updates the root + flet-video changelogs and the 0.85.0 migration guides.
… flag Continues the pre-1.0 deprecation cleanup: - Remove FletApp.show_app_startup_screen and FletApp.app_startup_screen_message (deprecated in 0.86.0) -> use boot_screen_options - Remove the --clear-cache flag of flet build / flet debug (deprecated in 0.86.0) -> use the flet clean command; the flag's build/flutter deletion behavior is removed with it - Finalize the cleanup changelog version placeholder from 'Unreleased' to 1.0.0 (root + flet-video changelogs and the 0.85.0/0.86.0 migration-guide timelines)
Continues the pre-1.0 deprecation cleanup: - Remove Page.go() (deprecated in 0.80.0) -> use Page.push_route() - Remove the Page.url_launcher, Page.browser_context_menu, Page.shared_preferences, Page.clipboard, and Page.storage_paths service accessors (deprecated in 0.80.0) -> instantiate the service classes directly: UrlLauncher(), BrowserContextMenu(), SharedPreferences(), Clipboard(), StoragePaths() - Migrate two examples off the removed accessors
… Colors aliases Completes the scheduled (1.0) deprecation removals: - Remove the ConstrainedControl base class (deprecated 0.80.0) -> inherit from LayoutControl - Remove ElevatedButton (deprecated 0.80.0) -> use Button - Remove DropdownM2 and the dropdownm2 module, incl. its Dart widget and control registration (deprecated 0.84.0) -> use Dropdown - Remove the 14 deprecated non-underscored Colors aliases (BLACK12..WHITE70) -> use the underscored names; revert Colors to a plain Enum - Clean up flet package exports, delete the DropdownM2 docs page and sidebar entry, and migrate one example type annotation to ft.Button
…ee 1.0 Sweeps the deprecations that had no scheduled removal version: - Remove app() and app_async() (deprecated 0.80.0) -> use run()/run_async() - Remove the target= alias parameter of run()/run_async() -> pass main - Remove Page.launch_url()/can_launch_url()/close_in_app_web_view() (deprecated 0.90.0) -> use UrlLauncher() - Remove the legacy [tool.flet.app.boot_screen]/[tool.flet.app.startup_screen] build-config fallback -> use [tool.flet.boot_screen] - Remove the Dart empty-string widget-state key back-compat mapping -> 'default' - Migrate 8 examples + the authentication cookbook doc off page.launch_url() to ft.UrlLauncher().launch_url() (and fix a stale web_window_name kwarg)
Reverses the DropdownM2 removal from 76e33fa and drops its deprecation: - Restore the Python control, the Dart widget + its control registration, and the docs page - Strip the @deprecated_class decorator (and its import) so DropdownM2 is no longer deprecated - Re-add the flet package exports (class + module) and the sidebar entry DropdownM2 remains a supported control; its 0.84.0 deprecation in favor of Dropdown is reverted.
…waited) SimpleAttribution.on_click used `lambda e: ft.UrlLauncher().launch_url(...)`, but launch_url is async — Flet's sync-handler dispatch calls the lambda and discards the returned coroutine, so it was never awaited and the click did nothing. Replace with a proper `async def` handler that Flet awaits. This was a pre-existing bug (the prior `page.launch_url()` form was also async).
Deploying flet-website-v2 with
|
| Latest commit: |
6922e92
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://eae7f464.flet-website-v2.pages.dev |
| Branch Preview URL: | https://fix-remove-deprecations.flet-website-v2.pages.dev |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR prepares Flet for a deprecation-free 1.0 by removing previously deprecated public APIs across Python, Dart, CLI tooling, docs, and examples, and updating references to their supported replacements.
Changes:
- Removed deprecated Python APIs (navigation helpers, service accessors, legacy controls, color aliases) and updated exports accordingly.
- Removed deprecated CLI/build flags and legacy build config fallbacks, aligning tooling with current commands/config keys.
- Updated docs, changelogs, Dart back-compat behavior, and multiple examples to use the new APIs (e.g.,
UrlLauncher(),Button,"default"widget-state key).
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| website/docs/updates/breaking-changes/v0-86-0/deprecated-clear-cache-flag.md | Updates timeline/references for --clear-cache removal in 1.0.0. |
| website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md | Updates timeline/references for deprecated Video APIs removal in 1.0.0. |
| website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md | Updates timeline/references for drag event coordinate fields removal in 1.0.0. |
| website/docs/cookbook/authentication.md | Migrates auth flow URL opening to ft.UrlLauncher() APIs. |
| sdk/python/packages/flet/src/flet/controls/page.py | Removes deprecated Page.go() and URL-launch/service accessor helpers. |
| sdk/python/packages/flet/src/flet/controls/material/elevated_button.py | Removes deprecated ElevatedButton wrapper (file deleted). |
| sdk/python/packages/flet/src/flet/controls/material/dropdownm2.py | Undeprecates DropdownM2 by removing its deprecation wrapper. |
| sdk/python/packages/flet/src/flet/controls/layout_control.py | Removes deprecated ConstrainedControl alias in favor of LayoutControl. |
| sdk/python/packages/flet/src/flet/controls/core/flet_app.py | Removes deprecated boot screen convenience properties from FletApp. |
| sdk/python/packages/flet/src/flet/controls/core/drag_target.py | Removes deprecated DragTargetEvent coordinate aliases. |
| sdk/python/packages/flet/src/flet/controls/colors.py | Removes deprecated color aliases and reverts Colors to a plain Enum. |
| sdk/python/packages/flet/src/flet/app.py | Removes deprecated app()/app_async() and target= aliasing in run()/run_async(). |
| sdk/python/packages/flet/src/flet/init.py | Stops exporting removed/legacy symbols (e.g., app, ConstrainedControl, ElevatedButton). |
| sdk/python/packages/flet-video/src/flutter/flet_video/lib/src/video.dart | Drops show_controls handling on the Dart side. |
| sdk/python/packages/flet-video/src/flet_video/video.py | Removes deprecated Video.show_controls and playlist helper methods. |
| sdk/python/packages/flet-video/CHANGELOG.md | Documents removed video APIs in the flet-video 1.0.0 changelog. |
| sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py | Removes deprecated --clear-cache flag and legacy boot/startup screen config fallback. |
| sdk/python/examples/extensions/map/multi_layers/main.py | Fixes attribution click handling by awaiting URL launch via UrlLauncher(). |
| sdk/python/examples/extensions/map/interaction_flags/main.py | Fixes attribution click handling by awaiting URL launch via UrlLauncher(). |
| sdk/python/examples/extensions/map/idle_camera/main.py | Fixes attribution click handling by awaiting URL launch via UrlLauncher(). |
| sdk/python/examples/extensions/map/camera_controls/main.py | Fixes attribution click handling by awaiting URL launch via UrlLauncher(). |
| sdk/python/examples/extensions/charts/line_chart/line_chart_with_custom_axes/main.py | Updates handler typing/usages to Button after ElevatedButton removal. |
| sdk/python/examples/extensions/audio_recorder/audio_recorder/main.py | Migrates page.launch_url() usage to UrlLauncher(). |
| sdk/python/examples/controls/material/context_menu/triggers/main.py | Migrates page.browser_context_menu usage to BrowserContextMenu(). |
| sdk/python/examples/controls/core/markdown/markdown/main.py | Migrates page.launch_url() usage to UrlLauncher(). |
| sdk/python/examples/controls/core/markdown/listviews/main.py | Migrates page.launch_url() usage to UrlLauncher(). |
| sdk/python/examples/controls/core/markdown/code_syntax_highlight/main.py | Migrates page.launch_url() usage to UrlLauncher(). |
| sdk/python/examples/apps/declarative/trolli/components/dialogs.py | Migrates page.shared_preferences accessor usage to SharedPreferences(). |
| packages/flet/lib/src/utils/widget_state.dart | Removes Dart-side empty-string widget-state key back-compat mapping. |
| CHANGELOG.md | Adds 1.0.0 breaking changes entry documenting all removals/changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…_context_menu The ContextMenu docstring linked `:attr:`flet.Page.browser_context_menu``, which this PR removes — leaving an unresolved reST xref that failed the docs build's cross-reference check (`docs/controls/contextmenu`). Point it at the `BrowserContextMenu` service directly. Verified locally with the full `yarn build` + `check_docs` sequence — all checks pass.
The removals were documented only in the changelog, so a user upgrading to 1.0 found nothing under Breaking changes and deprecations. The three removals that do have guides sit under v0.85.0/v0.86.0 as deprecation notices, where someone jumping from an older release would never look. Add one aggregate guide listing every removal against its replacement, plus the 1.0.0 sections in the breaking-changes index and the release notes that the compatibility policy asks for. A guide per removal would be noise: most are one-line renames, and the deprecation-era guides already cover the three that need real migration steps.
The changelog said `Page.launch_url()`, `Page.can_launch_url()` and `Page.close_in_app_web_view()` were deprecated in `0.90.0` — a release that never existed, since the line went from 0.86 straight to 1.0. The value came from the `@deprecated` decorator, which carried a forward-looking removal target in its `version` slot. They were deprecated in `0.80.0`: the decorator arrived with the new services in #5846, first released in v0.80.0, alongside the `Page` service accessors this entry sits next to.
FeodorFitsner
approved these changes
Aug 27, 2026
ndonkoHenri
added a commit
that referenced
this pull request
Aug 29, 2026
`/blog/flet-1-0` has no post behind it -- the blog declares `introducing-flet-1-0-alpha` and `flet-1-0-beta`, and the stable announcement is not written yet. Docusaurus fails the build on broken links, so this took down the docs workflow and the Cloudflare deploy with it. Every other entry links to a post that exists, so the line loses just the announcement and keeps its changelog and breaking-changes links. Put it back when the post lands. Arrived in #6693 and is unrelated to the Linux icon work; it rides on this branch only because that is where it was hit. Verified with a full `crocodocs:generate && docusaurus build`: green, and no other reference to that slug anywhere under website/.
ndonkoHenri
added a commit
that referenced
this pull request
Aug 29, 2026
`/blog/flet-1-0` has no post behind it -- the blog declares `introducing-flet-1-0-alpha` and `flet-1-0-beta`, and the stable announcement is not written yet. Docusaurus fails the build on broken links, so this took down the docs workflow and the Cloudflare deploy with it. Every other entry links to a post that exists, so the line loses just the announcement and keeps its changelog and breaking-changes links. Put it back when the post lands. Arrived in #6693 and is unrelated to the Linux icon work; it rides on this branch only because that is where it was hit. Verified with a full `crocodocs:generate && docusaurus build`: green, and no other reference to that slug anywhere under website/.
FeodorFitsner
added a commit
that referenced
this pull request
Sep 2, 2026
* fix(flet pack): Windows taskbar identity of packaged apps (#6767) - Ship rthooks.dat in the flet-cli wheel via package-data; without it PyInstaller silently never ran the Flet runtime hook, so the AUMID fix from #6403 was dead on arrival in wheel installs. - Stamp System.AppUserModel ID/RelaunchCommand/DisplayName/Icon window properties on the desktop client window (new flet_desktop.win_taskbar, pure ctypes): a process-level AppUserModelID only fixes grouping, while the taskbar name, icon and pin target resolve through the window relaunch properties. - Hashed-AUMID fallback for exe paths over 128 chars or with spaces. - Key ~/.flet/client cache dirs by bundled-archive content fingerprint (flet pack writes <archive>.sha256 at build time) so pack-patched and vanilla clients of the same version stop shadowing each other. - Document FLET_APP_RELAUNCH_* env vars. * simplify: always use raw exe path as AppUserModelID The hashed-AUMID fallback for >128-char / spaced paths guarded against a failure that was never actually isolated: in the AUMID-only test round, every unseeded path failed identically (window relaunch props did not exist yet), so the long path added no signal. With the window properties stamped, a raw >128-char path with spaces was verified working on Windows 11 - the window property store accepts it and the Relaunch* properties drive name/pin resolution. Keep the single, tested code path. * harden taskbar stamping and client cache per adversarial review - Match the client window by its FLUTTER_RUNNER_WIN32_WINDOW class instead of visibility: hidden-start apps (AppView.FLET_APP_HIDDEN) were never stamped because the worker waited for a visible window and gave up after 30 s. Stamping works on hidden windows, so they now get their identity immediately. - Hold a SYNCHRONIZE process handle while polling: stops when the client exits and prevents PID recycling from ever stamping a foreign window; the fixed 30 s deadline is gone. - Fingerprint sidecar now records '<hash> <size>' and the size must match the archive, so a stale sidecar next to a replaced archive re-hashes instead of silently mapping to the old client's cache. - Build client archives deterministically (fixed zip/tar/gzip timestamps, sorted entries) so identical content keeps the same fingerprint across rebuilds; GC superseded fingerprint dirs after 30 days of disuse with a rename-before-delete guard; survive concurrent first-run extraction races instead of crashing the loser. * style: alphabetical env var docs, Google-style docstrings, typing Move the FLET_APP_RELAUNCH_* doc sections to their alphabetical position, add type hints and Google-style Args/Returns sections to the new functions, and use single backticks in docstrings. [skip ci] * docs: clarify FLET_APP_USER_MODEL_ID / FLET_APP_RELAUNCH_* are Windows desktop only [skip ci] * docs: add docstrings to win_taskbar ctypes structures [skip ci] * docs(changelog): reference PR #6793 in taskbar identity entries [skip ci] * docs(changelog): tighten taskbar identity entries Drop verification narrative and investigation history; keep symptom, cause, and behavior. * address review: stream zip entries, validate fingerprint sidecar - compress_flet_client_dir() streamed each file through zf.open(zi, 'w') instead of reading it whole into memory with writestr(); the switch to a custom ZipInfo (for deterministic timestamps) had lost the streaming the previous zf.write() call had. - __get_archive_fingerprint() now requires the sidecar hash to be 64 lowercase hex digits before trusting it, so a corrupted or hand-edited sidecar falls back to hashing instead of producing a cache directory name that could contain path separators - and that the fingerprint GC, which only recognizes hex suffixes, would never clean up. - Note ctypes.OleDLL's automatic HRESULT checking in win_taskbar, which is why COM failures surface as OSError. * docs: drop the dangling 1.0.0 announcement link `/blog/flet-1-0` has no post behind it -- the blog declares `introducing-flet-1-0-alpha` and `flet-1-0-beta`, and the stable announcement is not written yet. Docusaurus fails the build on broken links, so this took down the docs workflow and the Cloudflare deploy with it. Every other entry links to a post that exists, so the line loses just the announcement and keeps its changelog and breaking-changes links. Put it back when the post lands. Arrived in #6693 and is unrelated to the Linux icon work; it rides on this branch only because that is where it was hit. Verified with a full `crocodocs:generate && docusaurus build`: green, and no other reference to that slug anywhere under website/. --------- Co-authored-by: Feodor Fitsner <feodor@appveyor.com>
FeodorFitsner
added a commit
that referenced
this pull request
Sep 2, 2026
* feat(build): set window icon for Linux bundles flutter_launcher_icons has no Linux generator, so flet build linux produced apps with no icon at all (#2269). Stage the resolved icon (icon_linux > icon > template default) at linux/app_icon.png in the Flutter project, install it into the bundle as data/app_icon.png, and point GTK at it on startup so X11/XWayland taskbars and window switchers show it. Also set g_set_prgname(APPLICATION_ID) in the runner (upstream parity with flutter#154522) so the Wayland app_id and X11 WM_CLASS match the bundle id, preparing desktop-entry integration. * feat(build): ship freedesktop integration in Linux bundles Wayland desktops resolve an app's taskbar icon and launcher name only from an installed .desktop entry matching the app id — window-set icons are ignored there by design. Generate a ready-to-install tree in the bundle: share/applications/<bundle_id>.desktop (Name from --product, Comment from --description, StartupWMClass=bundle id) and the app icon at share/icons/hicolor/256x256/apps/<bundle_id>.png, so users and packagers can register the app with a plain copy into ~/.local/share or /usr/share. Also fix --description never reaching the generated project: the value was passed as template key "description" while every template consumes "project_description", so the pubspec description, web meta description, PWA manifest, and the new desktop entry Comment= always rendered empty (#2269). * fix(build): harden Linux icon staging and description templating Review fixes for the Linux icon work: - Escape project_description in every template sink: pubspec.yaml and manifest.json render it via tojson, index.html HTML-escapes it, and the desktop entry flattens newlines — a description with quotes or line breaks no longer produces an unparsable project or an entry desktop-file-validate rejects. - Quote the desktop entry's Exec value so artifact names with spaces don't word-split into the wrong program. - Keep passing the legacy "description" context key for custom build templates that declared it in their own cookiecutter.json. - Degrade gracefully (icon-less bundle) when a custom template ships no images/icon.png instead of crashing on the copy. - Warn at build time when the Linux icon is not a PNG or not 256x256, since it lands in the fixed 256x256 hicolor theme directory (new stdlib get_png_size IHDR reader). - Run the icon_linux lookup only for linux targets: on other platforms it copied a dead file and its mtime churned the icons HashStamp, re-spawning flutter_launcher_icons for nothing. - Skip the flutter_launcher_icons spawn entirely on linux targets — it only regenerates other platforms' icons the bundle never ships. - Fold the .desktop install into the icon's if(EXISTS) guard (the separate guard was dead) so a desktop entry can never install without its themed icon. - Let the runner warn on a missing/undecodable icon instead of silently skipping (dropped the g_file_test pre-check). - Make .desktop Categories configurable via tool.flet.linux.categories (default Utility) and document it. * fix(build): scale the Linux window icon to fit _NET_WM_ICON gtk_window_set_default_icon_from_file() reported success while GDK silently discarded the icon: gdk_x11_window_set_icon_list caps the _NET_WM_ICON property at GDK_SELECTION_MAX_SIZE (256 KiB of CARDINALs) and, when the first icon does not fit, breaks out of the loop and calls XDeleteProperty instead. Any icon from 512x512 up was therefore dropped — including the build template's own 1024x1024 default, so the common case shipped no window icon at all. Load the icon into a pixbuf and scale it to 256x256 before setting it, so the property always fits, and stop dereferencing a GError that a FALSE return does not guarantee is set. Also install the themed icon into the icon-theme directory that matches its real pixel size (falling back to 256x256 for non-square or non-hicolor sizes) instead of always claiming 256x256, and escape backslashes and tabs in desktop entry values, which use backslash escape sequences and must stay single-line. `flet build linux` runs for build-template changes too, so sdk/python/templates/build is added to its CI path filter. * ci: add a Linux icon verification harness Builds a generated fixture app for linux across four legs — no icon, 256x256, 512x512, and one with quotes/newlines/tabs/backslashes in the description plus a space in the artifact name — then asserts on the bundle: the runner compiled, data/app_icon.png matches its source, the themed icon landed in the right hicolor directory, the desktop entry has the expected quoted Exec/Icon/StartupWMClass/Categories and no raw control characters, and the description round-trips through pubspec.yaml, manifest.json and index.html. A second tier launches the app under Xvfb and reads back WM_CLASS and _NET_WM_ICON. Remove .github/workflows/linux-icon-test.yml and .github/ci-tmp/ before opening the PR. * ci: suppress the heavy workflows while iterating on the icon harness Pushing this branch otherwise fires ci.yml, flet-build-test.yml and flet-test.yml on every iteration (~100 job-minutes), which only contends with the Linux icon harness for runners. Exclude the branch from their push triggers; their pull_request triggers are untouched, so the PR still gets full coverage. Revert this commit before opening the PR. * ci: make the icon harness tolerant of desktop-entry warnings desktop-file-validate prints warnings (deprecated keys, hints) that are not spec violations; fail the step only when it reports an error, and print the entry either way. Also drop the -all flag from the xwininfo window sweep, which only added output for the id grep to wade through. * ci: define SDK_PYTHON for the icon harness The Patch versions step was copied from flet-build-test-matrix.yml without the env var its common.sh helper cd's into, so every leg failed before building with "SDK_PYTHON: unbound variable". * ci: upload runnable bundle tarballs from the icon harness The artifact was inspection-only, so it could not be downloaded and run on a real desktop -- which is the whole point of checking an icon. Tar the bundle inside the job (the artifact zip drops the executable bit and mangles symlinks) and ship it with a RUN_ME.txt covering the X11 xprop check and the Wayland desktop-entry install. Package it before the Xvfb step so a runtime problem can never cost the download, and stop that step from hanging: the app is launched via setsid and the whole process group is killed, since a Flet app forks a bundled Python child that otherwise keeps xvfb-run alive forever (it ran 8 minutes against a 90-second worst case). The step is now bounded by timeout(1) plus timeout-minutes, and is informational -- Tier 1 is the contract. * ci: build the icon bundles on ubuntu-22.04 The bundles are downloaded and run on a real desktop, so the runner sets the glibc floor: built on ubuntu-latest (24.04, glibc 2.39) they fail to start on Ubuntu 22.04. Building on 22.04 (glibc 2.35) covers 22.04 and newer. Also rewrite the Xvfb check, which timed out on every leg. It now runs against a wall-clock deadline instead of an iteration count, bounds every individual X call with timeout(1), prefers the icon-bearing window over GDK's InputOnly group leader, and dumps the window tree and app log on any failure so a headless miss is diagnosable instead of silent. * ci: make the fixture generator work on Python 3.10 Ubuntu 22.04 ships Python 3.10, which has no stdlib tomllib, so every leg died generating its fixture. The round-trip check it guarded is optional — assert_bundle.py verifies the description end to end anyway — so skip it when the interpreter is too old. * fix(build): correct Linux icon theme sizes and desktop entry escaping Review of the icon work turned up four real defects: - resolve_icon_theme_size accepted 28, 42, 160 and 384 as hicolor sizes. hicolor-icon-theme declares none of them, so an icon of one of those sizes was installed into a directory the theme never scans -- Icon= resolved to nothing and Wayland kept the generic icon, which is worse than the 256x256 fallback those sizes bypassed. - Exec= interpolated the artifact name into quotes unescaped. A name containing a double quote produced G_SHELL_ERROR_BAD_QUOTING and an unlaunchable entry; a backslash voided the whole key. Categories= was likewise an unescaped join, where an embedded semicolon silently split one category in two and a non-list value crashed the render (wiping the build directory with an error that never mentioned pyproject.toml). Both values are now escaped and validated in Python, where the per-key rules can be expressed, and passed to the template ready to interpolate. Categories also gains the usual tool.flet fallback. - The runner warned on every launch of a bundle that legitimately ships no icon (plain flutter build, or a custom template), which aborts under G_DEBUG=fatal-warnings. A missing file is now g_debug; only an icon that fails to decode warns. - Staged app_icon.png/app_icon.cmake were never removed when the source icon went away, so CMake kept installing the stale icon. Also widen the scale arithmetic to 64-bit (width * 256 overflows gint for very wide images, at -O3), warn when scaling fails, correct the docs and CHANGELOG which promised a fixed 256x256 theme path, fix the documented sed recipe that stripped the Exec quoting it had just added, and point the categories link at the current registry URL. * fix(build): keep the desktop entry group header on its own line Removing the Categories jinja block left {%- endmacro -%} directly above [Desktop Entry], and its trailing whitespace-strip glued the group header onto the last comment line. GLib then parsed no group at all, so every key was ignored and the entry was inert. The unit test asserted the header as a substring, which stays true when it is glued, so it caught nothing -- CI did. Parse the rendered entry the way a desktop environment does instead, and assert the header starts its own line. * ci: assert icon presence, read dimensions with an explicit xprop format The window carries _NET_WM_ICON -- xprop names it with its CARDINAL type rather than reporting it missing -- but the default formatter renders a -len truncated property as empty, so the dimension parse produced nothing and failed a check that had actually succeeded. Presence is the load-bearing assertion, and it is now what passes or fails: an oversized icon is deleted outright by GDK, which is exactly the regression this exists to catch. The size is read separately with an explicit 32c dformat and only warns when it cannot be rendered. * ci: build the icon bundles for arm64 as well A Linux VM on an Apple Silicon host is arm64, where the x64 bundle only yields "Exec format error", so the bundles were unusable for the very verification they exist for. Cross the matrix with ubuntu-22.04-arm and name the tarballs and artifacts per architecture. Also quote the Exec rewrite in RUN_ME.txt, which had the same defect the docs did: the sed stripped the quoting the template adds, so a bundle under a path containing spaces would not launch from the app grid. * ci: resolve Flutter on arm64 runners for the icon harness The arm legs all died at Setup Flutter with "Unable to determine Flutter version for channel: stable version: 3.44.8 architecture: arm64": Flutter ships no linux-arm64 archive on stable, so the action cannot resolve one. ci.yml's build_linux job already works around this by selecting the master channel for arm64, so take the same route and add its git safe.directory step, which a cloned SDK needs. * ci: precache Flutter artifacts on arm64 runners With Flutter resolving on arm64, the build got one step further and then failed pub resolution: "could not find package sky_engine in the Flutter SDK". The arm64 SDK arrives as a git clone with no engine artifacts, and flet build runs `dart run serious_python:main package` before any flutter command would fetch them. Precache explicitly; the stable x64 download already ships them, so the step is arm-only. * docs(linux): explain the app-id fallback for the app name Verified on an Ubuntu 22.04 arm64 VM: with the desktop entry not yet installed, the dock tooltip shows the bundle ID rather than the product name. That is the same root cause as the generic Wayland icon -- the desktop environment resolves both from the entry -- and it is newly visible because the runner now sets its program name to the bundle ID, so the fallback is a reverse-DNS id instead of the binary name. * ci: remove the Linux icon verification harness Drops the temporary workflow, its fixture and assertion scripts, and the push-trigger suppression on ci.yml, flet-build-test.yml and flet-test.yml, which are now byte-identical to main again. The one change that stays is flet-build-test.yml's added sdk/python/templates/build/** path filter: build-template changes never triggered the Linux build test before, which is how a broken Linux runner could have merged unnoticed. Verified before removal on an Ubuntu 22.04 arm64 VM: the taskbar icon appears under X11/XWayland with no installation, and under native Wayland once the shipped desktop entry is installed, with the correct app name. * docs(publish): document the app description build setting `--description` had no section in the publish docs, unlike every sibling setting (product, company, copyright, bundle id), so the only way to learn where it lands was to read the templates. Add one covering its resolution order and, more usefully, its actual reach: web meta tag and PWA manifest, and now the Linux desktop entry's Comment. No other platform template consumes it. Also give the changelog entry the user-visible symptom rather than the mechanism -- web descriptions have been silently empty since the option was introduced. * feat(build): add --linux-categories and document the setting The desktop entry's categories were configurable only from pyproject and documented only in passing. Add the CLI option, matching the action="extend" nargs="+" idiom every other list option uses, and give the setting its own section in the publish docs with a resolution order, as its siblings have. Drop the `tool.flet.categories` fallback: nothing else reads it, and a platform-neutral key would be a trap rather than a convenience, since macOS (public.app-category.*) and Android (game/productivity) use vocabularies in which a freedesktop value means nothing. Also link the desktop entry's Comment and Categories keys to the freedesktop specification, using the /desktop-entry/ path — the /desktop-entry-spec/ form 301s to plain http. Merge the two Linux test modules into test_build_linux.py, grouped into classes by subject (icon staging, theme size, escaping, template rendering), following test_project_dependencies.py and test_create.py. * test(build): document the Linux test methods Each test now states what it asserts, and the classes state their subject, matching test_create.py. Several tests carried that explanation as a leading comment instead; those became docstrings, leaving inline comments only where they explain a specific line. * docs(linux): move application categories to the Linux page Categories are the only build setting that applies to exactly one platform, so they belong with the rest of the Linux packaging docs rather than in the shared settings list. The section keeps its resolution order and both examples, and drops the Tabs component, which the Linux page does not use. * docs(linux): use Tabs for the categories example The other platform pages present a setting's CLI and pyproject forms in a shared-groupId Tabs block, so the Linux page should too — it just had no setting needing them until now. Adds the two imports the macOS, Android and iOS pages already carry. * docs(linux): generate the apt prerequisites from flet-cli The package list on the Linux page was a hand-maintained copy of flet_cli.utils.linux_deps, which is also what `flet --version --json` reports and what CI installs. The two happen to agree today, but nothing enforced it: adding a package for a new plugin updates CI and silently leaves the docs wrong. Generate the block instead, via a crocodocs partial that imports the list inside the flet-cli environment — the same mechanism cross-platform-permissions.mdx already uses, so discovery is automatic from the page's import. Present it in three tabs: the package list, and the equivalent CLI command with and without jq, for setup scripts that should never go stale. The generated list is alphabetical, as the source is, losing the old loose grouping by purpose; the prose below it still explains what each group of packages is for. * fix(build): actually wire up --linux-categories The option and its resolution never reached the previous commit — only the docs and tests did — so the published resolution order described a flag that did not exist, and `tool.flet.categories` was still consulted despite being documented as removed. Add the argparse option, resolve it ahead of `[tool.flet.linux].categories`, and drop the platform-neutral key. Cover the wiring with tests that build the real parser: asserting on `escape_desktop_categories` alone passes whether or not the option is registered, which is exactly how this slipped through. * refactor(build): pass the app description under one template key `description` duplicated `project_description` with the same value. It was only ever reachable by a custom build template that declared the key in its own cookiecutter.json — the shipped template declares and consumes only `project_description` — so the second key protected a case that likely does not exist, at the cost of two names for one value. `flet create` is unaffected: its `description` key belongs to the separate app templates, which do consume `cookiecutter.description`. * refactor(build): name the desktop Exec context key for its platform `desktop_exec` sat beside `linux_categories` but read as though it applied to desktop platforms generally, when only the Linux desktop entry consumes it. Rename it to `linux_desktop_exec`. Its cookiecutter.json entry also defaulted to `{{ cookiecutter.artifact_name }}` while being declared above `artifact_name`, so the default resolved to nothing — invisible while `flet build` always passes an explicit value, but wrong for anything rendering the template on its own. Declare both Linux keys after `artifact_name`. * refactor(build): name the desktop entry escapers for their platform Rename escape_desktop_exec and escape_desktop_categories to escape_linux_desktop_exec / escape_linux_desktop_categories, matching the context keys they feed. Desktop entries are a Linux concern, and the bare names read as though they applied to every desktop platform. Also repairs the previous commit, which renamed the context key in the template but left the test's render context on the old name, so the desktop entry tests failed there. * fix(build): keep the template pubspec parseable while unrendered Escaping the description with `| tojson` left the value unquoted, and an unquoted `{{` opens a YAML flow mapping — so the template pubspec.yaml stopped parsing as YAML. `.github/scripts/patch_pubspec_version.py` loads that file before cookiecutter ever runs, so the build_templates CI job failed, and on a release tag the build template zip would not have been produced at all. Verified by running the CI script: exit 1 on this branch, exit 0 on main. Quoting cannot be fixed in the template alone, because that script rewrites the file with yaml.dump and normalizes quoting, so the escaping has to match what survives the round-trip. Escape the value in Python for a single-quoted scalar and interpolate it into the quotes the template provides. Also: - resolve the Linux categories only for linux targets, so a malformed `[tool.flet.linux] categories` cannot fail an Android or web build; - flatten control characters in both desktop-entry escapers, since a newline in Exec or Categories leaves a line with no `=` and the desktop environment discards the whole entry; - render templates in tests with StrictUndefined, so a renamed context key raises instead of quietly rendering empty — the failure mode that let a broken commit pass. Adds contract tests for both classes of bug that have now shipped: every `cookiecutter.<key>` a template reads must be declared in cookiecutter.json (cookiecutter drops the rest), and the pubspec must parse unrendered and render to valid YAML for quotes, backslashes and newlines. Both were confirmed to fail when their bug is reintroduced. * docs(linux): add a Distributing section `flet build linux` produces a bundle directory, which is not something an end user can download and run — the page stopped one step short of a shippable artifact. Add AppImage, .deb and .rpm recipes that build on the desktop entry and hicolor icon the bundle now ships, so packaging is mostly relocation. Each recipe keeps the bundle intact and rewrites Exec= to the install location, since the executable resolves its libraries and Python runtime from its own path. Also records why fastforge (formerly flutter_distributor) is not the recommended route: it rebuilds the app with `flutter build linux`, which produces a bundle with no Python payload because that is staged by a separate step under environment `flet build` sets, and it replaces the bundle's desktop entry with one lacking StartupWMClass. NOT YET VERIFIED on a Linux machine. * docs(linux): fix admonition titles and explain the FUSE requirement The new admonitions used `:::warning Title`, which Docusaurus only renders as a titled admonition in its bracketed form — the rest of the docs use `:::warning[Title]` 103 times against 5 spaced. The FUSE aside also assumed the reader knew what FUSE 2 is and whether they have it. Link the AppImage troubleshooting page, give the one-line check, and note that Ubuntu 22.04+ dropped libfuse2 by default — which is exactly where this bites — plus both ways out and the fact that it applies to the AppImage you ship, not just to appimagetool. * docs: repair admonitions that render without their title Docusaurus only renders a custom admonition title in the bracketed form, `:::note[Title]`; the spaced form drops the title into the body. Two pages used the spaced form. Also drops the aside explaining why fastforge is not the recommended packaging route — the Distributing section stands on the recipes it gives without arguing against a third-party tool by name. * test(build): move the template contract tests to their own file These assert invariants of the cookiecutter template itself — that every context key a template reads is declared, and that pubspec.yaml parses unrendered and renders to valid YAML — none of which is Linux-specific. They only lived in the Linux file because that is where the bugs that motivated them were found. Each file keeps its own copy of the small render helper rather than introducing a conftest, matching how the other suites here are written. * docs(build): restore comments dropped from template_data The three comments explaining why the description is carried under two keys were lost while the docs work lived on a second branch. Nothing about the behaviour changed; only the explanation of it went missing. * test(build): keep per-class detail in the class docstrings The Linux module docstring described what each group of tests covers, which belongs on the classes themselves — a reader looking at one class should not have to scroll to the top of the file for it. The module docstring now says only what is true of the whole file. Restores the same explanation to TestBuildTemplateContract, which lost it earlier and had it nowhere. * docs(linux): stop asserting which distributions ship FUSE 2 The FUSE note claimed Ubuntu 22.04 and later do not install libfuse2 by default. An Ubuntu 22.04 arm64 machine reports it present, so the claim is at best not universally true — it can arrive as another package's dependency. The check was already the actionable part; keep it and drop the distribution-specific assertion. * docs(linux): show how to fetch and chmod appimagetool The AppImage recipe said to get the tool "and make it executable" without showing either step, and then hardcoded x86_64 in the invocation — which is wrong on the arm64 machines this section is most likely to be tried on. Give the download and chmod commands, derive the architecture from `uname -m`, and use it consistently in all three places the tool is invoked. Both release URLs verified to resolve. * docs(linux): say where appimagetool has to live The download step never said which directory to run it from, and the recipe then invoked the tool by a bare relative path — so the two only worked together if the reader happened to build the AppDir from the same directory they downloaded into. Note that the tool can live anywhere and take its location as a variable in the recipe. * docs(linux): annotate the AppImage recipe Follows the GitHub Actions section's annotation style so each step explains itself, rather than leaving a reader to infer why the AppDir needs four entries at its root or why Exec= is rewritten to a bare name. Annotations force the line continuations out — a trailing `# (n)!` and a trailing `\` cannot coexist — which is a good trade: a continuation silently breaks when a paste inserts blank lines, and that is how the recipe failed the first time it was run for real. Also presents it as a script to save and run rather than a block to paste, adds `set -euo pipefail` so a failed copy stops there instead of surfacing as a confusing appimagetool error, and guards the bundle prerequisite. * docs(linux): make the AppImage annotations say what they mean Several were too compressed to act on: the bundle variable never said it takes a path, the executable one never said it takes a bare filename rather than a path, and "bundle", "AppDir" and "FHS" were used as though the reader already knew them. Each now says what kind of value it wants, where to find it, and what the term means on first use. * docs(linux): make each AppImage annotation stand on its own Annotations are read one at a time, so "that directory" and "that icon's own path" pointed at nothing for anyone opening those two on their own. Name what they refer to instead. Also carries the working tree's emphasis on save/edit/run in the intro. * docs(linux): name the three variables the reader has to edit "Edit the three variables at the top" left the reader to work out which of the six they were. Name them inline, matching the three annotations marked "Edit this". * docs(linux): distinguish main from additional categories The example passed two main categories, which is legal but means the entry "may appear more than once in the menu" per the spec — appimagetool hints about it, so the docs were teaching the thing a linter warns against. Use a main category paired with an additional one instead, and explain the split. Also drops the claim that desktop environments ignore unregistered values: the spec does not say that. What is true is that no menu rule matches them, so they have no effect on placement. * docs(linux): annotate the deb and rpm recipes Both were bare scripts: correct, but silent about every decision that matters. Neither said why the bundle goes to /opt in one piece, why /usr/bin gets a symlink rather than a wrapper (a wrapper resolves to /usr/bin, and the app locates its Python runtime from the running executable's path), or why rpmbuild's post-processing has to be switched off — left on, it byte-compiles the bundled site-packages with the system Python. Gives them the same treatment as the AppImage recipe: annotations on every meaningful line, no line continuations, variables to edit called out by name, and a verification step for the .deb. The rpm tab also gains the rpmbuild invocation and tree setup, which it previously assumed. * docs(linux): take the bundle path as a variable in the deb recipe The AppImage recipe took BUNDLE as a variable while this one hardcoded build/linux, so it could not package a bundle that lives anywhere else — a downloaded artifact, or a build kept outside the project. * docs(linux): renumber two annotation lists Both render correctly today only because markdown renumbers ordered lists for you. In the source the AppImage list skipped 4 and used 17 twice, so from the fourth item on every number named a different line than the one it annotated -- a trap for whoever edits it next. * docs(linux): make the rpm /usr/bin symlink relative rpm warns on any absolute symlink target, and rpmlint's default UseRelativeSymlinks flags it as symlink-should-be-relative. From /usr/bin, ../../opt/<name>/<bin> resolves to the same path, so the installed package is unchanged. Also document the stale build directory that wedges a retried rpmbuild with a misleading "Bad file descriptor" errno. * docs(linux): explain why deb and rpm symlinks differ The two recipes point /usr/bin at /opt in opposite ways on purpose: Debian Policy 10.5 asks for absolute links across top-level directories, while rpmlint's default UseRelativeSymlinks flags exactly that. Note it so the difference does not read as an oversight. * docs(linux): say what an AppImage does not register An AppImage installs no desktop entry anywhere the shell scans, so the app grid has no entry for it and its icon has no name to show. Verified on a 22.04 VM: the same image showed the app id until an entry for that app id existed, then the name. Worth stating because the section otherwise reads as though the format were interchangeable with the other two. * docs(linux): let the AppImage recipe fetch its own appimagetool The page said the tool "can live anywhere" and that the recipe "takes its location as a variable", but APPIMAGETOOL was not among the three variables the reader is told to edit -- it was hardcoded to $PWD. Anyone who saved the script in their project and left the download in ~/Downloads, which the prose explicitly allowed, got a failure. The script is also meant to be re-run on every rebuild, and that only worked from the one directory holding the tool. Fetching it from inside the script removes the path rather than documenting it. Guarded on the file already being there, so a rebuild costs nothing and a copy placed by hand -- from a mirror, or on a machine with no network -- is used untouched. Pinned to 1.9.1 rather than the rolling `continuous` tag, now that a build script re-runs the download: a rebuild should not be able to pick up a different tool without the reader choosing it. appimagetool does publish versioned releases, and 1.9.1 ships the same asset names, so this is a drop-in. Verified both pinned URLs resolve, the guard's three states, and that the extractor still pulls the recipe cleanly. * docs(webview): add JavaScriptMode type page to fix unresolved xref JavaScriptMode is exported from flet_webview but had no docs page, so the :attr:`flet_webview.JavaScriptMode.UNRESTRICTED` reference in WebView.set_javascript_mode rendered as raw reST text. * docs(linux): stop the appimagetool guard destroying a hand-placed copy An audit of the previous commit found the guard I had just written does the opposite of what I documented it doing, in exactly the two cases the annotation named. `[ ! -x "$APPIMAGETOOL" ]` tests the execute bit, not existence, and every ordinary way of getting the file -- wget, curl, a browser, an extracted archive -- leaves it mode 644. So the guard fired on precisely the hand-placed copies it promised to leave alone. And `wget -O` truncates its destination before it connects, which I proved rather than assumed: a 37-byte file against an unreachable host came back 0 bytes. A reader on a restricted network with their only copy next to the script lost it, and every re-run failed identically with nothing to fall back on. Now tests `-e`, downloads via `.part` and moves into place only on success, and chmods outside the block so a hand-placed copy gets the bit it needs -- the instruction to set it by hand having been removed along with the manual download. Exercised all four states against real wget: a mode-644 copy now survives online and offline and ends up executable, and a failed download leaves nothing that could pass for a working tool. Also narrows the offline claim. appimagetool downloads the AppImage runtime it embeds, so having the tool on disk is not enough to build without a network; annotation 22 now says so and points at --runtime-file. * docs: drop the dangling 1.0.0 announcement link `/blog/flet-1-0` has no post behind it -- the blog declares `introducing-flet-1-0-alpha` and `flet-1-0-beta`, and the stable announcement is not written yet. Docusaurus fails the build on broken links, so this took down the docs workflow and the Cloudflare deploy with it. Every other entry links to a post that exists, so the line loses just the announcement and keeps its changelog and breaking-changes links. Put it back when the post lands. Arrived in #6693 and is unrelated to the Linux icon work; it rides on this branch only because that is where it was hit. Verified with a full `crocodocs:generate && docusaurus build`: green, and no other reference to that slug anywhere under website/. * fix(`flet build`): double a literal percent in the desktop entry's Exec `%` introduces a field code, so an artifact name containing one -- `Save 50% Now` -- reached the desktop as `Save 50Now`, losing the percent and the character after it, and the launcher then pointed at a path that does not exist. Found while reviewing the `flet pack` sibling, whose escaper was mirrored from this one and inherited the same gap. Covered by two cases in the existing parametrised test so the two implementations cannot drift apart again. * fix(`flet build`): stop None reaching the generated project files Two defects from Copilot's review of #6799, both the same shape: a value resolved to None and was then passed into the cookiecutter context, where it overrode the default cookiecutter.json declares and rendered as the literal string "None". `project_description` had no final fallback, so a project with no description in --description, project.description or tool.poetry.description produced `content="None"` in web/index.html, `"description": "None"` in web/manifest.json, and the same in the README. pubspec.yaml escaped it to "" and was unaffected, which is why this went unnoticed. `linux_categories` was None for every non-Linux target. Each target renders the whole template, so a Windows or macOS build still wrote the desktop entry -- with `Categories=None` instead of the declared `Utility;`. It now falls back through the same escaper, and a test pins that fallback to the value in cookiecutter.json so the two cannot drift. Also drops the `raise` after `self.cleanup(...)` in the categories handler: cleanup ends in sys.exit(), so it was unreachable. The third point in that review -- a literal `%` in Exec= -- was already fixed in the preceding commit, found while reviewing the `flet pack` sibling. --------- Co-authored-by: Feodor Fitsner <feodor@appveyor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Prepares Flet for a deprecation-free 1.0 by removing every deprecated API from shipping source — both the version-scheduled deprecations (0.88 → 1.0) and the ones that had no scheduled removal. A multi-agent audit across all 24 Python and 19 Dart packages confirms zero active deprecations remain.
Removed
Controls & events
DragTargetEvent.x/.y/.offset→ uselocal_position/global_positionConstrainedControl→ inherit fromLayoutControlElevatedButton→ useButtonVideo.show_controls(→controls=None),Video.playlist_add()/playlist_remove()(→ mutateVideo.playlist)Page
Page.go()→Page.push_route()Page.url_launcher/browser_context_menu/shared_preferences/clipboard/storage_paths→ instantiate the service classes directly (UrlLauncher(), etc.)Page.launch_url()/can_launch_url()/close_in_app_web_view()→UrlLauncher().*App entry
app()/app_async()→run()/run_async()run(target=...)/run_async(target=...)→ passmainFletApp.show_app_startup_screen/app_startup_screen_message→boot_screen_optionsColors — 14 non-underscored aliases (
BLACK12…WHITE70) → underscored names (Colors.BLACK_12);Colorsreverted to a plainEnumCLI / build
--clear-cacheflag offlet build/flet debug→flet clean[tool.flet.app.boot_screen]/[tool.flet.app.startup_screen]config →[tool.flet.boot_screen]Dart — empty-string (
"") widget-state key back-compat → use"default"Notes
DropdownM2is kept and un-deprecated — its 0.84.0 deprecation in favor ofDropdownis reverted; it remains a supported control.page.launch_url()toft.UrlLauncher().flet_mapexamples:SimpleAttribution.on_click=lambda e: <async launch_url>never awaited the coroutine (click did nothing) → replaced with properasync defhandlers.All of the above are breaking. See the
## 1.0.0section ofCHANGELOG.mdand the updated 0.85.0 / 0.86.0 migration guides.Summary by Sourcery
Remove deprecated APIs and compatibility shims across Flet and update user-facing examples and migration documentation for a deprecation-free 1.0 release.
Bug Fixes:
Enhancements:
Build:
Documentation: