From 6609d701279c4115c8f8d3c6d550ff9f4223981d Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 22 Jan 2026 15:41:19 -0800 Subject: [PATCH 1/4] Refactor `Icons` and `CupertinoIcons` proxies for member caching and iteration (#6055) * Refactor icon proxies for member caching and iteration Introduced member caching in _CupertinoIconsProxy and _IconsProxy to avoid duplicate icon instances and improve attribute access. Added __iter__ and __len__ methods for both proxies to support iteration and length queries. Also set __name__ and __qualname__ for icon data classes to improve introspection. * Update build version script to increment patch version The script now increments the patch version instead of the minor version when updating the package version. This ensures versioning follows the semantic versioning convention more closely. * Bump Flet to 0.80.4 and update Flutter to 3.38.7 Updated Flet package version to 0.80.4 and aligned Flutter version to 3.38.7. Changelogs updated to reflect refactoring of icon proxies and Flutter version bump. Adjusted PyPI cleanup script to match new versioning. --- .fvmrc | 2 +- .github/scripts/clean-pypi.sh | 2 +- .github/scripts/update_build_version.sh | 12 +++---- CHANGELOG.md | 4 +++ client/pubspec.lock | 2 +- packages/flet/CHANGELOG.md | 4 +++ packages/flet/pubspec.yaml | 2 +- .../controls/cupertino/cupertino_icons.py | 34 ++++++++++++++++--- .../flet/src/flet/controls/material/icons.py | 34 ++++++++++++++++--- 9 files changed, 78 insertions(+), 18 deletions(-) diff --git a/.fvmrc b/.fvmrc index 6a1a5084a1..1d524b394f 100644 --- a/.fvmrc +++ b/.fvmrc @@ -1,3 +1,3 @@ { - "flutter": "3.38.6" + "flutter": "3.38.7" } diff --git a/.github/scripts/clean-pypi.sh b/.github/scripts/clean-pypi.sh index d93036d6cf..dec2631719 100644 --- a/.github/scripts/clean-pypi.sh +++ b/.github/scripts/clean-pypi.sh @@ -1,6 +1,6 @@ # set PYPI_CLEANUP_PASSWORD with pypi.org password -VER="0\.81\.0\.dev(?!7287)" +VER="0\.81\.0\.dev(?!7200)" uv tool install pypi-cleanup uvx pypi-cleanup -u flet -p flet -y -r $VER --do-it uvx pypi-cleanup -u flet -p flet-cli -y -r $VER --do-it diff --git a/.github/scripts/update_build_version.sh b/.github/scripts/update_build_version.sh index 504b974a8a..3ef5a69cd1 100755 --- a/.github/scripts/update_build_version.sh +++ b/.github/scripts/update_build_version.sh @@ -41,16 +41,16 @@ else # Remove leading "v" if present cv=${cv#v} - # Split into major/minor components + # Split into major/minor/patch components major=$(echo "$cv" | cut -d. -f1) minor=$(echo "$cv" | cut -d. -f2) + patch=$(echo "$cv" | cut -d. -f3) - # Increment the minor version (e.g. "1.2" → "1.3") - minor=$((minor + 1)) - - # Construct the package version: ..0 - export PKG_VER="${major}.${minor}.0" + # Increment patch version (e.g. "1.2.3" → "1.2.4") + patch=$((patch + 1)) + # Construct the package version: .. + export PKG_VER="${major}.${minor}.${patch}" # PyPI build version: + export PYPI_VER="${PKG_VER}.dev${BUILD_NUM}" fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 682cf5a539..ae252dcf70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.80.4 + +* Refactor `Icons` and `CupertinoIcons` proxies for member caching and iteration. + ## 0.80.3 * Lazy loading of icons, theme for faster app startup ([#6043](https://github.com/flet-dev/flet/issues/6043)). diff --git a/client/pubspec.lock b/client/pubspec.lock index 9bec460f66..4276781ccf 100644 --- a/client/pubspec.lock +++ b/client/pubspec.lock @@ -295,7 +295,7 @@ packages: path: "../packages/flet" relative: true source: path - version: "0.80.3" + version: "0.80.4" flet_ads: dependency: "direct main" description: diff --git a/packages/flet/CHANGELOG.md b/packages/flet/CHANGELOG.md index 098e0427a0..e21a0799bf 100644 --- a/packages/flet/CHANGELOG.md +++ b/packages/flet/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.80.4 + +* Flutter 3.38.7. + ## 0.80.3 * feat: add `locale` prop to `CupertinoDatePicker`, `DatePicker`, `DateRangePicker`, `TimePicker` ([#6030](https://github.com/flet-dev/flet/issues/6030)). diff --git a/packages/flet/pubspec.yaml b/packages/flet/pubspec.yaml index 2932fcc9ff..ae078d3b06 100644 --- a/packages/flet/pubspec.yaml +++ b/packages/flet/pubspec.yaml @@ -2,7 +2,7 @@ name: flet description: Write entire Flutter app in Python or add server-driven UI experience into existing Flutter app. homepage: https://flet.dev repository: https://github.com/flet-dev/flet/tree/main/packages/flet -version: 0.80.3 +version: 0.80.4 # Supported platforms platforms: diff --git a/sdk/python/packages/flet/src/flet/controls/cupertino/cupertino_icons.py b/sdk/python/packages/flet/src/flet/controls/cupertino/cupertino_icons.py index 44a65a7087..642e8d285b 100644 --- a/sdk/python/packages/flet/src/flet/controls/cupertino/cupertino_icons.py +++ b/sdk/python/packages/flet/src/flet/controls/cupertino/cupertino_icons.py @@ -21,6 +21,10 @@ def _missing_(cls, value): return obj +_CupertinoIconData.__name__ = "CupertinoIcons" +_CupertinoIconData.__qualname__ = "CupertinoIcons" + + class _CupertinoIconsProxy: __slots__ = ("_map", "_values") @@ -38,18 +42,32 @@ def _load(self) -> None: ) self._map = json.loads(data) + def _get_member(self, name: str) -> _CupertinoIconData: + self._load() + assert self._map is not None + cls = _CupertinoIconData + existing = cls._member_map_.get(name) + if existing is not None: + return existing + value = self._map[name] + member = int.__new__(cls, value) + member._value_ = value + member._name_ = name + cls._member_map_[name] = member + cls._value2member_map_[value] = member + cls._member_names_.append(name) + return member + def _get_values(self) -> list[_CupertinoIconData]: self._load() if self._values is None: assert self._map is not None - self._values = [_CupertinoIconData(v) for v in self._map.values()] + self._values = [self._get_member(name) for name in self._map] return self._values def __getattr__(self, name: str) -> IconData: - self._load() - assert self._map is not None try: - return _CupertinoIconData(self._map[name]) + return self._get_member(name) except KeyError: raise AttributeError(name) from None @@ -58,6 +76,14 @@ def __dir__(self) -> list[str]: assert self._map is not None return sorted(self._map.keys()) + def __iter__(self): + return iter(self._get_values()) + + def __len__(self) -> int: + self._load() + assert self._map is not None + return len(self._map) + def random( self, exclude: list[IconData] | None = None, diff --git a/sdk/python/packages/flet/src/flet/controls/material/icons.py b/sdk/python/packages/flet/src/flet/controls/material/icons.py index ffc89ae912..88c326fb1a 100644 --- a/sdk/python/packages/flet/src/flet/controls/material/icons.py +++ b/sdk/python/packages/flet/src/flet/controls/material/icons.py @@ -21,6 +21,10 @@ def _missing_(cls, value): return obj +_MaterialIconData.__name__ = "Icons" +_MaterialIconData.__qualname__ = "Icons" + + class _IconsProxy: __slots__ = ("_map", "_values") @@ -38,18 +42,32 @@ def _load(self) -> None: ) self._map = json.loads(data) + def _get_member(self, name: str) -> _MaterialIconData: + self._load() + assert self._map is not None + cls = _MaterialIconData + existing = cls._member_map_.get(name) + if existing is not None: + return existing + value = self._map[name] + member = int.__new__(cls, value) + member._value_ = value + member._name_ = name + cls._member_map_[name] = member + cls._value2member_map_[value] = member + cls._member_names_.append(name) + return member + def _get_values(self) -> list[_MaterialIconData]: self._load() if self._values is None: assert self._map is not None - self._values = [_MaterialIconData(v) for v in self._map.values()] + self._values = [self._get_member(name) for name in self._map] return self._values def __getattr__(self, name: str) -> IconData: - self._load() - assert self._map is not None try: - return _MaterialIconData(self._map[name]) + return self._get_member(name) except KeyError: raise AttributeError(name) from None @@ -58,6 +76,14 @@ def __dir__(self) -> list[str]: assert self._map is not None return sorted(self._map.keys()) + def __iter__(self): + return iter(self._get_values()) + + def __len__(self) -> int: + self._load() + assert self._map is not None + return len(self._map) + def random( self, exclude: list[IconData] | None = None, From d8eefd667564564f5a90737245fa2e8467666996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Pa=C5=99il?= <46622252+Dejv311@users.noreply.github.com> Date: Fri, 23 Jan 2026 19:52:52 +0100 Subject: [PATCH 2/4] flet-video: add mpv_properties to VideoConfiguration (#6041) * flet-video: add mpv_properties to VideoConfiguration * bugfix: fix compilation error for web * docs: Improve mpv_properties documentation * Update mpv_properties type hint and improve documentation for clarity --------- Co-authored-by: ndonkoHenri --- .../flet-video/src/flet_video/types.py | 25 +++++++++++++- .../src/flutter/flet_video/lib/src/video.dart | 33 +++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/sdk/python/packages/flet-video/src/flet_video/types.py b/sdk/python/packages/flet-video/src/flet_video/types.py index 77db740dec..f25308ec09 100644 --- a/sdk/python/packages/flet-video/src/flet_video/types.py +++ b/sdk/python/packages/flet-video/src/flet_video/types.py @@ -4,7 +4,7 @@ from dataclasses import dataclass, field from enum import Enum -from typing import Optional +from typing import Optional, Union import flet as ft @@ -90,6 +90,29 @@ class VideoConfiguration: Specifying this option will cause [`width`][(c).] & [`height`][(c).] to be ignored. """ + mpv_properties: Optional[dict[str, Union[str, int, float, bool]]] = None + """ + Extra mpv/libmpv properties to set on + native backends (Windows/macOS/Linux/iOS/Android). + + The keys are mpv option/property names without the leading `--`. Values can be + `str`, `int`, `float` or `bool`. All values are converted to strings before being + passed to mpv; boolean values are converted to `"yes"` / `"no"`. + + Full list of mpv options: https://mpv.io/manual/stable/#options + + Example: + ```python + >>> VideoConfiguration( + mpv_properties={ + "profile": "low-latency", # --profile=low-latency + "untimed": True, # --untimed + "volume": 80, # --volume=80 + } + ) + ``` + """ + @dataclass class VideoSubtitleTrack: 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 bde5ab167c..535b76bd46 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 @@ -25,6 +25,27 @@ class _VideoControlState extends State with FletStoreMixin { late VideoController _controller; bool _initialized = false; + Future _applyMpvProperties(Control control) async { + final cfg = control.get("configuration"); + if (cfg is! Map) return; + + final mpvPropsRaw = cfg["mpv_properties"]; + if (mpvPropsRaw is! Map) return; + + final platform = _player.platform; + if (platform is! NativePlayer) return; + final native = platform as dynamic; + + for (final entry in mpvPropsRaw.entries) { + final key = entry.key.toString(); + final val = entry.value; + if (val == null) continue; + final valueStr = val is bool ? (val ? "yes" : "no") : val.toString(); + await native.setProperty(key, valueStr); + } + } + + void _setup(Control control) { final playerConfig = PlayerConfiguration( title: control.getString("title", "flet-video")!, @@ -64,8 +85,14 @@ class _VideoControlState extends State with FletStoreMixin { }); } - _player.open(Playlist(parseVideoMedias(control.get("playlist"), [])!), - play: control.getBool("autoplay", false)!); + final playlist = + Playlist(parseVideoMedias(control.get("playlist"), [])!); + final autoplay = control.getBool("autoplay", false)!; + + () async { + await _applyMpvProperties(control); + await _player.open(playlist, play: autoplay); + }(); } void _teardown(Control control) { @@ -294,4 +321,4 @@ class _VideoControlState extends State with FletStoreMixin { return ConstrainedControl(control: widget.control, child: video); } -} +} \ No newline at end of file From 8de487afbe8a8948a4f695ab663fbaafb262e97d Mon Sep 17 00:00:00 2001 From: Islam Asabaev <105982046+7576457@users.noreply.github.com> Date: Fri, 23 Jan 2026 11:23:24 -0800 Subject: [PATCH 3/4] fix: Enable TextButton style and full-width Dropdown (#6048) * fix: allow Dropdown to expand horizontally (#6044) * fix: apply ButtonStyle in TextButton (#6047) * fix: TextButton style handling; allow Dropdown to expand horizontally * fix(dropdown): correct expand logic Co-authored-by: TheEthicalBoy <98978078+ndonkoHenri@users.noreply.github.com> * fix(button): correctly resolve merged style without _internals --------- Co-authored-by: TheEthicalBoy <98978078+ndonkoHenri@users.noreply.github.com> --- packages/flet/lib/src/controls/button.dart | 2 +- packages/flet/lib/src/controls/dropdown.dart | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/flet/lib/src/controls/button.dart b/packages/flet/lib/src/controls/button.dart index c154ec97e7..3d2b276ad9 100644 --- a/packages/flet/lib/src/controls/button.dart +++ b/packages/flet/lib/src/controls/button.dart @@ -98,7 +98,7 @@ class _ButtonControlState extends State with FletStoreMixin { var theme = Theme.of(context); var style = parseButtonStyle( - widget.control.internals?["style"], + widget.control.internals?["style"] ?? widget.control.get("style"), theme, defaultForegroundColor: widget.control.getColor("color", context, theme.colorScheme.primary)!, diff --git a/packages/flet/lib/src/controls/dropdown.dart b/packages/flet/lib/src/controls/dropdown.dart index dc472f1d63..abaa6511ac 100644 --- a/packages/flet/lib/src/controls/dropdown.dart +++ b/packages/flet/lib/src/controls/dropdown.dart @@ -10,6 +10,7 @@ import '../utils/buttons.dart'; import '../utils/colors.dart'; import '../utils/edge_insets.dart'; import '../utils/form_field.dart'; +import '../utils/layout.dart'; import '../utils/menu.dart'; import '../utils/numbers.dart'; import '../utils/text.dart'; @@ -270,6 +271,9 @@ class _DropdownControlState extends State { _focusNode.canRequestFocus = editable; + int expand = widget.control.getExpand("expand", 0)!; + EdgeInsets? expandedInsets = expand > 0 ? EdgeInsets.zero : null; + Widget dropDown = DropdownMenu( enabled: !widget.control.disabled, focusNode: _focusNode, @@ -291,6 +295,7 @@ class _DropdownControlState extends State { hintText: widget.control.getString("hint_text"), helperText: widget.control.getString("helper_text"), menuStyle: menuStyle, + expandedInsets: expandedInsets, inputDecorationTheme: inputDecorationTheme, inputFormatters: inputFormatters.isEmpty ? null : inputFormatters, onSelected: widget.control.disabled From fc20412893db25c07515488389a26794af9689b8 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Fri, 23 Jan 2026 13:28:06 -0800 Subject: [PATCH 4/4] Update changelogs for v0.80.4 release notes (#6061) Added entries for TextButton style and full-width Dropdown fix, mpv_properties in VideoConfiguration, and Icons/CupertinoIcons proxy refactor. Also included Flutter 3.38.7 update in both root and package changelogs. --- CHANGELOG.md | 5 ++++- packages/flet/CHANGELOG.md | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae252dcf70..795302628f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ ## 0.80.4 -* Refactor `Icons` and `CupertinoIcons` proxies for member caching and iteration. +* fix: Enable TextButton style and full-width Dropdown ([#6048](https://github.com/flet-dev/flet/issues/6048)). +* flet-video: add mpv_properties to VideoConfiguration ([#6041](https://github.com/flet-dev/flet/issues/6041)). +* Refactor `Icons` and `CupertinoIcons` proxies for member caching and iteration ([#6055](https://github.com/flet-dev/flet/issues/6055)). +* Flutter 3.38.7. ## 0.80.3 diff --git a/packages/flet/CHANGELOG.md b/packages/flet/CHANGELOG.md index e21a0799bf..1516a63a16 100644 --- a/packages/flet/CHANGELOG.md +++ b/packages/flet/CHANGELOG.md @@ -1,5 +1,8 @@ ## 0.80.4 +* fix: Enable TextButton style and full-width Dropdown ([#6048](https://github.com/flet-dev/flet/issues/6048)). +* flet-video: add mpv_properties to VideoConfiguration ([#6041](https://github.com/flet-dev/flet/issues/6041)). +* Refactor `Icons` and `CupertinoIcons` proxies for member caching and iteration ([#6055](https://github.com/flet-dev/flet/issues/6055)). * Flutter 3.38.7. ## 0.80.3