diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bd56efc20..65ee32fc4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: branches: - '**' tags: - - '*' + - 'v[0-9]+.[0-9]+.[0-9]+' paths: - '.github/workflows/ci.yml' - '.github/scripts/**' @@ -82,6 +82,9 @@ jobs: build_flet_package: name: Build Flet Flutter package runs-on: ubuntu-latest + permissions: + contents: read + id-token: write # Required for authentication using OIDC (pub.dev trusted publisher) outputs: PKG_VER: ${{ steps.versions.outputs.PKG_VER }} BUILD_VER: ${{ steps.versions.outputs.BUILD_VER }} @@ -111,25 +114,31 @@ jobs: working-directory: packages/flet run: flutter test + - name: Patch pubspec version for release + if: ${{ github.ref_type == 'tag' }} + shell: bash + working-directory: packages/flet + run: | + source "$SCRIPTS/common.sh" + patch_pubspec_version ./pubspec.yaml "$PKG_VER" + + - name: Install dependencies + shell: bash + working-directory: packages/flet + run: dart pub get + - name: Publish to pub.dev (Dry Run) shell: bash working-directory: packages/flet - run: dart pub publish --dry-run || exit 0 + run: dart pub publish --dry-run - name: Publish to pub.dev (Release) if: ${{ github.ref_type == 'tag' }} env: - PUB_DEV_TOKEN: ${{ secrets.PUB_DEV_TOKEN }} + PUB_ENVIRONMENT: github-actions shell: bash working-directory: packages/flet run: | - source "$SCRIPTS/common.sh" - mkdir -p "$HOME/.config/dart" - printf %s "$PUB_DEV_TOKEN" | base64 --decode > "$HOME/.config/dart/pub-credentials.json" - - # patch pubspec for release - patch_pubspec_version ./pubspec.yaml "$PKG_VER" - dart pub publish --force # ============================= diff --git a/client/pubspec.lock b/client/pubspec.lock index 4d35f1842..1ce7307e0 100644 --- a/client/pubspec.lock +++ b/client/pubspec.lock @@ -295,7 +295,7 @@ packages: path: "../packages/flet" relative: true source: path - version: "0.70.0" + version: "0.80.0" flet_ads: dependency: "direct main" description: diff --git a/packages/flet/CHANGELOG.md b/packages/flet/CHANGELOG.md index 1443f59c6..a90a0437c 100644 --- a/packages/flet/CHANGELOG.md +++ b/packages/flet/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.80.0 + +* **Flet 1.0 Beta Release** – [Read the announcement](https://flet.dev/blog/flet-1-0-beta) + # 0.70.0 * **Flet 1.0 Alpha Released** – [Read the announcement](https://flet.dev/blog/introducing-flet-1-0-alpha) diff --git a/packages/flet/lib/src/controls/button.dart b/packages/flet/lib/src/controls/button.dart index d741c4d35..c154ec97e 100644 --- a/packages/flet/lib/src/controls/button.dart +++ b/packages/flet/lib/src/controls/button.dart @@ -104,7 +104,7 @@ class _ButtonControlState extends State with FletStoreMixin { widget.control.getColor("color", context, theme.colorScheme.primary)!, defaultBackgroundColor: widget.control .getColor("bgcolor", context, theme.colorScheme.surface)!, - defaultOverlayColor: theme.colorScheme.primary.withOpacity(0.08), + defaultOverlayColor: theme.colorScheme.primary.withValues(alpha: 0.08), defaultShadowColor: theme.colorScheme.shadow, defaultSurfaceTintColor: theme.colorScheme.surfaceTint, defaultElevation: widget.control.getDouble("elevation", 1)!, diff --git a/packages/flet/lib/src/controls/cupertino_app_bar.dart b/packages/flet/lib/src/controls/cupertino_app_bar.dart index 6fac0f5d3..cb24be447 100644 --- a/packages/flet/lib/src/controls/cupertino_app_bar.dart +++ b/packages/flet/lib/src/controls/cupertino_app_bar.dart @@ -91,6 +91,7 @@ class CupertinoAppBarControl extends StatelessWidget final Color backgroundColor = CupertinoDynamicColor.maybeResolve( control.getColor("bgcolor", context), context) ?? CupertinoTheme.of(context).barBackgroundColor; - return backgroundColor.alpha == 0xFF; + final alpha8 = (backgroundColor.a * 255.0).round().clamp(0, 255); + return alpha8 == 0xFF; } } diff --git a/packages/flet/lib/src/controls/navigation_drawer.dart b/packages/flet/lib/src/controls/navigation_drawer.dart index 24a7159a5..a3d91e8cf 100644 --- a/packages/flet/lib/src/controls/navigation_drawer.dart +++ b/packages/flet/lib/src/controls/navigation_drawer.dart @@ -36,7 +36,6 @@ class _NavigationDrawerControlState extends State { debugPrint("NavigationDrawerControl build: ${widget.control.id}"); var selectedIndex = widget.control.getInt("selected_index", 0)!; - var endDrawer = widget.control.get("position") == "end"; if (_selectedIndex != selectedIndex) { _selectedIndex = selectedIndex; diff --git a/packages/flet/lib/src/controls/progress_bar.dart b/packages/flet/lib/src/controls/progress_bar.dart index 7278d97c7..348c3e278 100644 --- a/packages/flet/lib/src/controls/progress_bar.dart +++ b/packages/flet/lib/src/controls/progress_bar.dart @@ -28,6 +28,7 @@ class ProgressBarControl extends StatelessWidget { stopIndicatorColor: control.getColor("stop_indicator_color", context), stopIndicatorRadius: control.getDouble("stop_indicator_radius"), trackGap: control.getDouble("track_gap"), + // ignore: deprecated_member_use year2023: control.getBool( "year_2023"), // todo: deprecated and to be removed in future versions ); diff --git a/packages/flet/lib/src/controls/progress_ring.dart b/packages/flet/lib/src/controls/progress_ring.dart index 2b8242455..45efca077 100644 --- a/packages/flet/lib/src/controls/progress_ring.dart +++ b/packages/flet/lib/src/controls/progress_ring.dart @@ -31,6 +31,7 @@ class ProgressRingControl extends StatelessWidget { trackGap: control.getDouble("track_gap"), constraints: control.getBoxConstraints("size_constraints"), padding: control.getPadding("padding"), + // ignore: deprecated_member_use year2023: control.getBool( "year2023"), // todo: deprecated and to be removed in future versions ); diff --git a/packages/flet/lib/src/controls/search_bar.dart b/packages/flet/lib/src/controls/search_bar.dart index ef7941e65..91f682f06 100644 --- a/packages/flet/lib/src/controls/search_bar.dart +++ b/packages/flet/lib/src/controls/search_bar.dart @@ -26,7 +26,6 @@ class SearchBarControl extends StatefulWidget { class _SearchBarControlState extends State { late final SearchController _controller; - bool _focused = false; TextCapitalization? _textCapitalization; late final FocusNode _focusNode; String? _lastFocusValue; @@ -43,9 +42,6 @@ class _SearchBarControlState extends State { } void _onFocusChange() { - setState(() { - _focused = _focusNode.hasFocus; - }); widget.control.triggerEvent(_focusNode.hasFocus ? "focus" : "blur"); } diff --git a/packages/flet/lib/src/controls/segmented_button.dart b/packages/flet/lib/src/controls/segmented_button.dart index b995698e0..b4bf29d57 100644 --- a/packages/flet/lib/src/controls/segmented_button.dart +++ b/packages/flet/lib/src/controls/segmented_button.dart @@ -37,7 +37,7 @@ class _SegmentedButtonControlState extends State var style = widget.control.getButtonStyle("style", Theme.of(context), defaultForegroundColor: theme.colorScheme.primary, defaultBackgroundColor: theme.colorScheme.surface, - defaultOverlayColor: theme.colorScheme.primary.withOpacity(0.08), + defaultOverlayColor: theme.colorScheme.primary.withValues(alpha: 0.08), defaultShadowColor: theme.colorScheme.shadow, defaultSurfaceTintColor: theme.colorScheme.surfaceTint, defaultElevation: 1, diff --git a/packages/flet/lib/src/controls/slider.dart b/packages/flet/lib/src/controls/slider.dart index 4d0eb5c50..81e1c28fe 100644 --- a/packages/flet/lib/src/controls/slider.dart +++ b/packages/flet/lib/src/controls/slider.dart @@ -75,6 +75,7 @@ class _SliderControlState extends State { min: min, max: max, // todo: remove deprecated property year2023 + // ignore: deprecated_member_use year2023: widget.control.getBool("year_2023"), divisions: widget.control.getInt("divisions"), label: label?.replaceAll("{value}", _value.toStringAsFixed(round)), diff --git a/packages/flet/lib/src/controls/view.dart b/packages/flet/lib/src/controls/view.dart index 61831be88..cff69c6bf 100644 --- a/packages/flet/lib/src/controls/view.dart +++ b/packages/flet/lib/src/controls/view.dart @@ -16,7 +16,6 @@ import '../utils/buttons.dart'; import '../utils/colors.dart'; import '../utils/edge_insets.dart'; import '../utils/numbers.dart'; -import '../utils/platform.dart'; import '../utils/theme.dart'; import '../widgets/loading_page.dart'; import '../widgets/page_context.dart'; @@ -172,7 +171,6 @@ class _ViewControlState extends State { .addAll(dialogControls.map((c) => ControlWidget(control: c))); overlayWidgets.add(PageMedia(view: widget.control.parent)); } - } Widget body = Stack(children: [ diff --git a/packages/flet/lib/src/services/semantics_service.dart b/packages/flet/lib/src/services/semantics_service.dart index 0345d2d34..cc1a92183 100644 --- a/packages/flet/lib/src/services/semantics_service.dart +++ b/packages/flet/lib/src/services/semantics_service.dart @@ -26,8 +26,12 @@ class SemanticsServiceControl extends FletService { switch (name) { case "announce_message": var message = args["message"].toString(); - return SemanticsService.announce( - message, args["rtl"] ? TextDirection.rtl : TextDirection.ltr, + final view = WidgetsBinding.instance.platformDispatcher.implicitView; + if (view == null) { + return; + } + return SemanticsService.sendAnnouncement( + view, message, args["rtl"] ? TextDirection.rtl : TextDirection.ltr, assertiveness: control.getAssertiveness( args["assertiveness"], Assertiveness.polite)!); case "announce_tooltip": diff --git a/packages/flet/lib/src/transport/flet_backend_channel_mock.dart b/packages/flet/lib/src/transport/flet_backend_channel_mock.dart index 1555dd88b..f583f2381 100644 --- a/packages/flet/lib/src/transport/flet_backend_channel_mock.dart +++ b/packages/flet/lib/src/transport/flet_backend_channel_mock.dart @@ -24,13 +24,13 @@ class FletMockBackendChannel implements FletBackendChannel { await Future.delayed( const Duration(seconds: 1)); // Simulating async operation debugPrint("Connected to the Mock Flet backend channel"); - //_scenario_line_chart_simple(); - _scenario_register(); - //_scenario_test_services(); - //_scenario_call_window_methods(); + // _scenarioLineChartSimple(); + _scenarioRegister(); + // _scenarioTestServices(); + // scenarioCallWindowMethods(); } - _scenario_register() async { + Future _scenarioRegister() async { onMessage(Message(action: MessageAction.registerClient, payload: { "id": 1, "patch": { @@ -81,7 +81,8 @@ class FletMockBackendChannel implements FletBackendChannel { })); } - _scenario_line_chart_simple() async { + // ignore: unused_element + Future _scenarioLineChartSimple() async { onMessage(Message(action: MessageAction.registerClient, payload: { "id": 1, "patch": { @@ -169,7 +170,8 @@ class FletMockBackendChannel implements FletBackendChannel { })); } - _scenario_test_services() async { + // ignore: unused_element + Future _scenarioTestServices() async { onMessage(Message(action: MessageAction.patchControl, payload: { "id": 11, "patch": { @@ -212,7 +214,7 @@ class FletMockBackendChannel implements FletBackendChannel { // payload: {"id": 9, "name": "close", "args": {}})); } - scenario_call_window_methods() async { + Future scenarioCallWindowMethods() async { onMessage(Message( action: MessageAction.invokeControlMethod, payload: {"id": 9, "name": "to_front", "args": {}})); diff --git a/packages/flet/lib/src/utils/colors.dart b/packages/flet/lib/src/utils/colors.dart index 377845857..552f817e1 100644 --- a/packages/flet/lib/src/utils/colors.dart +++ b/packages/flet/lib/src/utils/colors.dart @@ -200,7 +200,7 @@ extension HexColor on Color { } if (color != null && colorOpacity != null) { - color = color.withOpacity(parseDouble(colorOpacity, 1.0)!); + color = color.withValues(alpha: parseDouble(colorOpacity, 1.0)!); } return color ?? defaultColor; @@ -262,11 +262,21 @@ extension HexColor on Color { } /// Prefixes a hash sign if [leadingHashSign] is set to `true` (default is `true`). - String toHex({bool leadingHashSign = true}) => '${leadingHashSign ? '#' : ''}' - '${alpha.toRadixString(16).padLeft(2, '0')}' - '${red.toRadixString(16).padLeft(2, '0')}' - '${green.toRadixString(16).padLeft(2, '0')}' - '${blue.toRadixString(16).padLeft(2, '0')}'; + String toHex({bool leadingHashSign = true}) { + int to8bit(double component) => + (component * 255.0).round().clamp(0, 255); + + final alpha8 = to8bit(a); + final red8 = to8bit(r); + final green8 = to8bit(g); + final blue8 = to8bit(b); + + return '${leadingHashSign ? '#' : ''}' + '${alpha8.toRadixString(16).padLeft(2, '0')}' + '${red8.toRadixString(16).padLeft(2, '0')}' + '${green8.toRadixString(16).padLeft(2, '0')}' + '${blue8.toRadixString(16).padLeft(2, '0')}'; + } } extension ColorExtension on Color { @@ -274,11 +284,14 @@ extension ColorExtension on Color { Color darken([int percent = 40]) { assert(1 <= percent && percent <= 100); final value = 1 - percent / 100; + int to8bit(double component) => + (component * 255.0).round().clamp(0, 255); + return Color.fromARGB( - alpha, - (red * value).round(), - (green * value).round(), - (blue * value).round(), + to8bit(a), + (to8bit(r) * value).round().clamp(0, 255), + (to8bit(g) * value).round().clamp(0, 255), + (to8bit(b) * value).round().clamp(0, 255), ); } } diff --git a/packages/flet/pubspec.yaml b/packages/flet/pubspec.yaml index e0f280973..3374cfbdf 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/packages/flet -version: 0.70.0 +version: 0.80.0 # Supported platforms platforms: @@ -27,12 +27,12 @@ dependencies: device_info_plus: ^12.3.0 equatable: ^2.0.3 file_picker: ^10.3.3 - flutter_highlight: 0.7.0 - flutter_markdown: 0.7.6+2 - flutter_svg: 2.2.1 + flutter_highlight: ^0.7.0 + flutter_markdown: ^0.7.6+2 + flutter_svg: ^2.2.1 highlight: ^0.7.0 - http: 1.5.0 - markdown: 7.3.0 + http: ^1.5.0 + markdown: ^7.3.0 msgpack_dart: ^1.0.1 path: ^1.9.0 path_provider: ^2.1.5 @@ -40,10 +40,10 @@ dependencies: screenshot: ^3.0.0 screen_brightness: ^2.1.7 sensors_plus: ^7.0.0 - shared_preferences: 2.5.3 + shared_preferences: ^2.5.3 share_plus: ^12.0.1 shimmer: ^3.0.0 - url_launcher: 6.3.2 + url_launcher: ^6.3.2 vector_math: ^2.2.0 web: ^1.1.1 web_socket_channel: ^3.0.2