From 4b1bc44acf935142dc38f057d586ac5b2de39aaa Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Fri, 17 Jul 2026 18:24:17 +0200 Subject: [PATCH 01/11] Remove deprecated DragTargetEvent coordinates and Video playlist/controls 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. --- CHANGELOG.md | 8 +++ sdk/python/packages/flet-video/CHANGELOG.md | 7 +++ .../flet-video/src/flet_video/video.py | 50 +------------------ .../src/flutter/flet_video/lib/src/video.dart | 4 +- .../src/flet/controls/core/drag_target.py | 49 ------------------ ...eprecated-drag-target-event-coordinates.md | 7 ++- .../v0-85-0/deprecated-video-apis.md | 7 ++- 7 files changed, 23 insertions(+), 109 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec1f39e280..a03d7a8883 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## Unreleased + +### Breaking changes + +* Remove `DragTargetEvent.x`, `DragTargetEvent.y`, and `DragTargetEvent.offset` (deprecated in `0.85.0`). Use `DragTargetEvent.local_position` for target-relative coordinates or `DragTargetEvent.global_position` for global coordinates ([#6401](https://github.com/flet-dev/flet/pull/6401)) by @ndonkoHenri. +* Remove `Video.show_controls` (deprecated in `0.85.0`). Set `Video.controls` to `None` to hide controls ([#6463](https://github.com/flet-dev/flet/pull/6463)) by @ndonkoHenri. +* Remove `Video.playlist_add()` and `Video.playlist_remove()` (deprecated in `0.85.0`). Mutate `Video.playlist` directly with list methods such as `append()` and `pop()` ([#6463](https://github.com/flet-dev/flet/pull/6463)) by @ndonkoHenri. + ## 0.86.1 ### Improvements diff --git a/sdk/python/packages/flet-video/CHANGELOG.md b/sdk/python/packages/flet-video/CHANGELOG.md index 63d23a9fb5..bac8bea77a 100644 --- a/sdk/python/packages/flet-video/CHANGELOG.md +++ b/sdk/python/packages/flet-video/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## Unreleased + +### Removed + +- `Video.show_controls` (deprecated in 0.85.0); set `Video.controls` to `None` to hide controls ([#6463](https://github.com/flet-dev/flet/pull/6463)) by @ndonkoHenri. +- `Video.playlist_add()` and `Video.playlist_remove()` (deprecated in 0.85.0); mutate `Video.playlist` directly with list methods such as `append()` and `pop()` ([#6463](https://github.com/flet-dev/flet/pull/6463)) by @ndonkoHenri. + ## 0.85.0 ### Added diff --git a/sdk/python/packages/flet-video/src/flet_video/video.py b/sdk/python/packages/flet-video/src/flet_video/video.py index ccdaa38919..986776244f 100644 --- a/sdk/python/packages/flet-video/src/flet_video/video.py +++ b/sdk/python/packages/flet-video/src/flet_video/video.py @@ -3,11 +3,9 @@ """ from dataclasses import field -from typing import Annotated, Optional, Union +from typing import Optional, Union import flet as ft -from flet.utils.deprecated import deprecated -from flet.utils.validation import V from flet_video.types import ( AdaptiveVideoControls, PlaylistMode, @@ -61,19 +59,6 @@ class Video(ft.LayoutControl): Whether the video should start playing automatically. """ - show_controls: Annotated[ - Optional[bool], - V.deprecated( - version="0.85.0", - delete_version="0.88.0", - reason="Use controls=None to hide controls.", - docs_reason="To hide controls, instead set :attr:`controls` to `None`.", - ), - ] = None - """ - Whether to show the video player :attr:`controls`. - """ - controls: Optional[ Union[ VideoControls, @@ -96,10 +81,6 @@ class Video(ft.LayoutControl): :attr:`VideoControlsMode.NORMAL` controls are reused before falling back to :attr:`VideoControlsMode.DEFAULT`. A mode value of `None` hides controls for that mode only. - - Note: - During the :attr:`show_controls` deprecation period, `show_controls=False` - hides controls even when this property is set. """ fullscreen: bool = False @@ -297,35 +278,6 @@ async def jump_to(self, media_index: int): arguments={"media_index": media_index}, ) - @deprecated( - reason="Use playlist.append(media) instead.", - docs_reason="Use :attr:`playlist` directly, for example `video.playlist.append(media)`.", # noqa: E501 - version="0.85.0", - delete_version="0.88.0", - show_parentheses=True, - ) - async def playlist_add(self, media: VideoMedia): - """Appends/Adds the provided `media` to the `playlist`.""" - if not media.resource: - raise ValueError("media has no resource") - self.playlist.append(media) - - @deprecated( - reason="Use playlist.pop(media_index) instead.", - docs_reason="Use :attr:`playlist` directly, for example `video.playlist.pop(media_index)`.", # noqa: E501 - version="0.85.0", - delete_version="0.88.0", - show_parentheses=True, - ) - async def playlist_remove(self, media_index: int): - """Removes the provided `media` from the `playlist`.""" - playlist_length = len(self.playlist) - if not (-playlist_length <= media_index < playlist_length): - raise IndexError("media_index is out of range") - if media_index < 0: - media_index = playlist_length + media_index - self.playlist.pop(media_index) - async def is_playing(self) -> bool: """ Returns: diff --git a/sdk/python/packages/flet-video/src/flutter/flet_video/lib/src/video.dart b/sdk/python/packages/flet-video/src/flutter/flet_video/lib/src/video.dart index 03eceb7c45..4f31e50f2b 100644 --- a/sdk/python/packages/flet-video/src/flutter/flet_video/lib/src/video.dart +++ b/sdk/python/packages/flet-video/src/flutter/flet_video/lib/src/video.dart @@ -337,9 +337,7 @@ class _VideoControlState extends State with FletStoreMixin { var playbackRate = widget.control.getDouble("playback_rate"); var playlist = widget.control.get("playlist"); var shufflePlaylist = widget.control.getBool("shuffle_playlist"); - var controls = widget.control.getBool("show_controls", true)! - ? widget.control.get("controls") - : null; + var controls = widget.control.get("controls"); var playlistMode = parsePlaylistMode(widget.control.getString("playlist_mode")); var fullscreen = widget.control.getBool("fullscreen", false)!; diff --git a/sdk/python/packages/flet/src/flet/controls/core/drag_target.py b/sdk/python/packages/flet/src/flet/controls/core/drag_target.py index f5bce32bdc..69ec990afd 100644 --- a/sdk/python/packages/flet/src/flet/controls/core/drag_target.py +++ b/sdk/python/packages/flet/src/flet/controls/core/drag_target.py @@ -6,7 +6,6 @@ from flet.controls.control_event import Event, EventHandler from flet.controls.core.draggable import Draggable from flet.controls.transform import Offset -from flet.utils.deprecated import deprecated from flet.utils.validation import V __all__ = [ @@ -73,54 +72,6 @@ def __post_init__(self): if self.src_id is not None: self.src = cast(Draggable, self.page.get_control(self.src_id)) - @property - @deprecated( - reason="Use `local_position.x` for target-relative coordinates or " - "`global_position.x` for global coordinates instead.", - docs_reason="Use [`local_position.x`][flet.DragTargetEvent.local_position] for target-relative coordinates or " # noqa: E501 - "[`global_position.x`][flet.DragTargetEvent.global_position] for global coordinates instead.", # noqa: E501 - version="0.85.0", - delete_version="0.88.0", - ) - def x(self) -> float: - """ - Horizontal pointer position in the global coordinate space. - """ - - return self.global_position.x - - @property - @deprecated( - reason="Use `local_position.y` for target-relative coordinates or " - "`global_position.y` for global coordinates instead.", - docs_reason="Use [`local_position.y`][flet.DragTargetEvent.local_position] for target-relative coordinates or " # noqa: E501 - "[`global_position.y`][flet.DragTargetEvent.global_position] for global coordinates instead.", # noqa: E501 - version="0.85.0", - delete_version="0.88.0", - ) - def y(self) -> float: - """ - Vertical pointer position in the global coordinate space. - """ - - return self.global_position.y - - @property - @deprecated( - reason="Use `local_position` for target-relative coordinates or " - "`global_position` for global coordinates instead.", - docs_reason="Use [`local_position`][flet.DragTargetEvent.local_position] for target-relative coordinates or " # noqa: E501 - "[`global_position`][flet.DragTargetEvent.global_position] for global coordinates instead.", # noqa: E501 - version="0.85.0", - delete_version="0.88.0", - ) - def offset(self) -> Offset: - """ - Pointer position in global coordinates. - """ - - return self.global_position - @dataclass class DragTargetLeaveEvent(Event["DragTarget"]): diff --git a/website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md b/website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md index 51a70b0207..a7865b6a8c 100644 --- a/website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md +++ b/website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md @@ -13,9 +13,8 @@ The [breaking changes and deprecations index](../index.md) lists the guides crea ## Summary -Flet 0.85.0 deprecated [`DragTargetEvent.x`][flet.DragTargetEvent.x], -[`DragTargetEvent.y`][flet.DragTargetEvent.y], and -[`DragTargetEvent.offset`][flet.DragTargetEvent.offset]. +Flet 0.85.0 deprecated `DragTargetEvent.x`, `DragTargetEvent.y`, and +`DragTargetEvent.offset`. Use [`DragTargetEvent.local_position`][flet.DragTargetEvent.local_position] for target-relative coordinates, or @@ -56,7 +55,7 @@ If your code needs page-level coordinates instead, use ## Timeline - Deprecated in: `0.85.0` -- Removal in: `0.88.0` +- Removed in: Unreleased ## References diff --git a/website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md b/website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md index 10580e1164..38b4c35f44 100644 --- a/website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md +++ b/website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md @@ -13,9 +13,8 @@ The [breaking changes and deprecations index](../index.md) lists the guides crea ## Summary -Flet 0.85.0 deprecated [`Video.show_controls`][flet_video.Video.show_controls], -[`Video.playlist_add()`][flet_video.Video.playlist_add], and -[`Video.playlist_remove()`][flet_video.Video.playlist_remove]. +Flet 0.85.0 deprecated `Video.show_controls`, `Video.playlist_add()`, and +`Video.playlist_remove()`. Use [`Video.controls`][flet_video.Video.controls] to configure or hide video controls. Mutate [`Video.playlist`][flet_video.Video.playlist] directly with @@ -75,7 +74,7 @@ been added to the page. ## Timeline - Deprecated in: `0.85.0` -- Removal in: `0.88.0` +- Removed in: Unreleased ## References From 6f260f3653a8ad4ca9e3a131a7068be6763303f2 Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Fri, 17 Jul 2026 18:24:17 +0200 Subject: [PATCH 02/11] Remove deprecated FletApp startup-screen properties and --clear-cache 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) --- CHANGELOG.md | 4 +- .../src/flet_cli/commands/build_base.py | 35 ------------ sdk/python/packages/flet-video/CHANGELOG.md | 2 +- .../flet/src/flet/controls/core/flet_app.py | 57 ------------------- ...eprecated-drag-target-event-coordinates.md | 2 +- .../v0-85-0/deprecated-video-apis.md | 2 +- .../v0-86-0/deprecated-clear-cache-flag.md | 2 +- 7 files changed, 7 insertions(+), 97 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a03d7a8883..48e13943da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,12 @@ -## Unreleased +## 1.0.0 ### Breaking changes * Remove `DragTargetEvent.x`, `DragTargetEvent.y`, and `DragTargetEvent.offset` (deprecated in `0.85.0`). Use `DragTargetEvent.local_position` for target-relative coordinates or `DragTargetEvent.global_position` for global coordinates ([#6401](https://github.com/flet-dev/flet/pull/6401)) by @ndonkoHenri. * Remove `Video.show_controls` (deprecated in `0.85.0`). Set `Video.controls` to `None` to hide controls ([#6463](https://github.com/flet-dev/flet/pull/6463)) by @ndonkoHenri. * Remove `Video.playlist_add()` and `Video.playlist_remove()` (deprecated in `0.85.0`). Mutate `Video.playlist` directly with list methods such as `append()` and `pop()` ([#6463](https://github.com/flet-dev/flet/pull/6463)) by @ndonkoHenri. +* Remove `FletApp.show_app_startup_screen` and `FletApp.app_startup_screen_message` (deprecated in `0.86.0`). Use `FletApp.boot_screen_options` instead, e.g. `boot_screen_options={'spinner_size': 30}` or `boot_screen_options={'startup_message': '...'}` by @ndonkoHenri. +* Remove the `--clear-cache` flag of `flet build` and `flet debug` (deprecated in `0.86.0`). Use the `flet clean` command instead ([#6233](https://github.com/flet-dev/flet/issues/6233)) by @ndonkoHenri. ## 0.86.1 diff --git a/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py b/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py index 5eb5ef62cd..1305894051 100644 --- a/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py +++ b/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py @@ -17,7 +17,6 @@ import flet.version import flet_cli.utils.processes as processes from flet.utils import copy_tree, slugify -from flet.utils.deprecated import deprecated_warning from flet_cli.commands.flutter_base import ( BaseFlutterCommand, console, @@ -285,14 +284,6 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None: help="Files and/or directories to exclude from the package" "; can be used multiple times", ) - parser.add_argument( - "--clear-cache", - dest="clear_cache", - action="store_true", - default=None, - help="Remove any existing build cache before starting the build process. " - "Deprecated: use the `flet clean` command instead", - ) parser.add_argument( "--project", dest="project_name", @@ -710,21 +701,6 @@ def handle(self, options: argparse.Namespace) -> None: super().handle(options) - if getattr(self.options, "clear_cache", None): - deprecated_warning( - name="--clear-cache", - reason="Use the `flet clean` command instead.", - version="0.86.0", - delete_version="0.89.0", - type="flag", - ) - console.print( - "Warning: the `--clear-cache` flag is deprecated since version " - "0.86.0 and will be removed in version 0.89.0. " - "Use the `flet clean` command instead.", - style=warning_style, - ) - if "target_platform" in self.options: self.target_platform = self.options.target_platform @@ -1517,17 +1493,6 @@ def create_flutter_project(self, second_pass=False): hash_changed = hash.has_changed() if hash_changed: - # if options.clear_cache is set, delete any existing Flutter bootstrap - # project directory - if ( - self.options.clear_cache - and self.flutter_dir.exists() - and not second_pass - ): - if self.verbose > 1: - console.log(f"Deleting {self.flutter_dir}", style=verbose2_style) - shutil.rmtree(self.flutter_dir, ignore_errors=True) - # create a new Flutter bootstrap project directory, if non-existent if not second_pass: self.flutter_dir.mkdir(parents=True, exist_ok=True) diff --git a/sdk/python/packages/flet-video/CHANGELOG.md b/sdk/python/packages/flet-video/CHANGELOG.md index bac8bea77a..c6a0107df3 100644 --- a/sdk/python/packages/flet-video/CHANGELOG.md +++ b/sdk/python/packages/flet-video/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## Unreleased +## 1.0.0 ### Removed diff --git a/sdk/python/packages/flet/src/flet/controls/core/flet_app.py b/sdk/python/packages/flet/src/flet/controls/core/flet_app.py index 5a38f74481..ccf18ccdf7 100644 --- a/sdk/python/packages/flet/src/flet/controls/core/flet_app.py +++ b/sdk/python/packages/flet/src/flet/controls/core/flet_app.py @@ -4,7 +4,6 @@ from flet.controls.base_control import control from flet.controls.control_event import ControlEventHandler, Event, EventHandler from flet.controls.layout_control import LayoutControl -from flet.utils.deprecated import deprecated __all__ = ["FletApp", "FletAppOutputEvent"] @@ -98,59 +97,3 @@ class FletApp(LayoutControl): `force_pyodide=True`; root-level Pyodide pages have nowhere to bubble the event. """ - - @property - @deprecated( - reason="Use `boot_screen_options` instead, e.g. " - "boot_screen_options={'spinner_size': 30}.", - version="0.86.0", - delete_version="0.89.0", - ) - def show_app_startup_screen(self) -> bool: - """ - Whether to show the app startup screen. - """ - return bool((self.boot_screen_options or {}).get("spinner_size", 0)) - - @show_app_startup_screen.setter - @deprecated( - reason="Use `boot_screen_options` instead, e.g. " - "boot_screen_options={'spinner_size': 30}.", - version="0.86.0", - delete_version="0.89.0", - ) - def show_app_startup_screen(self, value: bool) -> None: - options = dict(self.boot_screen_options or {}) - if value: - options.setdefault("spinner_size", 30) - else: - options.pop("spinner_size", None) - self.boot_screen_options = options - - @property - @deprecated( - reason="Use `boot_screen_options` instead, e.g. " - "boot_screen_options={'startup_message': '...'}.", - version="0.86.0", - delete_version="0.89.0", - ) - def app_startup_screen_message(self) -> Optional[str]: - """ - Message to display on the app startup screen. - """ - return (self.boot_screen_options or {}).get("startup_message") - - @app_startup_screen_message.setter - @deprecated( - reason="Use `boot_screen_options` instead, e.g. " - "boot_screen_options={'startup_message': '...'}.", - version="0.86.0", - delete_version="0.89.0", - ) - def app_startup_screen_message(self, value: Optional[str]) -> None: - options = dict(self.boot_screen_options or {}) - if value is not None: - options["startup_message"] = value - else: - options.pop("startup_message", None) - self.boot_screen_options = options diff --git a/website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md b/website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md index a7865b6a8c..5e603dd62c 100644 --- a/website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md +++ b/website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md @@ -55,7 +55,7 @@ If your code needs page-level coordinates instead, use ## Timeline - Deprecated in: `0.85.0` -- Removed in: Unreleased +- Removed in: `1.0.0` ## References diff --git a/website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md b/website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md index 38b4c35f44..8ba5dcfc95 100644 --- a/website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md +++ b/website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md @@ -74,7 +74,7 @@ been added to the page. ## Timeline - Deprecated in: `0.85.0` -- Removed in: Unreleased +- Removed in: `1.0.0` ## References diff --git a/website/docs/updates/breaking-changes/v0-86-0/deprecated-clear-cache-flag.md b/website/docs/updates/breaking-changes/v0-86-0/deprecated-clear-cache-flag.md index a3aec1aef1..868350abd6 100644 --- a/website/docs/updates/breaking-changes/v0-86-0/deprecated-clear-cache-flag.md +++ b/website/docs/updates/breaking-changes/v0-86-0/deprecated-clear-cache-flag.md @@ -50,7 +50,7 @@ current directory), so you can target another project with `flet clean path/to/a ## Timeline - Deprecated in: `0.86.0` -- Removal in: `0.89.0` +- Removed in: `1.0.0` ## References From 3fb5ca5a08a5d221fa3b362eb9be68b781dafcbd Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Fri, 17 Jul 2026 18:39:40 +0200 Subject: [PATCH 03/11] Remove deprecated Page.go() and Page service accessors 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 --- CHANGELOG.md | 2 + .../declarative/trolli/components/dialogs.py | 2 +- .../material/context_menu/triggers/main.py | 2 +- .../packages/flet/src/flet/controls/page.py | 90 ------------------- 4 files changed, 4 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48e13943da..9c2e874157 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ * Remove `Video.playlist_add()` and `Video.playlist_remove()` (deprecated in `0.85.0`). Mutate `Video.playlist` directly with list methods such as `append()` and `pop()` ([#6463](https://github.com/flet-dev/flet/pull/6463)) by @ndonkoHenri. * Remove `FletApp.show_app_startup_screen` and `FletApp.app_startup_screen_message` (deprecated in `0.86.0`). Use `FletApp.boot_screen_options` instead, e.g. `boot_screen_options={'spinner_size': 30}` or `boot_screen_options={'startup_message': '...'}` by @ndonkoHenri. * Remove the `--clear-cache` flag of `flet build` and `flet debug` (deprecated in `0.86.0`). Use the `flet clean` command instead ([#6233](https://github.com/flet-dev/flet/issues/6233)) by @ndonkoHenri. +* Remove `Page.go()` (deprecated in `0.80.0`). Use `Page.push_route()` instead by @ndonkoHenri. +* 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 corresponding service classes directly: `UrlLauncher()`, `BrowserContextMenu()`, `SharedPreferences()`, `Clipboard()`, `StoragePaths()` by @ndonkoHenri. ## 0.86.1 diff --git a/sdk/python/examples/apps/declarative/trolli/components/dialogs.py b/sdk/python/examples/apps/declarative/trolli/components/dialogs.py index 9db842bb2c..4cf8cc3e19 100644 --- a/sdk/python/examples/apps/declarative/trolli/components/dialogs.py +++ b/sdk/python/examples/apps/declarative/trolli/components/dialogs.py @@ -45,7 +45,7 @@ async def do_login(_: ft.Event): error_text.value = "Please provide username and password" ft.context.page.update() return - await ft.context.page.shared_preferences.set("current_user", user) + await ft.SharedPreferences().set("current_user", user) app.user = user ft.context.page.pop_dialog() diff --git a/sdk/python/examples/controls/material/context_menu/triggers/main.py b/sdk/python/examples/controls/material/context_menu/triggers/main.py index f7e356c262..6b995dd630 100644 --- a/sdk/python/examples/controls/material/context_menu/triggers/main.py +++ b/sdk/python/examples/controls/material/context_menu/triggers/main.py @@ -4,7 +4,7 @@ async def main(page: ft.Page): # on web, disable default browser context menu if page.web: - await page.browser_context_menu.disable() + await ft.BrowserContextMenu().disable() def handle_item_click(e: ft.Event[ft.PopupMenuItem]): action = e.control.content diff --git a/sdk/python/packages/flet/src/flet/controls/page.py b/sdk/python/packages/flet/src/flet/controls/page.py index be0c3fb51e..db40cab504 100644 --- a/sdk/python/packages/flet/src/flet/controls/page.py +++ b/sdk/python/packages/flet/src/flet/controls/page.py @@ -853,23 +853,6 @@ def run_thread( partial(handler_with_context, *args, **kwargs), ) - @deprecated( - "Use push_route() instead.", - version="0.80.0", - delete_version="0.90.0", - show_parentheses=True, - ) - def go( - self, route: str, skip_route_change_event: bool = False, **kwargs: Any - ) -> None: - """ - A helper method that updates [`page.route`](#route), calls \ - [`page.on_route_change`](#on_route_change) event handler to update views and \ - finally calls `page.update()`. - """ - - asyncio.create_task(self.push_route(route, **kwargs)) - async def push_route(self, route: str, **kwargs: Any) -> None: """ Pushes a new navigation route to the browser history stack. @@ -1296,79 +1279,6 @@ def pubsub(self) -> "PubSubClient": """ return self.session.pubsub_client - @property - @deprecated( - reason="Use UrlLauncher() instead.", - docs_reason="Use :class:`~flet.UrlLauncher` instead.", - version="0.80.0", - delete_version="0.90.0", - ) - def url_launcher(self) -> UrlLauncher: - """ - The UrlLauncher service for the current page. - """ - return UrlLauncher() - - @property - @deprecated( - reason="Use BrowserContextMenu() instead.", - docs_reason="Use :class:`~flet.BrowserContextMenu` instead.", - version="0.80.0", - delete_version="0.90.0", - ) - def browser_context_menu(self): - """ - The BrowserContextMenu service for the current page. - """ - from flet.controls.services.browser_context_menu import BrowserContextMenu - - return BrowserContextMenu() - - @property - @deprecated( - reason="Use SharedPreferences() instead.", - docs_reason="Use :class:`~flet.SharedPreferences` instead.", - version="0.80.0", - delete_version="0.90.0", - ) - def shared_preferences(self): - """ - The SharedPreferences service for the current page. - """ - from flet.controls.services.shared_preferences import SharedPreferences - - return SharedPreferences() - - @property - @deprecated( - reason="Use Clipboard() instead.", - docs_reason="Use :class:`~flet.Clipboard` instead.", - version="0.80.0", - delete_version="0.90.0", - ) - def clipboard(self): - """ - The Clipboard service for the current page. - """ - from flet.controls.services.clipboard import Clipboard - - return Clipboard() - - @property - @deprecated( - reason="Use StoragePaths() instead.", - docs_reason="Use :class:`~flet.StoragePaths` instead.", - version="0.80.0", - delete_version="0.90.0", - ) - def storage_paths(self): - """ - The StoragePaths service for the current page. - """ - from flet.controls.services.storage_paths import StoragePaths - - return StoragePaths() - async def get_device_info(self) -> Optional[DeviceInfo]: """ Returns device information. From 76e33fa8e79ce5388ff9eff0ce431ed4364db6a3 Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Fri, 17 Jul 2026 18:59:46 +0200 Subject: [PATCH 04/11] Remove ConstrainedControl, ElevatedButton, DropdownM2, and deprecated 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 --- CHANGELOG.md | 4 + .../flet/lib/src/controls/dropdownm2.dart | 180 -------------- .../flet/lib/src/flet_core_extension.dart | 3 - .../line_chart_with_custom_axes/main.py | 2 +- sdk/python/packages/flet/src/flet/__init__.py | 12 - .../packages/flet/src/flet/controls/colors.py | 28 +-- .../flet/src/flet/controls/layout_control.py | 12 +- .../src/flet/controls/material/dropdownm2.py | 226 ------------------ .../flet/controls/material/elevated_button.py | 13 - .../controls/material/form_field_control.py | 3 +- website/docs/controls/dropdownm2.md | 8 - website/sidebars.yml | 1 - 12 files changed, 8 insertions(+), 484 deletions(-) delete mode 100644 packages/flet/lib/src/controls/dropdownm2.dart delete mode 100644 sdk/python/packages/flet/src/flet/controls/material/dropdownm2.py delete mode 100644 sdk/python/packages/flet/src/flet/controls/material/elevated_button.py delete mode 100644 website/docs/controls/dropdownm2.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c2e874157..c909f57d66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ * Remove the `--clear-cache` flag of `flet build` and `flet debug` (deprecated in `0.86.0`). Use the `flet clean` command instead ([#6233](https://github.com/flet-dev/flet/issues/6233)) by @ndonkoHenri. * Remove `Page.go()` (deprecated in `0.80.0`). Use `Page.push_route()` instead by @ndonkoHenri. * 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 corresponding service classes directly: `UrlLauncher()`, `BrowserContextMenu()`, `SharedPreferences()`, `Clipboard()`, `StoragePaths()` by @ndonkoHenri. +* Remove the `ConstrainedControl` base class (deprecated in `0.80.0`). Inherit from `LayoutControl` instead by @ndonkoHenri. +* Remove `ElevatedButton` (deprecated in `0.80.0`). Use `Button` instead by @ndonkoHenri. +* Remove `DropdownM2` and its `dropdownm2` module (deprecated in `0.84.0`). Use `Dropdown` instead by @ndonkoHenri. +* Remove the deprecated non-underscored `Colors` aliases (`BLACK12`, `BLACK26`, `BLACK38`, `BLACK45`, `BLACK54`, `BLACK87`, `WHITE10`, `WHITE12`, `WHITE24`, `WHITE30`, `WHITE38`, `WHITE54`, `WHITE60`, `WHITE70`). Use the underscored names instead (e.g. `Colors.BLACK_12`) by @ndonkoHenri. ## 0.86.1 diff --git a/packages/flet/lib/src/controls/dropdownm2.dart b/packages/flet/lib/src/controls/dropdownm2.dart deleted file mode 100644 index b1437a9b3a..0000000000 --- a/packages/flet/lib/src/controls/dropdownm2.dart +++ /dev/null @@ -1,180 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../extensions/control.dart'; -import '../models/control.dart'; -import '../utils/alignment.dart'; -import '../utils/borders.dart'; -import '../utils/colors.dart'; -import '../utils/edge_insets.dart'; -import '../utils/form_field.dart'; -import '../utils/layout.dart'; -import '../utils/numbers.dart'; -import '../utils/text.dart'; -import 'base_controls.dart'; - -class DropdownM2Control extends StatefulWidget { - final Control control; - - DropdownM2Control({Key? key, required this.control}) - : super(key: key ?? ValueKey("control_${control.id}")); - - @override - State createState() => _DropdownM2ControlState(); -} - -class _DropdownM2ControlState extends State { - String? _value; - bool _focused = false; - late final FocusNode _focusNode; - - @override - void initState() { - super.initState(); - _focusNode = FocusNode(); - _focusNode.addListener(_onFocusChange); - widget.control.addInvokeMethodListener(_invokeMethod); - } - - void _onFocusChange() { - setState(() { - _focused = _focusNode.hasFocus; - }); - widget.control.triggerEvent(_focusNode.hasFocus ? "focus" : "blur"); - } - - Future _invokeMethod(String name, dynamic args) async { - debugPrint("DropdownM2.$name($args)"); - switch (name) { - case "focus": - _focusNode.requestFocus(); - default: - throw Exception("Unknown DropdownM2 method: $name"); - } - } - - @override - void dispose() { - _focusNode.removeListener(_onFocusChange); - _focusNode.dispose(); - widget.control.removeInvokeMethodListener(_invokeMethod); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - debugPrint("DropdownM2 build: ${widget.control.id}"); - - var textSize = widget.control.getDouble("text_size"); - var color = widget.control.getColor("color", context); - var focusedColor = widget.control.getColor("focused_color", context); - - var textStyle = widget.control - .getTextStyle("text_style", Theme.of(context), const TextStyle())!; - - if (textSize != null) { - textStyle = textStyle.copyWith(fontSize: textSize); - } - - if (focusedColor != null) { - textStyle = textStyle.copyWith( - color: _focused ? focusedColor : (color ?? textStyle.color)); - } - - if (color != null) { - textStyle = textStyle.copyWith(color: color); - } - - if (textStyle.color == null) { - textStyle = - textStyle.copyWith(color: Theme.of(context).colorScheme.onSurface); - } - - var items = widget.control - .children("options") - .map>((Control item) { - item.notifyParent = true; - var textStyle = item.getTextStyle("text_style", Theme.of(context)); - if (item.disabled && textStyle != null) { - textStyle = textStyle.apply(color: Theme.of(context).disabledColor); - } - var value = - item.getString("key") ?? item.getString("text") ?? item.id.toString(); - var content = - item.buildWidget("content") ?? Text(value, style: textStyle); - var alignment = item.getAlignment("alignment"); - if (alignment != null) { - content = Container(alignment: alignment, child: content); - } - return DropdownMenuItem( - enabled: !item.disabled, - value: value, - alignment: alignment ?? AlignmentDirectional.centerStart, - onTap: !item.disabled ? () => item.triggerEvent("click") : null, - child: content); - }).toList(); - - String? value = widget.control.getString("value"); - if (_value != value) { - _value = value; - } - - if (items.where((item) => item.value == value).isEmpty) { - _value = null; - } - - Widget dropDown = DropdownButtonFormField( - style: textStyle, - autofocus: widget.control.getBool("autofocus", false)!, - focusNode: _focusNode, - initialValue: _value, - dropdownColor: widget.control.getColor("bgcolor", context), - enableFeedback: widget.control.getBool("enable_feedback"), - elevation: widget.control.getInt("elevation", 8)!, - padding: widget.control.getPadding("padding"), - itemHeight: widget.control.getDouble("item_height"), - menuMaxHeight: widget.control.getDouble("max_menu_height"), - iconEnabledColor: - widget.control.getColor("select_icon_enabled_color", context), - iconDisabledColor: - widget.control.getColor("select_icon_disabled_color", context), - iconSize: widget.control.getDouble("select_icon_size", 24.0)!, - borderRadius: widget.control.getBorderRadius("border_radius"), - alignment: widget.control.getAlignment("alignment") ?? - AlignmentDirectional.centerStart, - isExpanded: widget.control.getBool("options_fill_horizontally", true)!, - icon: widget.control.buildIconOrWidget("select_icon"), - hint: widget.control.buildWidget("hint"), - disabledHint: widget.control.buildWidget("disabled_hint"), - decoration: buildInputDecoration(context, widget.control, - customSuffix: null, focused: _focused), - onTap: !widget.control.disabled - ? () => widget.control.triggerEvent("click") - : null, - onChanged: widget.control.disabled - ? null - : (String? value) { - _value = value!; - widget.control.updateProperties({"value": value}); - widget.control.triggerEvent("change", value); - }, - items: items, - ); - - if (widget.control.getExpand("expand", 0)! > 0) { - return LayoutControl(control: widget.control, child: dropDown); - } else { - return LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - if (constraints.maxWidth == double.infinity && - widget.control.getDouble("width") == null) { - dropDown = ConstrainedBox( - constraints: const BoxConstraints.tightFor(width: 300), - child: dropDown); - } - - return LayoutControl(control: widget.control, child: dropDown); - }, - ); - } - } -} diff --git a/packages/flet/lib/src/flet_core_extension.dart b/packages/flet/lib/src/flet_core_extension.dart index 9bb0d0232b..6f64f6ffbf 100644 --- a/packages/flet/lib/src/flet_core_extension.dart +++ b/packages/flet/lib/src/flet_core_extension.dart @@ -51,7 +51,6 @@ import 'controls/divider.dart'; import 'controls/drag_target.dart'; import 'controls/draggable.dart'; import 'controls/dropdown.dart'; -import 'controls/dropdownm2.dart'; import 'controls/expansion_panel.dart'; import 'controls/expansion_tile.dart'; import 'controls/flet_app_control.dart'; @@ -253,8 +252,6 @@ class FletCoreExtension extends FletExtension { return DraggableControl(key: key, control: control); case "Dropdown": return DropdownControl(key: key, control: control); - case "DropdownM2": - return DropdownM2Control(key: key, control: control); case "ExpansionPanelList": return ExpansionPanelListControl(key: key, control: control); case "ExpansionTile": diff --git a/sdk/python/examples/extensions/charts/line_chart/line_chart_with_custom_axes/main.py b/sdk/python/examples/extensions/charts/line_chart/line_chart_with_custom_axes/main.py index 839d384228..426227f275 100644 --- a/sdk/python/examples/extensions/charts/line_chart/line_chart_with_custom_axes/main.py +++ b/sdk/python/examples/extensions/charts/line_chart/line_chart_with_custom_axes/main.py @@ -123,7 +123,7 @@ def main(page: ft.Page): ), ) - def toggle_data(e: ft.Event[ft.ElevatedButton]): + def toggle_data(e: ft.Event[ft.Button]): if state.toggled: chart.data_series = data_2 chart.interactive = False diff --git a/sdk/python/packages/flet/src/flet/__init__.py b/sdk/python/packages/flet/src/flet/__init__.py index c534e26a23..d39e06b2f2 100644 --- a/sdk/python/packages/flet/src/flet/__init__.py +++ b/sdk/python/packages/flet/src/flet/__init__.py @@ -334,7 +334,6 @@ ValueKey, ) from flet.controls.layout_control import ( - ConstrainedControl, LayoutControl, LayoutSizeChangeEvent, ) @@ -344,7 +343,6 @@ ) from flet.controls.material import ( dropdown, - dropdownm2, icons, ) from flet.controls.material.alert_dialog import AlertDialog @@ -395,8 +393,6 @@ Dropdown, DropdownOption, ) - from flet.controls.material.dropdownm2 import DropdownM2 - from flet.controls.material.elevated_button import ElevatedButton from flet.controls.material.expansion_panel import ( ExpansionPanel, ExpansionPanelList, @@ -819,7 +815,6 @@ "Connectivity", "ConnectivityChangeEvent", "ConnectivityType", - "ConstrainedControl", "Container", "Context", "ContextMenu", @@ -900,12 +895,10 @@ "DragWillAcceptEvent", "Draggable", "Dropdown", - "DropdownM2", "DropdownOption", "DropdownTheme", "Duration", "DurationValue", - "ElevatedButton", "Event", "EventControlType", "EventHandler", @@ -1233,7 +1226,6 @@ "cupertino_colors", "cupertino_icons", "dropdown", - "dropdownm2", "icons", "is_route_active", "margin", @@ -1353,7 +1345,6 @@ "Connectivity": "flet.controls.services.connectivity", "ConnectivityChangeEvent": "flet.controls.services.connectivity", "ConnectivityType": "flet.controls.services.connectivity", - "ConstrainedControl": "flet.controls.layout_control", "Container": "flet.controls.material.container", "Context": "flet.controls.context", "ContextMenu": "flet.controls.material.context_menu", @@ -1434,12 +1425,10 @@ "DragWillAcceptEvent": "flet.controls.core.drag_target", "Draggable": "flet.controls.core.draggable", "Dropdown": "flet.controls.material.dropdown", - "DropdownM2": "flet.controls.material.dropdownm2", "DropdownOption": "flet.controls.material.dropdown", "DropdownTheme": "flet.controls.theme", "Duration": "flet.controls.duration", "DurationValue": "flet.controls.duration", - "ElevatedButton": "flet.controls.material.elevated_button", "Event": "flet.controls.control_event", "EventControlType": "flet.controls.control_event", "EventHandler": "flet.controls.control_event", @@ -1766,7 +1755,6 @@ "cupertino_colors": "flet.controls.cupertino", "cupertino_icons": "flet.controls.cupertino", "dropdown": "flet.controls.material", - "dropdownm2": "flet.controls.material", "icons": "flet.controls.material", "is_route_active": "flet.components.router", "margin": "flet.controls", diff --git a/sdk/python/packages/flet/src/flet/controls/colors.py b/sdk/python/packages/flet/src/flet/controls/colors.py index fbddce30ca..8e87f82c7e 100644 --- a/sdk/python/packages/flet/src/flet/controls/colors.py +++ b/sdk/python/packages/flet/src/flet/controls/colors.py @@ -55,15 +55,13 @@ from enum import Enum from typing import TYPE_CHECKING, Optional, Union -from flet.utils.deprecated_enum import DeprecatedEnumMeta - if TYPE_CHECKING: from flet.controls.types import ColorValue __all__ = ["Colors"] -class Colors(str, Enum, metaclass=DeprecatedEnumMeta): +class Colors(str, Enum): """ Named Material colors. """ @@ -493,27 +491,3 @@ def with_opacity(opacity: Union[int, float], color: "ColorValue") -> str: YELLOW_ACCENT_200 = "yellowaccent200" YELLOW_ACCENT_400 = "yellowaccent400" YELLOW_ACCENT_700 = "yellowaccent700" - - -# TODO - remove in Flet 1.0 -_DEPRECATED_COLOR_ALIASES = { - "BLACK12": ("BLACK_12", "Use Colors.BLACK_12 instead."), - "BLACK26": ("BLACK_26", "Use Colors.BLACK_26 instead."), - "BLACK38": ("BLACK_38", "Use Colors.BLACK_38 instead."), - "BLACK45": ("BLACK_45", "Use Colors.BLACK_45 instead."), - "BLACK54": ("BLACK_54", "Use Colors.BLACK_54 instead."), - "BLACK87": ("BLACK_87", "Use Colors.BLACK_87 instead."), - "WHITE10": ("WHITE_10", "Use Colors.WHITE_10 instead."), - "WHITE12": ("WHITE_12", "Use Colors.WHITE_12 instead."), - "WHITE24": ("WHITE_24", "Use Colors.WHITE_24 instead."), - "WHITE30": ("WHITE_30", "Use Colors.WHITE_30 instead."), - "WHITE38": ("WHITE_38", "Use Colors.WHITE_38 instead."), - "WHITE54": ("WHITE_54", "Use Colors.WHITE_54 instead."), - "WHITE60": ("WHITE_60", "Use Colors.WHITE_60 instead."), - "WHITE70": ("WHITE_70", "Use Colors.WHITE_70 instead."), -} - -Colors._deprecated_members_ = _DEPRECATED_COLOR_ALIASES - -for alias_name, (target_name, _) in _DEPRECATED_COLOR_ALIASES.items(): - Colors._member_map_[alias_name] = getattr(Colors, target_name) diff --git a/sdk/python/packages/flet/src/flet/controls/layout_control.py b/sdk/python/packages/flet/src/flet/controls/layout_control.py index 6af296eb1f..46174e52bc 100644 --- a/sdk/python/packages/flet/src/flet/controls/layout_control.py +++ b/sdk/python/packages/flet/src/flet/controls/layout_control.py @@ -20,9 +20,8 @@ Transform, ) from flet.controls.types import Number -from flet.utils import deprecated_class -__all__ = ["ConstrainedControl", "LayoutControl", "LayoutSizeChangeEvent"] +__all__ = ["LayoutControl", "LayoutSizeChangeEvent"] @dataclass @@ -319,12 +318,3 @@ def main(page: ft.Page): More information [here](https://flet.dev/docs/cookbook/animations). """ - - -@deprecated_class( - reason="Inherit from LayoutControl instead.", - version="0.80.0", - delete_version="1.0", -) -class ConstrainedControl(LayoutControl): - pass diff --git a/sdk/python/packages/flet/src/flet/controls/material/dropdownm2.py b/sdk/python/packages/flet/src/flet/controls/material/dropdownm2.py deleted file mode 100644 index 52da53640f..0000000000 --- a/sdk/python/packages/flet/src/flet/controls/material/dropdownm2.py +++ /dev/null @@ -1,226 +0,0 @@ -from typing import Optional - -from flet.controls.alignment import Alignment -from flet.controls.base_control import control -from flet.controls.control import Control -from flet.controls.control_event import ControlEventHandler -from flet.controls.material.form_field_control import FormFieldControl -from flet.controls.padding import PaddingValue -from flet.controls.text_style import TextStyle -from flet.controls.types import ( - ColorValue, - IconDataOrControl, - Number, -) -from flet.utils.deprecated import deprecated_class -from flet.utils.validation import V, ValidationRules - -__all__ = ["DropdownM2", "Option"] - - -@control("Option") -class Option(Control): - """ - Represents an item in a dropdown. - """ - - key: Optional[str] = None - """ - Option's key. - - If not specified :attr:`text` will be used as fallback. - - Raises: - ValueError: If neither `key` nor :attr:`text` is provided. - """ - - text: Optional[str] = None - """ - Option's display text. - - If not specified :attr:`key` will be used as fallback. - - Raises: - ValueError: If neither :attr:`key` nor `text` is provided. - """ - - content: Optional[Control] = None - """ - A `Control` to display in this option. If not specified, `text` will be used as \ - fallback, else `text` will be ignored. - """ - - alignment: Optional[Alignment] = None - """ - Defines the alignment of this option in it's container. - - Defaults to `Alignment.center_left()`. - """ - - text_style: Optional[TextStyle] = None - """ - Defines the style of the `text`. - """ - - on_click: Optional[ControlEventHandler["Option"]] = None - """ - Called when this option is clicked. - """ - - __validation_rules__: ValidationRules = ( - V.ensure( - lambda ctrl: ctrl.key is not None or ctrl.text is not None, - message="key or text must be specified", - ), - ) - - -@deprecated_class( - reason="Use Dropdown instead.", - docs_reason="Use [`Dropdown`][flet.Dropdown] instead.", - version="0.84.0", - delete_version="1.0", -) -@control("DropdownM2") -class DropdownM2(FormFieldControl): - """ - A dropdown lets the user select from a number of items. The dropdown shows the \ - currently selected item as well as an arrow that opens a menu for selecting \ - another item. - - Example: - ```python - ft.DropdownM2( - width=220, - value="Alice", - options=[ - ft.dropdownm2.Option(key="Alice", text="Alice"), - ft.dropdownm2.Option(key="Bob", text="Bob"), - ], - ) - ``` - """ - - value: Optional[str] = None - """ - `key` value of the selected option. - """ - - options: Optional[list[Option]] = None - """ - A list of `Option` controls representing items in this dropdown. - """ - - alignment: Optional[Alignment] = None - """ - Defines how the `hint` or the selected item is positioned within this dropdown. - """ - - autofocus: bool = False - """ - True if the control will be selected as the initial focus. If there is more than \ - one control on a page with autofocus set, then the first one added to the page \ - will get focus. - """ - - hint_content: Optional[Control] = None - """ - A placeholder `Control` for the dropdown's value that is displayed when `value` is \ - `None`. - """ - - select_icon: Optional[IconDataOrControl] = None - """ - The [name of the icon](https://flet.dev/docs/types/icons) or `Control` to use \ - for the drop-down select button's icon. - - Defaults to `Icon(ft.Icons.ARROW_DROP_DOWN)`. - """ - - elevation: Number = 8 - """ - The dropdown's elevation. - """ - - item_height: Optional[Number] = None - """ - The height of the items/options in the dropdown menu. - """ - - max_menu_height: Optional[Number] = None - """ - The maximum height of the dropdown menu. - """ - - select_icon_size: Number = 24.0 - """ - The size of the icon button which wraps `select_icon`. - """ - - enable_feedback: Optional[bool] = None - """ - Whether detected gestures should provide acoustic and/or haptic feedback. On \ - Android, for example, setting this to `True` produce a click sound and a \ - long-press will produce a short vibration. - """ - - padding: Optional[PaddingValue] = None - """ - The padding around the visible portion of this dropdown. - """ - - select_icon_enabled_color: Optional[ColorValue] = None - """ - The color of any `Icon` descendant of `select_icon` if this button is enabled. - """ - - select_icon_disabled_color: Optional[ColorValue] = None - """ - The color of any `Icon` descendant of `select_icon` if this button is disabled. - """ - - options_fill_horizontally: bool = True - """ - Whether the dropdown's inner contents to horizontally fill its parent. - By default this button's inner width is the minimum size of its content. - - If `True`, the inner width is expanded to fill its surrounding container. - """ - - disabled_hint_content: Optional[Control] = None - """ - A placeholder `Control` for the dropdown's value that is displayed when `value` is \ - `None` and the dropdown is disabled. - """ - - on_change: Optional[ControlEventHandler["DropdownM2"]] = None - """ - Called when the selected item of this dropdown has changed. - """ - - on_focus: Optional[ControlEventHandler["DropdownM2"]] = None - """ - Called when the control has received focus. - """ - - on_blur: Optional[ControlEventHandler["DropdownM2"]] = None - """ - Called when the control has lost focus. - """ - - on_click: Optional[ControlEventHandler["DropdownM2"]] = None - """ - Called when this dropdown is clicked. - """ - - def before_update(self): - super().before_update() - if ( - self.bgcolor is not None - or self.fill_color is not None - or self.focused_bgcolor is not None - ) and self.filled is None: - self.filled = True # required to display any of the above colors - - def __contains__(self, item): - return item in self.options diff --git a/sdk/python/packages/flet/src/flet/controls/material/elevated_button.py b/sdk/python/packages/flet/src/flet/controls/material/elevated_button.py deleted file mode 100644 index 18706db87d..0000000000 --- a/sdk/python/packages/flet/src/flet/controls/material/elevated_button.py +++ /dev/null @@ -1,13 +0,0 @@ -from flet.controls.material.button import Button -from flet.utils.deprecated import deprecated_class - -__all__ = ["ElevatedButton"] - - -@deprecated_class( - reason="Use Button instead.", - version="0.80.0", - delete_version="1.0", -) -class ElevatedButton(Button): - pass diff --git a/sdk/python/packages/flet/src/flet/controls/material/form_field_control.py b/sdk/python/packages/flet/src/flet/controls/material/form_field_control.py index d4a5271476..0005b217af 100644 --- a/sdk/python/packages/flet/src/flet/controls/material/form_field_control.py +++ b/sdk/python/packages/flet/src/flet/controls/material/form_field_control.py @@ -46,8 +46,7 @@ class FormFieldControl(LayoutControl): Base class for Material form-field controls with a decorated input area. It provides the shared label, hint, helper, error, prefix, suffix, fill, and - border properties used by controls such as :class:`~flet.TextField` and - :class:`~flet.DropdownM2`. + border properties used by controls such as :class:`~flet.TextField`. """ text_size: Optional[Number] = None diff --git a/website/docs/controls/dropdownm2.md b/website/docs/controls/dropdownm2.md deleted file mode 100644 index e55db7ff94..0000000000 --- a/website/docs/controls/dropdownm2.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -class_name: "flet.DropdownM2" -title: "DropdownM2" ---- - -import {ClassAll} from '@site/src/components/crocodocs'; - - diff --git a/website/sidebars.yml b/website/sidebars.yml index 206c97b79d..a1bb7d67a5 100644 --- a/website/sidebars.yml +++ b/website/sidebars.yml @@ -195,7 +195,6 @@ docs: Dropdown: _index: controls/dropdown/index.md DropdownOption: controls/dropdownoption.md - DropdownM2: controls/dropdownm2.md ExpansionPanel: controls/expansionpanel.md ExpansionPanelList: controls/expansionpanellist.md ExpansionTile: controls/expansiontile.md From 2090c23da5c6ea99ac0bc4a934f415960a923056 Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Fri, 17 Jul 2026 19:25:53 +0200 Subject: [PATCH 05/11] Remove remaining no-removal-version deprecations for a deprecation-free 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) --- CHANGELOG.md | 5 ++ packages/flet/lib/src/utils/widget_state.dart | 5 -- .../markdown/code_syntax_highlight/main.py | 2 +- .../controls/core/markdown/listviews/main.py | 2 +- .../controls/core/markdown/markdown/main.py | 2 +- .../audio_recorder/audio_recorder/main.py | 2 +- .../extensions/map/camera_controls/main.py | 2 +- .../extensions/map/idle_camera/main.py | 2 +- .../extensions/map/interaction_flags/main.py | 2 +- .../extensions/map/multi_layers/main.py | 2 +- .../src/flet_cli/commands/build_base.py | 21 ----- sdk/python/packages/flet/src/flet/__init__.py | 6 -- sdk/python/packages/flet/src/flet/app.py | 45 ++--------- .../packages/flet/src/flet/controls/page.py | 81 ------------------- website/docs/cookbook/authentication.md | 4 +- 15 files changed, 22 insertions(+), 161 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c909f57d66..96fa3d05ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,11 @@ * Remove `ElevatedButton` (deprecated in `0.80.0`). Use `Button` instead by @ndonkoHenri. * Remove `DropdownM2` and its `dropdownm2` module (deprecated in `0.84.0`). Use `Dropdown` instead by @ndonkoHenri. * Remove the deprecated non-underscored `Colors` aliases (`BLACK12`, `BLACK26`, `BLACK38`, `BLACK45`, `BLACK54`, `BLACK87`, `WHITE10`, `WHITE12`, `WHITE24`, `WHITE30`, `WHITE38`, `WHITE54`, `WHITE60`, `WHITE70`). Use the underscored names instead (e.g. `Colors.BLACK_12`) by @ndonkoHenri. +* Remove `app()` and `app_async()` (deprecated in `0.80.0`). Use `run()` and `run_async()` instead by @ndonkoHenri. +* Remove the `target` parameter of `run()` and `run_async()` (deprecated alias for `main`). Pass `main` instead by @ndonkoHenri. +* Remove `Page.launch_url()`, `Page.can_launch_url()`, and `Page.close_in_app_web_view()` (deprecated in `0.90.0`). Use `UrlLauncher().launch_url()` / `.can_launch_url()` / `.close_in_app_web_view()` instead by @ndonkoHenri. +* Remove the legacy `[tool.flet.app.boot_screen]` / `[tool.flet.app.startup_screen]` build-config fallback. Use `[tool.flet.boot_screen]` with a named screen instead by @ndonkoHenri. +* Remove the Dart empty-string (`""`) widget-state key back-compat mapping. Use `"default"` (or `ControlState.DEFAULT`) instead by @ndonkoHenri. ## 0.86.1 diff --git a/packages/flet/lib/src/utils/widget_state.dart b/packages/flet/lib/src/utils/widget_state.dart index 616ca81bed..c25307a79f 100644 --- a/packages/flet/lib/src/utils/widget_state.dart +++ b/packages/flet/lib/src/utils/widget_state.dart @@ -12,9 +12,6 @@ WidgetStateProperty? getWidgetStateProperty( if (j is! Map || j.isEmpty) { j = {"default": j}; } - if (j.containsKey("")) { - j["default"] = j.remove(""); - } if (!j.keys.every( (k) => k == "default" || WidgetState.values.any((v) => v.name == k))) { // wrap into another dict @@ -35,8 +32,6 @@ class WidgetStateFromJSON extends WidgetStateProperty { _states = LinkedHashMap.from( jsonDictValue?.map((k, v) { var key = k.trim().toLowerCase(); - // "" is deprecated and renamed to "default" - if (key == "") key = "default"; return MapEntry(key, converterFromJson(v)); }) ?? {}, diff --git a/sdk/python/examples/controls/core/markdown/code_syntax_highlight/main.py b/sdk/python/examples/controls/core/markdown/code_syntax_highlight/main.py index 7c836b9c83..9d0656d22d 100644 --- a/sdk/python/examples/controls/core/markdown/code_syntax_highlight/main.py +++ b/sdk/python/examples/controls/core/markdown/code_syntax_highlight/main.py @@ -159,7 +159,7 @@ def main(page: ft.Page): } async def navigate_md_link(e: ft.Event[ft.Markdown]): - await page.launch_url(e.data) + await ft.UrlLauncher().launch_url(e.data) page.add( ft.SafeArea( diff --git a/sdk/python/examples/controls/core/markdown/listviews/main.py b/sdk/python/examples/controls/core/markdown/listviews/main.py index 119a5905b4..d2e4da81fe 100644 --- a/sdk/python/examples/controls/core/markdown/listviews/main.py +++ b/sdk/python/examples/controls/core/markdown/listviews/main.py @@ -121,7 +121,7 @@ def main(page: ft.Page): async def navigate_md_link(e: ft.Event[ft.Markdown]): - await page.launch_url(e.data) + await ft.UrlLauncher().launch_url(e.data) page.add( ft.SafeArea( diff --git a/sdk/python/examples/controls/core/markdown/markdown/main.py b/sdk/python/examples/controls/core/markdown/markdown/main.py index 075fc15c35..1ceb6fcdc9 100644 --- a/sdk/python/examples/controls/core/markdown/markdown/main.py +++ b/sdk/python/examples/controls/core/markdown/markdown/main.py @@ -80,7 +80,7 @@ def main(page: ft.Page): page.scroll = ft.ScrollMode.AUTO async def handle_link_tap(e: ft.Event[ft.Markdown]): - await page.launch_url(e.data) + await ft.UrlLauncher().launch_url(e.data) page.add( ft.SafeArea( diff --git a/sdk/python/examples/extensions/audio_recorder/audio_recorder/main.py b/sdk/python/examples/extensions/audio_recorder/audio_recorder/main.py index c2d4b8b5bb..a0310c503f 100644 --- a/sdk/python/examples/extensions/audio_recorder/audio_recorder/main.py +++ b/sdk/python/examples/extensions/audio_recorder/audio_recorder/main.py @@ -19,7 +19,7 @@ async def handle_recording_stop(e: ft.Event[ft.Button]): output_path = await recorder.stop_recording() show_snackbar(f"Stopped recording. Output Path: {output_path}") if page.web and output_path is not None: - await page.launch_url(output_path) + await ft.UrlLauncher().launch_url(output_path) async def handle_list_devices(e: ft.Event[ft.Button]): o = await recorder.get_input_devices() diff --git a/sdk/python/examples/extensions/map/camera_controls/main.py b/sdk/python/examples/extensions/map/camera_controls/main.py index da1886e17f..e44875ced1 100644 --- a/sdk/python/examples/extensions/map/camera_controls/main.py +++ b/sdk/python/examples/extensions/map/camera_controls/main.py @@ -81,7 +81,7 @@ async def set_world_zoom(e: ft.Event[ft.Button]): ), ftm.SimpleAttribution( text="OpenStreetMap contributors", - on_click=lambda e: e.page.launch_url( + on_click=lambda e: ft.UrlLauncher().launch_url( "https://www.openstreetmap.org/copyright" ), ), diff --git a/sdk/python/examples/extensions/map/idle_camera/main.py b/sdk/python/examples/extensions/map/idle_camera/main.py index d2c383beb6..310bdbb4bb 100644 --- a/sdk/python/examples/extensions/map/idle_camera/main.py +++ b/sdk/python/examples/extensions/map/idle_camera/main.py @@ -68,7 +68,7 @@ async def handle_map_event(e: ftm.MapEvent): ), ftm.SimpleAttribution( text="OpenStreetMap contributors", - on_click=lambda e: e.page.launch_url( + on_click=lambda e: ft.UrlLauncher().launch_url( "https://www.openstreetmap.org/copyright" ), ), diff --git a/sdk/python/examples/extensions/map/interaction_flags/main.py b/sdk/python/examples/extensions/map/interaction_flags/main.py index 580b8914c5..a668c8a723 100644 --- a/sdk/python/examples/extensions/map/interaction_flags/main.py +++ b/sdk/python/examples/extensions/map/interaction_flags/main.py @@ -62,7 +62,7 @@ def handle_map_event(e: ftm.MapEvent): ), ftm.SimpleAttribution( text="OpenStreetMap contributors", - on_click=lambda e: e.page.launch_url( + on_click=lambda e: ft.UrlLauncher().launch_url( "https://www.openstreetmap.org/copyright" ), ), diff --git a/sdk/python/examples/extensions/map/multi_layers/main.py b/sdk/python/examples/extensions/map/multi_layers/main.py index e79263637b..2c84a67923 100644 --- a/sdk/python/examples/extensions/map/multi_layers/main.py +++ b/sdk/python/examples/extensions/map/multi_layers/main.py @@ -56,7 +56,7 @@ def handle_tap(e: ftm.MapTapEvent): ), ftm.SimpleAttribution( text="OpenStreetMap contributors", - on_click=lambda e: e.page.launch_url( + on_click=lambda e: ft.UrlLauncher().launch_url( "https://www.openstreetmap.org/copyright" ), ), diff --git a/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py b/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py index 1305894051..f5434969c3 100644 --- a/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py +++ b/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py @@ -1393,29 +1393,8 @@ def merged(key): name = boot_screen.get("name", "flet") options = boot_screen.get(name) or {} else: - # backward compatibility with the legacy app.boot_screen / - # app.startup_screen settings name = "flet" options = {} - legacy_boot = merged("app.boot_screen") - legacy_startup = merged("app.startup_screen") - if legacy_boot or legacy_startup: - console.log( - "[tool.flet.app.boot_screen] and " - "[tool.flet.app.startup_screen] are deprecated; use " - "[tool.flet.boot_screen] with a named screen instead.", - style=warning_style, - ) - if legacy_boot.get("show"): - options["spinner_size"] = 30 - message = legacy_boot.get("message") - if message: - options["prepare_message"] = message - if legacy_startup.get("show"): - options["spinner_size"] = 30 - message = legacy_startup.get("message") - if message: - options["startup_message"] = message return { "name": name, diff --git a/sdk/python/packages/flet/src/flet/__init__.py b/sdk/python/packages/flet/src/flet/__init__.py index d39e06b2f2..f953080611 100644 --- a/sdk/python/packages/flet/src/flet/__init__.py +++ b/sdk/python/packages/flet/src/flet/__init__.py @@ -9,8 +9,6 @@ if TYPE_CHECKING: from flet.app import ( AppCallable, - app, - app_async, run, run_async, ) @@ -1215,8 +1213,6 @@ "WindowsDeviceInfo", "__version__", "alignment", - "app", - "app_async", "border", "border_radius", "component", @@ -1744,8 +1740,6 @@ "WindowResizeEdge": "flet.controls.core.window", "WindowsDeviceInfo": "flet.controls.device_info", "alignment": "flet.controls", - "app": "flet.app", - "app_async": "flet.app", "border": "flet.controls", "border_radius": "flet.controls", "component": "flet.components.component_decorator", diff --git a/sdk/python/packages/flet/src/flet/app.py b/sdk/python/packages/flet/src/flet/app.py index 1c6a82762b..8ec817aa87 100644 --- a/sdk/python/packages/flet/src/flet/app.py +++ b/sdk/python/packages/flet/src/flet/app.py @@ -23,7 +23,6 @@ is_pyodide, open_in_browser, ) -from flet.utils.deprecated import deprecated from flet.utils.pip import ( ensure_flet_desktop_package_installed, ensure_flet_web_package_installed, @@ -41,32 +40,6 @@ """ -@deprecated( - "Use run() instead.", - docs_reason="Use [`run()`][flet.run] instead.", - version="0.80.0", - show_parentheses=True, -) -def app(*args, **kwargs): - new_args = list(args) - if "target" in kwargs: - new_args.insert(0, kwargs["target"]) - return run(*new_args, **kwargs) - - -@deprecated( - "Use run_async() instead.", - docs_reason="Use [`run_async()`][flet.run_async] instead.", - version="0.80.0", - show_parentheses=True, -) -def app_async(*args, **kwargs): - new_args = list(args) - if "target" in kwargs: - new_args.insert(0, kwargs["target"]) - return run_async(*new_args, **kwargs) - - def run( main: AppCallable, before_main: Optional[AppCallable] = None, @@ -80,7 +53,6 @@ def run( route_url_strategy: RouteUrlStrategy = RouteUrlStrategy.PATH, no_cdn: Optional[bool] = False, export_asgi_app: Optional[bool] = False, - target=None, ): """ Runs the Flet app. @@ -101,14 +73,13 @@ def run( no_cdn: Whether not load CanvasKit, Pyodide, or fonts from CDN. export_asgi_app: If `True`, returns a configured ASGI app instead of running an event loop. - target: Deprecated alias for `main`. Returns: A FastAPI ASGI app when `export_asgi_app=True`. Otherwise, runs the app and returns `None`. """ if is_pyodide(): - __run_pyodide(main=main or target, before_main=before_main) + __run_pyodide(main=main, before_main=before_main) return if export_asgi_app: @@ -116,7 +87,7 @@ def run( from flet_web.fastapi.serve_fastapi_web_app import get_fastapi_web_app return get_fastapi_web_app( - main=main or target, + main=main, before_main=before_main, page_name=__get_page_name(name), assets_dir=__get_assets_dir_path(assets_dir, relative_to_cwd=True), @@ -134,7 +105,7 @@ def run( return asyncio.run( run_async( - main=main or target, + main=main, before_main=before_main, name=name, host=host, @@ -161,7 +132,6 @@ async def run_async( web_renderer: WebRenderer = WebRenderer.AUTO, route_url_strategy: RouteUrlStrategy = RouteUrlStrategy.PATH, no_cdn: Optional[bool] = False, - target=None, ): """ Asynchronously run a Flet app using socket or web server transport. @@ -179,11 +149,10 @@ async def run_async( web_renderer: Web renderer type for web-hosted mode. route_url_strategy: Route URL strategy (`path` or `hash`). no_cdn: Whether to avoid loading CanvasKit, Pyodide, and fonts from CDN. - target: Deprecated alias for `main`. """ if is_pyodide(): - __run_pyodide(main=main or target, before_main=before_main) + __run_pyodide(main=main, before_main=before_main) return if isinstance(view, str): @@ -270,19 +239,19 @@ def exit_gracefully(signum, frame): if is_embedded() and bridge_port_env: conn = await __run_dart_bridge_server( port=int(bridge_port_env), - main=main or target, + main=main, before_main=before_main, ) elif is_socket_server: conn = await __run_socket_server( port=port, - main=main or target, + main=main, before_main=before_main, blocking=is_embedded(), ) else: conn = await __run_web_server( - main=main or target, + main=main, before_main=before_main, host=host, port=port, diff --git a/sdk/python/packages/flet/src/flet/controls/page.py b/sdk/python/packages/flet/src/flet/controls/page.py index db40cab504..52a5d2ecb5 100644 --- a/sdk/python/packages/flet/src/flet/controls/page.py +++ b/sdk/python/packages/flet/src/flet/controls/page.py @@ -15,7 +15,6 @@ Optional, ParamSpec, TypeVar, - Union, ) from urllib.parse import urlparse @@ -53,12 +52,9 @@ DeviceOrientation, Locale, PagePlatform, - Url, - UrlTarget, Wrapper, ) from flet.utils import is_pyodide -from flet.utils.deprecated import deprecated from flet.utils.from_dict import from_dict from flet.utils.strings import random_string @@ -1144,83 +1140,6 @@ def logout(self) -> None: if self.on_logout: asyncio.create_task(self._trigger_event("logout", event_data=None, e=e)) - @deprecated( - "Use UrlLauncher().launch_url() instead.", - version="0.90.0", - show_parentheses=True, - ) - async def launch_url( - self, - url: Union[str, Url], - *, - web_popup_window_name: Optional[Union[str, UrlTarget]] = None, - web_popup_window: bool = False, - web_popup_window_width: Optional[int] = None, - web_popup_window_height: Optional[int] = None, - ) -> None: - """ - Opens a web browser or popup window to a given `url`. - - Args: - url: The URL to open. - web_popup_window_name: Window tab/name to open URL in. Use - :attr:`flet.UrlTarget.SELF` for the same browser tab, - :attr:`flet.UrlTarget.BLANK` for a new browser tab (or in external - application on a mobile device), or a custom name for a named tab. - web_popup_window: Display the URL in a browser popup window. - web_popup_window_width: Popup window width. - web_popup_window_height: Popup window height. - """ - if web_popup_window: - await UrlLauncher().open_window( - url, - title=web_popup_window_name, - width=web_popup_window_width, - height=web_popup_window_height, - ) - else: - await UrlLauncher().launch_url(url) - - @deprecated( - "Use UrlLauncher().can_launch_url() instead.", - version="0.90.0", - show_parentheses=True, - ) - async def can_launch_url(self, url: str) -> bool: - """ - Checks whether the specified URL can be handled by some app installed on the \ - device. - - Args: - url: The URL to check. - - Returns: - `True` if it is possible to verify that there is a handler available. - `False` if there is no handler available, or the application does not - have permission to check. For example: - - - On recent versions of Android and iOS, this will always return `False` - unless the application has been configuration to allow querying the - system for launch support. - - In web mode, this will always return `False` except for a few specific - schemes that are always assumed to be supported (such as http(s)), - as web pages are never allowed to query installed applications. - """ - return await UrlLauncher().can_launch_url(url) - - @deprecated( - "Use UrlLauncher().close_in_app_web_view() instead.", - version="0.90.0", - show_parentheses=True, - ) - async def close_in_app_web_view(self) -> None: - """ - Closes in-app web view opened with `launch_url()`. - - 📱 Mobile only. - """ - await UrlLauncher().close_in_app_web_view() - @property def session(self) -> "Session": """ diff --git a/website/docs/cookbook/authentication.md b/website/docs/cookbook/authentication.md index 29e73dd5bd..cf3b704531 100644 --- a/website/docs/cookbook/authentication.md +++ b/website/docs/cookbook/authentication.md @@ -392,7 +392,7 @@ You can also change web app to open provider's authorization page in the same ta ```python page.login( provider, - on_open_authorization_url=lambda url: asyncio.create_task(page.launch_url(url, web_window_name="_self")), + on_open_authorization_url=lambda url: asyncio.create_task(ft.UrlLauncher().launch_url(url, web_only_window_name="_self")), redirect_to_page=True ) ``` @@ -402,7 +402,7 @@ To open flow in a new tab (notice `_self` replaced with `_blank`): ```python page.login( provider, - on_open_authorization_url=lambda url: asyncio.create_task(page.launch_url(url, web_window_name="_blank")) + on_open_authorization_url=lambda url: asyncio.create_task(ft.UrlLauncher().launch_url(url, web_only_window_name="_blank")) ) ``` From eaf1a7fe83d5075658a9a08dce7ef9d3d92ab927 Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Sat, 18 Jul 2026 12:46:13 +0200 Subject: [PATCH 06/11] Restore DropdownM2 as a non-deprecated control Reverses the DropdownM2 removal from 76e33fa8e 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. --- CHANGELOG.md | 5 +- .../flet/lib/src/controls/dropdownm2.dart | 180 ++++++++++++++ .../flet/lib/src/flet_core_extension.dart | 3 + sdk/python/packages/flet/src/flet/__init__.py | 6 + .../src/flet/controls/material/dropdownm2.py | 219 ++++++++++++++++++ .../controls/material/form_field_control.py | 3 +- website/docs/controls/dropdownm2.md | 8 + website/sidebars.yml | 1 + 8 files changed, 423 insertions(+), 2 deletions(-) create mode 100644 packages/flet/lib/src/controls/dropdownm2.dart create mode 100644 sdk/python/packages/flet/src/flet/controls/material/dropdownm2.py create mode 100644 website/docs/controls/dropdownm2.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 96fa3d05ce..809d4aad56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,6 @@ * 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 corresponding service classes directly: `UrlLauncher()`, `BrowserContextMenu()`, `SharedPreferences()`, `Clipboard()`, `StoragePaths()` by @ndonkoHenri. * Remove the `ConstrainedControl` base class (deprecated in `0.80.0`). Inherit from `LayoutControl` instead by @ndonkoHenri. * Remove `ElevatedButton` (deprecated in `0.80.0`). Use `Button` instead by @ndonkoHenri. -* Remove `DropdownM2` and its `dropdownm2` module (deprecated in `0.84.0`). Use `Dropdown` instead by @ndonkoHenri. * Remove the deprecated non-underscored `Colors` aliases (`BLACK12`, `BLACK26`, `BLACK38`, `BLACK45`, `BLACK54`, `BLACK87`, `WHITE10`, `WHITE12`, `WHITE24`, `WHITE30`, `WHITE38`, `WHITE54`, `WHITE60`, `WHITE70`). Use the underscored names instead (e.g. `Colors.BLACK_12`) by @ndonkoHenri. * Remove `app()` and `app_async()` (deprecated in `0.80.0`). Use `run()` and `run_async()` instead by @ndonkoHenri. * Remove the `target` parameter of `run()` and `run_async()` (deprecated alias for `main`). Pass `main` instead by @ndonkoHenri. @@ -19,6 +18,10 @@ * Remove the legacy `[tool.flet.app.boot_screen]` / `[tool.flet.app.startup_screen]` build-config fallback. Use `[tool.flet.boot_screen]` with a named screen instead by @ndonkoHenri. * Remove the Dart empty-string (`""`) widget-state key back-compat mapping. Use `"default"` (or `ControlState.DEFAULT`) instead by @ndonkoHenri. +### Changed + +* `DropdownM2` is no longer deprecated and remains a supported control; its `0.84.0` deprecation in favor of `Dropdown` has been reverted by @ndonkoHenri. + ## 0.86.1 ### Improvements diff --git a/packages/flet/lib/src/controls/dropdownm2.dart b/packages/flet/lib/src/controls/dropdownm2.dart new file mode 100644 index 0000000000..b1437a9b3a --- /dev/null +++ b/packages/flet/lib/src/controls/dropdownm2.dart @@ -0,0 +1,180 @@ +import 'package:flutter/material.dart'; + +import '../extensions/control.dart'; +import '../models/control.dart'; +import '../utils/alignment.dart'; +import '../utils/borders.dart'; +import '../utils/colors.dart'; +import '../utils/edge_insets.dart'; +import '../utils/form_field.dart'; +import '../utils/layout.dart'; +import '../utils/numbers.dart'; +import '../utils/text.dart'; +import 'base_controls.dart'; + +class DropdownM2Control extends StatefulWidget { + final Control control; + + DropdownM2Control({Key? key, required this.control}) + : super(key: key ?? ValueKey("control_${control.id}")); + + @override + State createState() => _DropdownM2ControlState(); +} + +class _DropdownM2ControlState extends State { + String? _value; + bool _focused = false; + late final FocusNode _focusNode; + + @override + void initState() { + super.initState(); + _focusNode = FocusNode(); + _focusNode.addListener(_onFocusChange); + widget.control.addInvokeMethodListener(_invokeMethod); + } + + void _onFocusChange() { + setState(() { + _focused = _focusNode.hasFocus; + }); + widget.control.triggerEvent(_focusNode.hasFocus ? "focus" : "blur"); + } + + Future _invokeMethod(String name, dynamic args) async { + debugPrint("DropdownM2.$name($args)"); + switch (name) { + case "focus": + _focusNode.requestFocus(); + default: + throw Exception("Unknown DropdownM2 method: $name"); + } + } + + @override + void dispose() { + _focusNode.removeListener(_onFocusChange); + _focusNode.dispose(); + widget.control.removeInvokeMethodListener(_invokeMethod); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + debugPrint("DropdownM2 build: ${widget.control.id}"); + + var textSize = widget.control.getDouble("text_size"); + var color = widget.control.getColor("color", context); + var focusedColor = widget.control.getColor("focused_color", context); + + var textStyle = widget.control + .getTextStyle("text_style", Theme.of(context), const TextStyle())!; + + if (textSize != null) { + textStyle = textStyle.copyWith(fontSize: textSize); + } + + if (focusedColor != null) { + textStyle = textStyle.copyWith( + color: _focused ? focusedColor : (color ?? textStyle.color)); + } + + if (color != null) { + textStyle = textStyle.copyWith(color: color); + } + + if (textStyle.color == null) { + textStyle = + textStyle.copyWith(color: Theme.of(context).colorScheme.onSurface); + } + + var items = widget.control + .children("options") + .map>((Control item) { + item.notifyParent = true; + var textStyle = item.getTextStyle("text_style", Theme.of(context)); + if (item.disabled && textStyle != null) { + textStyle = textStyle.apply(color: Theme.of(context).disabledColor); + } + var value = + item.getString("key") ?? item.getString("text") ?? item.id.toString(); + var content = + item.buildWidget("content") ?? Text(value, style: textStyle); + var alignment = item.getAlignment("alignment"); + if (alignment != null) { + content = Container(alignment: alignment, child: content); + } + return DropdownMenuItem( + enabled: !item.disabled, + value: value, + alignment: alignment ?? AlignmentDirectional.centerStart, + onTap: !item.disabled ? () => item.triggerEvent("click") : null, + child: content); + }).toList(); + + String? value = widget.control.getString("value"); + if (_value != value) { + _value = value; + } + + if (items.where((item) => item.value == value).isEmpty) { + _value = null; + } + + Widget dropDown = DropdownButtonFormField( + style: textStyle, + autofocus: widget.control.getBool("autofocus", false)!, + focusNode: _focusNode, + initialValue: _value, + dropdownColor: widget.control.getColor("bgcolor", context), + enableFeedback: widget.control.getBool("enable_feedback"), + elevation: widget.control.getInt("elevation", 8)!, + padding: widget.control.getPadding("padding"), + itemHeight: widget.control.getDouble("item_height"), + menuMaxHeight: widget.control.getDouble("max_menu_height"), + iconEnabledColor: + widget.control.getColor("select_icon_enabled_color", context), + iconDisabledColor: + widget.control.getColor("select_icon_disabled_color", context), + iconSize: widget.control.getDouble("select_icon_size", 24.0)!, + borderRadius: widget.control.getBorderRadius("border_radius"), + alignment: widget.control.getAlignment("alignment") ?? + AlignmentDirectional.centerStart, + isExpanded: widget.control.getBool("options_fill_horizontally", true)!, + icon: widget.control.buildIconOrWidget("select_icon"), + hint: widget.control.buildWidget("hint"), + disabledHint: widget.control.buildWidget("disabled_hint"), + decoration: buildInputDecoration(context, widget.control, + customSuffix: null, focused: _focused), + onTap: !widget.control.disabled + ? () => widget.control.triggerEvent("click") + : null, + onChanged: widget.control.disabled + ? null + : (String? value) { + _value = value!; + widget.control.updateProperties({"value": value}); + widget.control.triggerEvent("change", value); + }, + items: items, + ); + + if (widget.control.getExpand("expand", 0)! > 0) { + return LayoutControl(control: widget.control, child: dropDown); + } else { + return LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + if (constraints.maxWidth == double.infinity && + widget.control.getDouble("width") == null) { + dropDown = ConstrainedBox( + constraints: const BoxConstraints.tightFor(width: 300), + child: dropDown); + } + + return LayoutControl(control: widget.control, child: dropDown); + }, + ); + } + } +} diff --git a/packages/flet/lib/src/flet_core_extension.dart b/packages/flet/lib/src/flet_core_extension.dart index 6f64f6ffbf..9bb0d0232b 100644 --- a/packages/flet/lib/src/flet_core_extension.dart +++ b/packages/flet/lib/src/flet_core_extension.dart @@ -51,6 +51,7 @@ import 'controls/divider.dart'; import 'controls/drag_target.dart'; import 'controls/draggable.dart'; import 'controls/dropdown.dart'; +import 'controls/dropdownm2.dart'; import 'controls/expansion_panel.dart'; import 'controls/expansion_tile.dart'; import 'controls/flet_app_control.dart'; @@ -252,6 +253,8 @@ class FletCoreExtension extends FletExtension { return DraggableControl(key: key, control: control); case "Dropdown": return DropdownControl(key: key, control: control); + case "DropdownM2": + return DropdownM2Control(key: key, control: control); case "ExpansionPanelList": return ExpansionPanelListControl(key: key, control: control); case "ExpansionTile": diff --git a/sdk/python/packages/flet/src/flet/__init__.py b/sdk/python/packages/flet/src/flet/__init__.py index f953080611..ada04ca522 100644 --- a/sdk/python/packages/flet/src/flet/__init__.py +++ b/sdk/python/packages/flet/src/flet/__init__.py @@ -341,6 +341,7 @@ ) from flet.controls.material import ( dropdown, + dropdownm2, icons, ) from flet.controls.material.alert_dialog import AlertDialog @@ -391,6 +392,7 @@ Dropdown, DropdownOption, ) + from flet.controls.material.dropdownm2 import DropdownM2 from flet.controls.material.expansion_panel import ( ExpansionPanel, ExpansionPanelList, @@ -893,6 +895,7 @@ "DragWillAcceptEvent", "Draggable", "Dropdown", + "DropdownM2", "DropdownOption", "DropdownTheme", "Duration", @@ -1222,6 +1225,7 @@ "cupertino_colors", "cupertino_icons", "dropdown", + "dropdownm2", "icons", "is_route_active", "margin", @@ -1421,6 +1425,7 @@ "DragWillAcceptEvent": "flet.controls.core.drag_target", "Draggable": "flet.controls.core.draggable", "Dropdown": "flet.controls.material.dropdown", + "DropdownM2": "flet.controls.material.dropdownm2", "DropdownOption": "flet.controls.material.dropdown", "DropdownTheme": "flet.controls.theme", "Duration": "flet.controls.duration", @@ -1749,6 +1754,7 @@ "cupertino_colors": "flet.controls.cupertino", "cupertino_icons": "flet.controls.cupertino", "dropdown": "flet.controls.material", + "dropdownm2": "flet.controls.material", "icons": "flet.controls.material", "is_route_active": "flet.components.router", "margin": "flet.controls", diff --git a/sdk/python/packages/flet/src/flet/controls/material/dropdownm2.py b/sdk/python/packages/flet/src/flet/controls/material/dropdownm2.py new file mode 100644 index 0000000000..cd376226f3 --- /dev/null +++ b/sdk/python/packages/flet/src/flet/controls/material/dropdownm2.py @@ -0,0 +1,219 @@ +from typing import Optional + +from flet.controls.alignment import Alignment +from flet.controls.base_control import control +from flet.controls.control import Control +from flet.controls.control_event import ControlEventHandler +from flet.controls.material.form_field_control import FormFieldControl +from flet.controls.padding import PaddingValue +from flet.controls.text_style import TextStyle +from flet.controls.types import ( + ColorValue, + IconDataOrControl, + Number, +) +from flet.utils.validation import V, ValidationRules + +__all__ = ["DropdownM2", "Option"] + + +@control("Option") +class Option(Control): + """ + Represents an item in a dropdown. + """ + + key: Optional[str] = None + """ + Option's key. + + If not specified :attr:`text` will be used as fallback. + + Raises: + ValueError: If neither `key` nor :attr:`text` is provided. + """ + + text: Optional[str] = None + """ + Option's display text. + + If not specified :attr:`key` will be used as fallback. + + Raises: + ValueError: If neither :attr:`key` nor `text` is provided. + """ + + content: Optional[Control] = None + """ + A `Control` to display in this option. If not specified, `text` will be used as \ + fallback, else `text` will be ignored. + """ + + alignment: Optional[Alignment] = None + """ + Defines the alignment of this option in it's container. + + Defaults to `Alignment.center_left()`. + """ + + text_style: Optional[TextStyle] = None + """ + Defines the style of the `text`. + """ + + on_click: Optional[ControlEventHandler["Option"]] = None + """ + Called when this option is clicked. + """ + + __validation_rules__: ValidationRules = ( + V.ensure( + lambda ctrl: ctrl.key is not None or ctrl.text is not None, + message="key or text must be specified", + ), + ) + + +@control("DropdownM2") +class DropdownM2(FormFieldControl): + """ + A dropdown lets the user select from a number of items. The dropdown shows the \ + currently selected item as well as an arrow that opens a menu for selecting \ + another item. + + Example: + ```python + ft.DropdownM2( + width=220, + value="Alice", + options=[ + ft.dropdownm2.Option(key="Alice", text="Alice"), + ft.dropdownm2.Option(key="Bob", text="Bob"), + ], + ) + ``` + """ + + value: Optional[str] = None + """ + `key` value of the selected option. + """ + + options: Optional[list[Option]] = None + """ + A list of `Option` controls representing items in this dropdown. + """ + + alignment: Optional[Alignment] = None + """ + Defines how the `hint` or the selected item is positioned within this dropdown. + """ + + autofocus: bool = False + """ + True if the control will be selected as the initial focus. If there is more than \ + one control on a page with autofocus set, then the first one added to the page \ + will get focus. + """ + + hint_content: Optional[Control] = None + """ + A placeholder `Control` for the dropdown's value that is displayed when `value` is \ + `None`. + """ + + select_icon: Optional[IconDataOrControl] = None + """ + The [name of the icon](https://flet.dev/docs/types/icons) or `Control` to use \ + for the drop-down select button's icon. + + Defaults to `Icon(ft.Icons.ARROW_DROP_DOWN)`. + """ + + elevation: Number = 8 + """ + The dropdown's elevation. + """ + + item_height: Optional[Number] = None + """ + The height of the items/options in the dropdown menu. + """ + + max_menu_height: Optional[Number] = None + """ + The maximum height of the dropdown menu. + """ + + select_icon_size: Number = 24.0 + """ + The size of the icon button which wraps `select_icon`. + """ + + enable_feedback: Optional[bool] = None + """ + Whether detected gestures should provide acoustic and/or haptic feedback. On \ + Android, for example, setting this to `True` produce a click sound and a \ + long-press will produce a short vibration. + """ + + padding: Optional[PaddingValue] = None + """ + The padding around the visible portion of this dropdown. + """ + + select_icon_enabled_color: Optional[ColorValue] = None + """ + The color of any `Icon` descendant of `select_icon` if this button is enabled. + """ + + select_icon_disabled_color: Optional[ColorValue] = None + """ + The color of any `Icon` descendant of `select_icon` if this button is disabled. + """ + + options_fill_horizontally: bool = True + """ + Whether the dropdown's inner contents to horizontally fill its parent. + By default this button's inner width is the minimum size of its content. + + If `True`, the inner width is expanded to fill its surrounding container. + """ + + disabled_hint_content: Optional[Control] = None + """ + A placeholder `Control` for the dropdown's value that is displayed when `value` is \ + `None` and the dropdown is disabled. + """ + + on_change: Optional[ControlEventHandler["DropdownM2"]] = None + """ + Called when the selected item of this dropdown has changed. + """ + + on_focus: Optional[ControlEventHandler["DropdownM2"]] = None + """ + Called when the control has received focus. + """ + + on_blur: Optional[ControlEventHandler["DropdownM2"]] = None + """ + Called when the control has lost focus. + """ + + on_click: Optional[ControlEventHandler["DropdownM2"]] = None + """ + Called when this dropdown is clicked. + """ + + def before_update(self): + super().before_update() + if ( + self.bgcolor is not None + or self.fill_color is not None + or self.focused_bgcolor is not None + ) and self.filled is None: + self.filled = True # required to display any of the above colors + + def __contains__(self, item): + return item in self.options diff --git a/sdk/python/packages/flet/src/flet/controls/material/form_field_control.py b/sdk/python/packages/flet/src/flet/controls/material/form_field_control.py index 0005b217af..d4a5271476 100644 --- a/sdk/python/packages/flet/src/flet/controls/material/form_field_control.py +++ b/sdk/python/packages/flet/src/flet/controls/material/form_field_control.py @@ -46,7 +46,8 @@ class FormFieldControl(LayoutControl): Base class for Material form-field controls with a decorated input area. It provides the shared label, hint, helper, error, prefix, suffix, fill, and - border properties used by controls such as :class:`~flet.TextField`. + border properties used by controls such as :class:`~flet.TextField` and + :class:`~flet.DropdownM2`. """ text_size: Optional[Number] = None diff --git a/website/docs/controls/dropdownm2.md b/website/docs/controls/dropdownm2.md new file mode 100644 index 0000000000..e55db7ff94 --- /dev/null +++ b/website/docs/controls/dropdownm2.md @@ -0,0 +1,8 @@ +--- +class_name: "flet.DropdownM2" +title: "DropdownM2" +--- + +import {ClassAll} from '@site/src/components/crocodocs'; + + diff --git a/website/sidebars.yml b/website/sidebars.yml index a1bb7d67a5..206c97b79d 100644 --- a/website/sidebars.yml +++ b/website/sidebars.yml @@ -195,6 +195,7 @@ docs: Dropdown: _index: controls/dropdown/index.md DropdownOption: controls/dropdownoption.md + DropdownM2: controls/dropdownm2.md ExpansionPanel: controls/expansionpanel.md ExpansionPanelList: controls/expansionpanellist.md ExpansionTile: controls/expansiontile.md From fdb2ae96704b818c6f1bb39c679e32dc747a8bca Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Sat, 18 Jul 2026 13:09:22 +0200 Subject: [PATCH 07/11] Fix map examples launching URLs from a sync lambda (coroutine never awaited) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- sdk/python/examples/extensions/map/camera_controls/main.py | 7 ++++--- sdk/python/examples/extensions/map/idle_camera/main.py | 7 ++++--- .../examples/extensions/map/interaction_flags/main.py | 7 ++++--- sdk/python/examples/extensions/map/multi_layers/main.py | 7 ++++--- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/sdk/python/examples/extensions/map/camera_controls/main.py b/sdk/python/examples/extensions/map/camera_controls/main.py index e44875ced1..f43c4e440d 100644 --- a/sdk/python/examples/extensions/map/camera_controls/main.py +++ b/sdk/python/examples/extensions/map/camera_controls/main.py @@ -5,6 +5,9 @@ def main(page: ft.Page): page.padding = 16 + async def open_attribution(e: ft.Event[ftm.SimpleAttribution]): + await ft.UrlLauncher().launch_url("https://www.openstreetmap.org/copyright") + async def update_camera_status(trigger: str): camera = await my_map.get_camera() camera_status.value = ( @@ -81,9 +84,7 @@ async def set_world_zoom(e: ft.Event[ft.Button]): ), ftm.SimpleAttribution( text="OpenStreetMap contributors", - on_click=lambda e: ft.UrlLauncher().launch_url( - "https://www.openstreetmap.org/copyright" - ), + on_click=open_attribution, ), ftm.MarkerLayer( markers=[ diff --git a/sdk/python/examples/extensions/map/idle_camera/main.py b/sdk/python/examples/extensions/map/idle_camera/main.py index 310bdbb4bb..1109fc97cc 100644 --- a/sdk/python/examples/extensions/map/idle_camera/main.py +++ b/sdk/python/examples/extensions/map/idle_camera/main.py @@ -13,6 +13,9 @@ def main(page: ft.Page): page.padding = 16 + async def open_attribution(e: ft.Event[ftm.SimpleAttribution]): + await ft.UrlLauncher().launch_url("https://www.openstreetmap.org/copyright") + async def handle_map_event(e: ftm.MapEvent): last_event.value = ( "Last event: " @@ -68,9 +71,7 @@ async def handle_map_event(e: ftm.MapEvent): ), ftm.SimpleAttribution( text="OpenStreetMap contributors", - on_click=lambda e: ft.UrlLauncher().launch_url( - "https://www.openstreetmap.org/copyright" - ), + on_click=open_attribution, ), ], ), diff --git a/sdk/python/examples/extensions/map/interaction_flags/main.py b/sdk/python/examples/extensions/map/interaction_flags/main.py index a668c8a723..6b7db88d7d 100644 --- a/sdk/python/examples/extensions/map/interaction_flags/main.py +++ b/sdk/python/examples/extensions/map/interaction_flags/main.py @@ -16,6 +16,9 @@ def main(page: ft.Page): page.padding = 16 + async def open_attribution(e: ft.Event[ftm.SimpleAttribution]): + await ft.UrlLauncher().launch_url("https://www.openstreetmap.org/copyright") + def get_selected_flags() -> ftm.InteractionFlag: flags = ftm.InteractionFlag.NONE for checkbox in checkboxes: @@ -62,9 +65,7 @@ def handle_map_event(e: ftm.MapEvent): ), ftm.SimpleAttribution( text="OpenStreetMap contributors", - on_click=lambda e: ft.UrlLauncher().launch_url( - "https://www.openstreetmap.org/copyright" - ), + on_click=open_attribution, ), ], ) diff --git a/sdk/python/examples/extensions/map/multi_layers/main.py b/sdk/python/examples/extensions/map/multi_layers/main.py index 2c84a67923..7ae7e95f58 100644 --- a/sdk/python/examples/extensions/map/multi_layers/main.py +++ b/sdk/python/examples/extensions/map/multi_layers/main.py @@ -5,6 +5,9 @@ def main(page: ft.Page): + async def open_attribution(e: ft.Event[ftm.SimpleAttribution]): + await ft.UrlLauncher().launch_url("https://www.openstreetmap.org/copyright") + def handle_tap(e: ftm.MapTapEvent): if e.name == "tap": marker_layer.markers.append( @@ -56,9 +59,7 @@ def handle_tap(e: ftm.MapTapEvent): ), ftm.SimpleAttribution( text="OpenStreetMap contributors", - on_click=lambda e: ft.UrlLauncher().launch_url( - "https://www.openstreetmap.org/copyright" - ), + on_click=open_attribution, ), marker_layer := ftm.MarkerLayer( markers=[ From 568a64642b2c62dedef55503b6789e123fe7613a Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Sat, 18 Jul 2026 13:31:16 +0200 Subject: [PATCH 08/11] Reference removal PR #6693 in the 1.0.0 changelog and migration guides Point the 1.0.0 CHANGELOG entries (root + flet-video) at the removal PR #6693 instead of the original deprecation PRs, and add #6693 to the References of the drag-target/video/clear-cache migration guides. --- CHANGELOG.md | 32 +++++++++---------- sdk/python/packages/flet-video/CHANGELOG.md | 4 +-- ...eprecated-drag-target-event-coordinates.md | 2 +- .../v0-85-0/deprecated-video-apis.md | 2 +- .../v0-86-0/deprecated-clear-cache-flag.md | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 809d4aad56..ba67d75b91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,25 +2,25 @@ ### Breaking changes -* Remove `DragTargetEvent.x`, `DragTargetEvent.y`, and `DragTargetEvent.offset` (deprecated in `0.85.0`). Use `DragTargetEvent.local_position` for target-relative coordinates or `DragTargetEvent.global_position` for global coordinates ([#6401](https://github.com/flet-dev/flet/pull/6401)) by @ndonkoHenri. -* Remove `Video.show_controls` (deprecated in `0.85.0`). Set `Video.controls` to `None` to hide controls ([#6463](https://github.com/flet-dev/flet/pull/6463)) by @ndonkoHenri. -* Remove `Video.playlist_add()` and `Video.playlist_remove()` (deprecated in `0.85.0`). Mutate `Video.playlist` directly with list methods such as `append()` and `pop()` ([#6463](https://github.com/flet-dev/flet/pull/6463)) by @ndonkoHenri. -* Remove `FletApp.show_app_startup_screen` and `FletApp.app_startup_screen_message` (deprecated in `0.86.0`). Use `FletApp.boot_screen_options` instead, e.g. `boot_screen_options={'spinner_size': 30}` or `boot_screen_options={'startup_message': '...'}` by @ndonkoHenri. -* Remove the `--clear-cache` flag of `flet build` and `flet debug` (deprecated in `0.86.0`). Use the `flet clean` command instead ([#6233](https://github.com/flet-dev/flet/issues/6233)) by @ndonkoHenri. -* Remove `Page.go()` (deprecated in `0.80.0`). Use `Page.push_route()` instead by @ndonkoHenri. -* 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 corresponding service classes directly: `UrlLauncher()`, `BrowserContextMenu()`, `SharedPreferences()`, `Clipboard()`, `StoragePaths()` by @ndonkoHenri. -* Remove the `ConstrainedControl` base class (deprecated in `0.80.0`). Inherit from `LayoutControl` instead by @ndonkoHenri. -* Remove `ElevatedButton` (deprecated in `0.80.0`). Use `Button` instead by @ndonkoHenri. -* Remove the deprecated non-underscored `Colors` aliases (`BLACK12`, `BLACK26`, `BLACK38`, `BLACK45`, `BLACK54`, `BLACK87`, `WHITE10`, `WHITE12`, `WHITE24`, `WHITE30`, `WHITE38`, `WHITE54`, `WHITE60`, `WHITE70`). Use the underscored names instead (e.g. `Colors.BLACK_12`) by @ndonkoHenri. -* Remove `app()` and `app_async()` (deprecated in `0.80.0`). Use `run()` and `run_async()` instead by @ndonkoHenri. -* Remove the `target` parameter of `run()` and `run_async()` (deprecated alias for `main`). Pass `main` instead by @ndonkoHenri. -* Remove `Page.launch_url()`, `Page.can_launch_url()`, and `Page.close_in_app_web_view()` (deprecated in `0.90.0`). Use `UrlLauncher().launch_url()` / `.can_launch_url()` / `.close_in_app_web_view()` instead by @ndonkoHenri. -* Remove the legacy `[tool.flet.app.boot_screen]` / `[tool.flet.app.startup_screen]` build-config fallback. Use `[tool.flet.boot_screen]` with a named screen instead by @ndonkoHenri. -* Remove the Dart empty-string (`""`) widget-state key back-compat mapping. Use `"default"` (or `ControlState.DEFAULT`) instead by @ndonkoHenri. +* Remove `DragTargetEvent.x`, `DragTargetEvent.y`, and `DragTargetEvent.offset` (deprecated in `0.85.0`). Use `DragTargetEvent.local_position` for target-relative coordinates or `DragTargetEvent.global_position` for global coordinates ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove `Video.show_controls` (deprecated in `0.85.0`). Set `Video.controls` to `None` to hide controls ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove `Video.playlist_add()` and `Video.playlist_remove()` (deprecated in `0.85.0`). Mutate `Video.playlist` directly with list methods such as `append()` and `pop()` ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove `FletApp.show_app_startup_screen` and `FletApp.app_startup_screen_message` (deprecated in `0.86.0`). Use `FletApp.boot_screen_options` instead, e.g. `boot_screen_options={'spinner_size': 30}` or `boot_screen_options={'startup_message': '...'}` ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove the `--clear-cache` flag of `flet build` and `flet debug` (deprecated in `0.86.0`). Use the `flet clean` command instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove `Page.go()` (deprecated in `0.80.0`). Use `Page.push_route()` instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* 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 corresponding service classes directly: `UrlLauncher()`, `BrowserContextMenu()`, `SharedPreferences()`, `Clipboard()`, `StoragePaths()` ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove the `ConstrainedControl` base class (deprecated in `0.80.0`). Inherit from `LayoutControl` instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove `ElevatedButton` (deprecated in `0.80.0`). Use `Button` instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove the deprecated non-underscored `Colors` aliases (`BLACK12`, `BLACK26`, `BLACK38`, `BLACK45`, `BLACK54`, `BLACK87`, `WHITE10`, `WHITE12`, `WHITE24`, `WHITE30`, `WHITE38`, `WHITE54`, `WHITE60`, `WHITE70`). Use the underscored names instead (e.g. `Colors.BLACK_12`) ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove `app()` and `app_async()` (deprecated in `0.80.0`). Use `run()` and `run_async()` instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove the `target` parameter of `run()` and `run_async()` (deprecated alias for `main`). Pass `main` instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove `Page.launch_url()`, `Page.can_launch_url()`, and `Page.close_in_app_web_view()` (deprecated in `0.90.0`). Use `UrlLauncher().launch_url()` / `.can_launch_url()` / `.close_in_app_web_view()` instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove the legacy `[tool.flet.app.boot_screen]` / `[tool.flet.app.startup_screen]` build-config fallback. Use `[tool.flet.boot_screen]` with a named screen instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove the Dart empty-string (`""`) widget-state key back-compat mapping. Use `"default"` (or `ControlState.DEFAULT`) instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. ### Changed -* `DropdownM2` is no longer deprecated and remains a supported control; its `0.84.0` deprecation in favor of `Dropdown` has been reverted by @ndonkoHenri. +* `DropdownM2` is no longer deprecated and remains a supported control; its `0.84.0` deprecation in favor of `Dropdown` has been reverted ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. ## 0.86.1 diff --git a/sdk/python/packages/flet-video/CHANGELOG.md b/sdk/python/packages/flet-video/CHANGELOG.md index c6a0107df3..915ee1c960 100644 --- a/sdk/python/packages/flet-video/CHANGELOG.md +++ b/sdk/python/packages/flet-video/CHANGELOG.md @@ -9,8 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Removed -- `Video.show_controls` (deprecated in 0.85.0); set `Video.controls` to `None` to hide controls ([#6463](https://github.com/flet-dev/flet/pull/6463)) by @ndonkoHenri. -- `Video.playlist_add()` and `Video.playlist_remove()` (deprecated in 0.85.0); mutate `Video.playlist` directly with list methods such as `append()` and `pop()` ([#6463](https://github.com/flet-dev/flet/pull/6463)) by @ndonkoHenri. +- `Video.show_controls` (deprecated in 0.85.0); set `Video.controls` to `None` to hide controls ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +- `Video.playlist_add()` and `Video.playlist_remove()` (deprecated in 0.85.0); mutate `Video.playlist` directly with list methods such as `append()` and `pop()` ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. ## 0.85.0 diff --git a/website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md b/website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md index 5e603dd62c..f55a9179c9 100644 --- a/website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md +++ b/website/docs/updates/breaking-changes/v0-85-0/deprecated-drag-target-event-coordinates.md @@ -60,5 +60,5 @@ If your code needs page-level coordinates instead, use ## References - API documentation: [`DragTargetEvent`][flet.DragTargetEvent] -- Issues and PRs: [#6387](https://github.com/flet-dev/flet/issues/6387), [#6401](https://github.com/flet-dev/flet/pull/6401) +- Issues and PRs: [#6387](https://github.com/flet-dev/flet/issues/6387), [#6401](https://github.com/flet-dev/flet/pull/6401), [#6693](https://github.com/flet-dev/flet/pull/6693) (removal) - Release notes: [Flet 0.85.0](../../release-notes.md#085x) diff --git a/website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md b/website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md index 8ba5dcfc95..0cbf44f2d8 100644 --- a/website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md +++ b/website/docs/updates/breaking-changes/v0-85-0/deprecated-video-apis.md @@ -79,5 +79,5 @@ been added to the page. ## References - API documentation: [`Video`][flet_video.Video] -- Issues and PRs: [PR #6463](https://github.com/flet-dev/flet/pull/6463) +- Issues and PRs: [PR #6463](https://github.com/flet-dev/flet/pull/6463), [PR #6693](https://github.com/flet-dev/flet/pull/6693) (removal) - Release notes: [Flet 0.85.0](../../release-notes.md#085x) diff --git a/website/docs/updates/breaking-changes/v0-86-0/deprecated-clear-cache-flag.md b/website/docs/updates/breaking-changes/v0-86-0/deprecated-clear-cache-flag.md index 868350abd6..3cf9922d67 100644 --- a/website/docs/updates/breaking-changes/v0-86-0/deprecated-clear-cache-flag.md +++ b/website/docs/updates/breaking-changes/v0-86-0/deprecated-clear-cache-flag.md @@ -55,5 +55,5 @@ current directory), so you can target another project with `flet clean path/to/a ## References - CLI documentation: [`flet clean`](../../../cli/flet-clean.md), [`flet build`](../../../cli/flet-build.md) -- Issues and PRs: [#6233](https://github.com/flet-dev/flet/issues/6233) +- Issues and PRs: [#6233](https://github.com/flet-dev/flet/issues/6233), [#6693](https://github.com/flet-dev/flet/pull/6693) (removal) - Release notes: [Flet 0.86.0](../../release-notes.md) From 218947c341f73e89b26af2a948f500865641c3c4 Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Sat, 18 Jul 2026 13:47:09 +0200 Subject: [PATCH 09/11] Fix docs build: ContextMenu docstring referenced removed Page.browser_context_menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .../flet/src/flet/controls/material/context_menu.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/python/packages/flet/src/flet/controls/material/context_menu.py b/sdk/python/packages/flet/src/flet/controls/material/context_menu.py index b426df9e69..36a8a3d99c 100644 --- a/sdk/python/packages/flet/src/flet/controls/material/context_menu.py +++ b/sdk/python/packages/flet/src/flet/controls/material/context_menu.py @@ -97,9 +97,9 @@ class ContextMenu(LayoutControl): Wraps its :attr:`content` and displays contextual menus for specific mouse events. Tip: - On web, call :meth:`flet.BrowserContextMenu.disable` method of - :attr:`flet.Page.browser_context_menu` to suppress the default browser - context menu before relying on custom menus. + On web, call [`BrowserContextMenu.disable()`][flet.BrowserContextMenu.disable] + method to suppress the default browser context menu before relying + on custom menus. """ content: Annotated[ From 77e8a841f68553a1628ddeb2af633507d2df12c3 Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Mon, 17 Aug 2026 02:39:14 +0200 Subject: [PATCH 10/11] docs: add a 1.0.0 guide for the removed deprecated APIs 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. --- .../docs/updates/breaking-changes/index.md | 6 + .../v1-0-0/removed-deprecated-apis.md | 129 ++++++++++++++++++ website/docs/updates/release-notes.md | 4 + website/sidebars.yml | 2 + 4 files changed, 141 insertions(+) create mode 100644 website/docs/updates/breaking-changes/v1-0-0/removed-deprecated-apis.md diff --git a/website/docs/updates/breaking-changes/index.md b/website/docs/updates/breaking-changes/index.md index 007e668502..9c5208e3f5 100644 --- a/website/docs/updates/breaking-changes/index.md +++ b/website/docs/updates/breaking-changes/index.md @@ -22,6 +22,12 @@ This page lists the guides created for each release. The following guides are available. They're sorted by release, with the most recent release first. Each guide explains the change, the reason for it, and how to migrate your code. +### Released in Flet 1.0.0 + +#### Breaking changes + +- [All deprecated APIs removed](/docs/updates/breaking-changes/v1-0-0/removed-deprecated-apis) + ### Released in Flet 0.86.0 #### Breaking changes diff --git a/website/docs/updates/breaking-changes/v1-0-0/removed-deprecated-apis.md b/website/docs/updates/breaking-changes/v1-0-0/removed-deprecated-apis.md new file mode 100644 index 0000000000..9d4292eb1b --- /dev/null +++ b/website/docs/updates/breaking-changes/v1-0-0/removed-deprecated-apis.md @@ -0,0 +1,129 @@ +--- +title: "All deprecated APIs removed" +--- + +# All deprecated APIs removed + +:::note +This guide is accurate as of Flet 1.0.0. Later releases might add new APIs or +additional migration paths. + +The [breaking changes and deprecations index](../index.md) lists the guides created for each release. +::: + +## Summary + +Flet 1.0.0 removes every API that was deprecated in the previous Flet versions, so the +release ships deprecation-free. Each removal has a direct replacement. + +### Controls and types + +| Removed | Replacement | +|-----------------------------------------------|------------------------------------------------------------------| +| `ElevatedButton` | [`Button`][flet.Button] | +| `ConstrainedControl` | [`LayoutControl`][flet.LayoutControl] | +| `DragTargetEvent.x` / `.y` | `DragTargetEvent.local_position` | +| `DragTargetEvent.offset` | `DragTargetEvent.global_position` | +| `Video.show_controls` | Set `Video.controls` to `None` to hide them | +| `Video.playlist_add()` / `.playlist_remove()` | Mutate `Video.playlist` directly, e.g. `append()` / `pop()` | +| `Colors.BLACK12`, `Colors.WHITE70`, … | The underscored names, e.g. `Colors.BLACK_12`, `Colors.WHITE_70` | + +### Page and app APIs + +| Removed | Replacement | +|--------------------------------------------------|----------------------------------------------------| +| `app()` / `app_async()` | `run()` / `run_async()` | +| `target` parameter of `run()` / `run_async()` | `main` | +| `Page.go()` | `Page.push_route()` | +| `Page.launch_url()` | `UrlLauncher().launch_url()` | +| `Page.can_launch_url()` | `UrlLauncher().can_launch_url()` | +| `Page.close_in_app_web_view()` | `UrlLauncher().close_in_app_web_view()` | +| `Page.url_launcher` | `UrlLauncher()` | +| `Page.browser_context_menu` | `BrowserContextMenu()` | +| `Page.shared_preferences` | `SharedPreferences()` | +| `Page.clipboard` | `Clipboard()` | +| `Page.storage_paths` | `StoragePaths()` | +| `FletApp.show_app_startup_screen` | `FletApp.boot_screen_options` | +| `FletApp.app_startup_screen_message` | `FletApp.boot_screen_options` | + +### Tooling and configuration + +| Removed | Replacement | +|------------------------------------------------------------------|-----------------------------------------------| +| `--clear-cache` flag of `flet build` and `flet debug` | The `flet clean` command | +| `[tool.flet.app.boot_screen]` / `[tool.flet.app.startup_screen]` | `[tool.flet.boot_screen]` with a named screen | +| Dart empty-string (`""`) widget-state key | `"default"`, or `ControlState.DEFAULT` | + +`DropdownM2` is **not** removed. Its deprecation in favour of `Dropdown` is +withdrawn, and it remains a supported control. + +## Background + +Flet's [compatibility policy](../../compatibility-policy.md) removes a +deprecated API after three minor releases. Rather than spread those removals +across several `0.8x` releases, they are taken together in 1.0.0 so that the +first stable release carries no deprecation debt and no compatibility shims. + +Every API listed above emitted a runtime `DeprecationWarning` and carried a +deprecation label in the API docs before this release, so code that ran without +warnings on `0.86` needs no changes. + +## Migration guide + +Run your app on Flet `0.86` first and fix everything that emits a +`DeprecationWarning` — that is the complete list of what 1.0.0 removes. To +surface the warnings, run Python with them enabled: + +```bash +python -W default::DeprecationWarning main.py +``` + +Then apply the replacements from the tables above. + +Code before migration: + +```python +import flet as ft + +async def main(page: ft.Page): + async def open_site(e): + await page.launch_url("https://flet.dev") + + page.add(ft.ElevatedButton("Open", on_click=open_site)) + await page.go("/home") + +ft.app(target=main) +``` + +Code after migration: + +```python +import flet as ft + +async def main(page: ft.Page): + async def open_site(e): + await ft.UrlLauncher().launch_url("https://flet.dev") + + page.add(ft.Button("Open", on_click=open_site)) + await page.push_route("/home") + +ft.run(main) +``` + +Three of these removals have their own guides, written when the APIs were +deprecated: + +- [`DragTargetEvent` coordinate fields](../v0-85-0/deprecated-drag-target-event-coordinates.md) +- [`Video` control APIs](../v0-85-0/deprecated-video-apis.md) +- [`flet build --clear-cache` flag](../v0-86-0/deprecated-clear-cache-flag.md) + +## Timeline + +- Removed in: `1.0.0` + +## References + +- API documentation: [`Button`][flet.Button], [`LayoutControl`][flet.LayoutControl], [`UrlLauncher`][flet.UrlLauncher], [`Colors`][flet.Colors] +- [Compatibility policy](../../compatibility-policy.md) +- Issues and PRs: [#6693](https://github.com/flet-dev/flet/pull/6693) +- Release notes: [Flet 1.0.0](../../release-notes.md#10x) diff --git a/website/docs/updates/release-notes.md b/website/docs/updates/release-notes.md index a39a075677..108ec77100 100644 --- a/website/docs/updates/release-notes.md +++ b/website/docs/updates/release-notes.md @@ -8,6 +8,10 @@ This page links release announcements, changelogs, and migration notes for Flet ## Stable releases +### 1.0.x + +- 1.0.0: [Changelog](https://github.com/flet-dev/flet/blob/main/CHANGELOG.md#100), [Breaking changes and deprecations](breaking-changes/index.md#released-in-flet-100) + ### 0.86.x - 0.86.0: [Announcement](/blog/flet-v-0-86-release-announcement), [Changelog](https://github.com/flet-dev/flet/blob/main/CHANGELOG.md#0860), [Breaking changes and deprecations](breaking-changes/index.md#released-in-flet-0860) diff --git a/website/sidebars.yml b/website/sidebars.yml index 90c24e9b9f..e7c7a54b47 100644 --- a/website/sidebars.yml +++ b/website/sidebars.yml @@ -72,6 +72,8 @@ docs: Release notes: updates/release-notes.md Breaking changes and deprecations: _index: updates/breaking-changes/index.md + v1.0.0: + All deprecated APIs removed: updates/breaking-changes/v1-0-0/removed-deprecated-apis.md v0.86.0: App files ship unpacked in a read-only bundle; storage dirs reworked: updates/breaking-changes/v0-86-0/app-files-unpacked-read-only-bundle.md "Android: site-packages ship zipped; some packages need extract_packages": updates/breaking-changes/v0-86-0/android-extract-packages.md From 6922e9262ce323757d319b464703afe044b781e9 Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Mon, 17 Aug 2026 02:39:15 +0200 Subject: [PATCH 11/11] docs: correct the version that deprecated the `Page` URL methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1543afe0f..76cf59d6ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ * Remove the deprecated non-underscored `Colors` aliases (`BLACK12`, `BLACK26`, `BLACK38`, `BLACK45`, `BLACK54`, `BLACK87`, `WHITE10`, `WHITE12`, `WHITE24`, `WHITE30`, `WHITE38`, `WHITE54`, `WHITE60`, `WHITE70`). Use the underscored names instead (e.g. `Colors.BLACK_12`) ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. * Remove `app()` and `app_async()` (deprecated in `0.80.0`). Use `run()` and `run_async()` instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. * Remove the `target` parameter of `run()` and `run_async()` (deprecated alias for `main`). Pass `main` instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. -* Remove `Page.launch_url()`, `Page.can_launch_url()`, and `Page.close_in_app_web_view()` (deprecated in `0.90.0`). Use `UrlLauncher().launch_url()` / `.can_launch_url()` / `.close_in_app_web_view()` instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. +* Remove `Page.launch_url()`, `Page.can_launch_url()`, and `Page.close_in_app_web_view()` (deprecated in `0.80.0`). Use `UrlLauncher().launch_url()` / `.can_launch_url()` / `.close_in_app_web_view()` instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. * Remove the legacy `[tool.flet.app.boot_screen]` / `[tool.flet.app.startup_screen]` build-config fallback. Use `[tool.flet.boot_screen]` with a named screen instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri. * Remove the Dart empty-string (`""`) widget-state key back-compat mapping. Use `"default"` (or `ControlState.DEFAULT`) instead ([#6693](https://github.com/flet-dev/flet/pull/6693)) by @ndonkoHenri.