Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .fvmrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"flutter": "3.47.7"
"flutter": "3.47.8"
}
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
* Add `Theme.markdown_theme`: a default `MarkdownStyleSheet` for every `Markdown`, with a control's own `md_style_sheet` applied on top property by property by @FeodorFitsner.
* Add `PopupMenuTheme.border_radius` to set the default hover/splash corner radius of every `PopupMenuButton` by @FeodorFitsner.

* Bump the bundled Flutter to [3.47.7](https://github.com/flutter/flutter/blob/stable/CHANGELOG.md#3477) (from 3.44.8). Android builds use Gradle 9.3.1, Android Gradle Plugin 8.13.2 and Kotlin 2.3.21 by @ndonkoHenri.
* Bump the bundled Flutter to [3.47.8](https://github.com/flutter/flutter/blob/stable/CHANGELOG.md#3478) (from 3.44.8). Android builds use Gradle 9.3.1, Android Gradle Plugin 8.13.2 and Kotlin 2.3.21 ([#6916](https://github.com/flet-dev/flet/pull/6916), [#7023](https://github.com/flet-dev/flet/pull/7023)) by @ndonkoHenri.

**Compatibility:** Desktop apps and the desktop app that `flet run` opens now render with Impeller, Flutter 3.47's default desktop renderer, instead of Skia. Use `flet build --no-impeller` (or `impeller = false` under `[tool.flet]`), `flet run --no-impeller` or the `FLET_NO_IMPELLER` environment variable to render with Skia; see [Renderer](/docs/publish#renderer). Android plugins that still use `jcenter()` or other APIs removed in Gradle 9 no longer build. `flet build` downloads Flutter 3.47.7 on first use.

Expand All @@ -59,14 +59,14 @@

### Bug fixes

* Fix `use_state()` type inference for callable initializers in mypy and ty ([#6960](https://github.com/flet-dev/flet/issues/6960), [#7014](https://github.com/flet-dev/flet/pull/7014)) by @mmporong.
* Fix `use_state()` and `use_ref()` type inference for callable initializers in mypy and ty ([#6960](https://github.com/flet-dev/flet/issues/6960), [#7014](https://github.com/flet-dev/flet/pull/7014), [#7023](https://github.com/flet-dev/flet/pull/7023)) by @mmporong.
* Fix `flet build` apps showing a blank page when the system suspended them while Python was starting, such as when iOS launches an app in the background for a notification action ([#6999](https://github.com/flet-dev/flet/pull/6999)) by @ndonkoHenri.
* Fix `flet build` naming a Linux app's icons `None.png` and leaving the iOS frameworks it builds from the app's packages under shared identifiers when no `bundle_id` is set ([#6999](https://github.com/flet-dev/flet/pull/6999)) by @ndonkoHenri.
* Fix `flet build` writing numbers in `[tool.flet.macos.entitlement]`, `[tool.flet.ios.info]` and `[tool.flet.macos.info]` as strings, producing invalid plists when keys or values contain `&` or `<`, and failing when a `pyproject.toml` value contains `{{` ([#6999](https://github.com/flet-dev/flet/pull/6999)) by @ndonkoHenri.
* Fix `FilePicker` dialogs failing with a timeout after being open for an hour ([#6999](https://github.com/flet-dev/flet/pull/6999)) by @ndonkoHenri.
* Fix `flet build` failing on every rebuild after one with changed build options, in apps with Flutter extensions ([#7010](https://github.com/flet-dev/flet/issues/7010), [#7012](https://github.com/flet-dev/flet/pull/7012)) by @ndonkoHenri.
* Fix `flet build` not reinstalling the app's packages after `requirements.txt` is edited or `build/site-packages` is deleted ([#6994](https://github.com/flet-dev/flet/issues/6994), [#6996](https://github.com/flet-dev/flet/pull/6996)) by @ndonkoHenri.
* Fix `flet test` failing when the app under test starts slowly, as on the first run after a build: the test now waits until the app finishes initializing its first page ([#6993](https://github.com/flet-dev/flet/issues/6993), [#6995](https://github.com/flet-dev/flet/pull/6995)) by @ndonkoHenri.
* Fix `flet test` failing when the app under test starts slowly, as on the first run after a build: the test now waits until the app finishes initializing its first page, and fails right away with the Python traceback when the app's Python program fails to start ([#6993](https://github.com/flet-dev/flet/issues/6993), [#6995](https://github.com/flet-dev/flet/pull/6995), [#7023](https://github.com/flet-dev/flet/pull/7023)) by @ndonkoHenri.
* Fix `use_effect()` cleanups being skipped: a cleanup returned by the setup was lost once the component re-rendered, only one ran when `cleanup=` was passed too, and `async` cleanups never ran when a dependency change re-ran the effect. A pending `async` setup is also cancelled on unmount ([#6963](https://github.com/flet-dev/flet/issues/6963), [#6983](https://github.com/flet-dev/flet/pull/6983), [#7005](https://github.com/flet-dev/flet/pull/7005)) by @mangod12.
* iOS apps built with `flet build ipa` no longer fail App Store Connect validation with ITMS-90683 (missing `NSPhotoLibraryUsageDescription` and `NSCameraUsageDescription` purpose strings): the `file_picker` plugin is updated to 13.x, which picks photos with the system photo picker and no longer links DKImagePickerController's camera and photo-library code. `device_info_plus`, `package_info_plus` and `share_plus` move to their next major versions with it (`win32` 6). `FilePicker.save_file()` on desktop now creates the chosen file (empty when no `src_bytes` are given) before returning its path by @FeodorFitsner.
* Fix `Tester.find_by_key()` not finding `Tab` and `PopupMenuItem` controls by their keys ([#6965](https://github.com/flet-dev/flet/issues/6965), [#6976](https://github.com/flet-dev/flet/pull/6976)) by @RezaShamsipour.
Expand Down
2 changes: 1 addition & 1 deletion packages/flet/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 1.1.0

* Flutter updated to [3.47.8](https://github.com/flutter/flutter/blob/stable/CHANGELOG.md#3478).
* Update `file_picker` to 13.x (federated; iOS picks media with `PHPickerViewController`, dropping DKImagePickerController, whose camera and photo-library references made App Store Connect demand purpose strings). `FilePickerService` uses `pickFile()`/`pickFiles()`, reads bytes and uploads through `PlatformFile.readAsBytes()`/`readAsByteStream()`, passes `lockParentWindow` through `WindowsOptions`/`LinuxOptions` and `cancel_upload_on_window_blur` through `file_picker_web`'s `FilePickerWebOptions` (imported only on web). `saveFile()` always writes the file, so desktop saves without `src_bytes` create it empty. Bump `device_info_plus` to ^13.3.0, `package_info_plus` to ^10.2.2 and `share_plus` to ^13.3.1 (`win32` 6, required by file_picker 13's Windows implementation) by @FeodorFitsner.
* Apply `min_width`/`max_width`/`min_height`/`max_height` to every `LayoutControl` as a `ConstrainedBox` around the control (outside any fixed size). A control that implements one of these names itself lists it in `skip_properties` (`ListTile.min_height`, `NavigationRail.min_width`) by @FeodorFitsner.
* Pass `material_tap_target_size` to `Switch` and `ThemeData` (`parseMaterialTapTargetSize()`) by @FeodorFitsner.
Expand All @@ -22,7 +23,6 @@
* An embedded page builds its `Navigator` with `requestFocus: false`, so pushing its routes doesn't move the focus out of the host app by @FeodorFitsner.
* `PageControl` wraps an embedded page's app in a `CupertinoTheme` derived from the page's own Material theme (top-level pages are unchanged). Flutter's `Theme` reuses an ambient `CupertinoTheme` when one exists above it instead of deriving one from its `ThemeData`, so an embedded page's Cupertino widgets took the host app's colors by @FeodorFitsner.
* `CupertinoButtonControl` falls back to the `ButtonStyle` in `internals["style"]` - what an adaptive Material `Button` sends - for background, foreground and padding when `bgcolor`/`color`/`padding` are absent by @FeodorFitsner.
* Flutter updated to [3.47.7](https://github.com/flutter/flutter/blob/stable/CHANGELOG.md#3477).
* **Breaking:** `parseTheme()` now builds themes from a seed with neutral surfaces by default (`#ffffff` / `#121212` and a neutral grey ramp for surface containers, `onSurface`, `outline` and inverse surfaces); the seed still drives accent colors. A theme's `surfaces: "tonal"` restores the seed-tinted Material 3 surfaces. Adds the `ThemeSurfaces` enum, `parseThemeSurfaces()` and `neutralizeSurfaces()` ([#6921](https://github.com/flet-dev/flet/issues/6921)) by @FeodorFitsner.
* Import Material and Cupertino from the `material_ui` and `cupertino_ui` packages instead of `package:flutter/material.dart` and `package:flutter/cupertino.dart`. Helpers that take or return Material or Cupertino types, such as `parseColor()`, `parseTextStyle()` and `parseButtonStyle()`, now use those packages' types, and `flet.dart` no longer re-exports `Icons` and `CupertinoIcons`. Requires Flutter 3.47 or later.
* Add `markdownStyleSheetFromTheme()`, which builds the default `MarkdownStyleSheet` from a `material_ui` theme. `MarkdownStyleSheet.fromTheme()` from `flutter_markdown_plus` only accepts the Flutter SDK's `ThemeData`.
Expand Down
10 changes: 10 additions & 0 deletions packages/flet_integration_test/lib/src/app_startup.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,22 @@ import 'package:flutter_test/flutter_test.dart';
/// the first launch after a build, when antivirus software scans the bundle,
/// so a fixed number of frames is not enough. Throws when the app reports a
/// startup error or has not loaded within [timeout].
///
/// A startup error includes the embedded Python program failing before it
/// connects, such as an exception raised while importing the app's modules.
/// The app reports that on its boot screen rather than through the Flet
/// protocol, so the thrown exception carries the boot screen's error text,
/// including the Python traceback.
Future<void> waitForAppLoaded(WidgetTester tester,
{Duration timeout = const Duration(minutes: 2)}) async {
final deadline = tester.binding.clock.now().add(timeout);
while (true) {
await tester.pump(const Duration(milliseconds: 100));
final backend = _findFletBackend(tester);
final bootError = backend?.bootStatus.value.error;
if (bootError != null && bootError.isNotEmpty) {
throw Exception("The app failed to start:\n$bootError");
}
if (backend != null && !backend.isLoading) {
if (backend.error.isNotEmpty) {
throw Exception("The app failed to start: ${backend.error}");
Expand Down
16 changes: 16 additions & 0 deletions packages/flet_integration_test/test/app_startup_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,22 @@ void main() {
contains('Initialization failed'))));
});

testWidgets('a Python program that fails to start fails with its traceback',
(tester) async {
final backend = await _mountApp(tester);
// The embedded Python program exits before it connects, so the backend
// is still loading and only the boot screen shows the error.
Timer(const Duration(milliseconds: 300), () {
backend.bootStatus.value = const BootStatus(BootStage.startingUp,
error: "ModuleNotFoundError: No module named 'pydantic_core'");
});

await expectLater(
() => waitForAppLoaded(tester),
throwsA(isA<Exception>().having((e) => e.toString(), 'message',
contains("No module named 'pydantic_core'"))));
});

testWidgets('a registered app that never initializes times out',
(tester) async {
final backend = await _mountApp(tester);
Expand Down
16 changes: 15 additions & 1 deletion sdk/python/packages/flet/src/flet/components/hooks/use_ref.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from collections.abc import Callable
from dataclasses import dataclass
from typing import Generic, TypeVar
from typing import Any, Generic, TypeVar, overload

from flet.components.hooks.hook import Hook
from flet.components.utils import current_component
Expand Down Expand Up @@ -35,6 +35,20 @@ class RefHook(Hook, Generic[RefValueT]):
ref: MutableRef[RefValueT]


@overload
def use_ref(initial_value: None = None) -> MutableRef[Any]: ...


@overload
def use_ref(initial_value: Callable[[], RefValueT]) -> MutableRef[RefValueT]: ...


@overload
def use_ref(
initial_value: RefValueT | Callable[[], RefValueT],
) -> MutableRef[RefValueT]: ...


def use_ref(
initial_value: RefValueT | Callable[[], RefValueT] | None = None,
) -> MutableRef[RefValueT]:
Expand Down
Loading