Skip to content

Conversation

@ndonkoHenri
Copy link
Contributor

Fix #5470

Example:

import base64

import flet as ft
import flet_lottie as ftl

image_b64 = "iVBORw0KGgoAAAANSUhEUgAAABkAAAAgCAYAAADnnNMGAAAACXBIWXMAAAORAAADkQFnq8zdAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAA6dJREFUSImllltoHFUYx3/fzOzm0lt23ZrQ1AQbtBehNpvQohgkBYVo410RwQctNE3Sh0IfiiBoIAjqi6TYrKnFy4O3oiiRavDJFi3mXomIBmOxNZe63ay52GR3Zj4f2sTEzmx3m//TYf7/c35zvgPnO6KqrESXqpq3muocAikv6m+/zytj3ejik1VN21G31YA9CgJ6xC+bMyQZPVCuarciPAMYC99V6Vw5pLbFSibHmlVoRVj9P3cmPBM8tSJI/M6mzabpfoAQ9fIF7WK4bd5vvuFnLGgy2vi0abg94A0AcJGvMq3hDxGRyar9r4F+iLAm0yIiRk8m37tctS1WsrIhhrI30+Srmg+J87OXUf3lWGS1q89dC6ltsSanxk4Aj2QBABii96300g87P/rtlrWr8l+vyDMfdlXSyyEikqxsiOUAQJCBhfHdXRfCq1LSsSlcWG+KBAGStvvrMkgiuv8lUc2mREukPwLUfHG+uTQv8Eown7VL3XlbBxYhf1c17hbVF3MDwA9bts280TnaU1YYqPby07aeFlUlHt27wSQ4CLo+F8AvoTCvHmyKF+ZbEb/M77P2LgvAwmrTHAHflN3KZxVbMC2jMFNOpgPnrMSOhvvFkMezXdwV4ePbtvHtxnJAMQ0j4JtVnO+eLb5oiSlt5HDbv7t1O90lpYCCCKbhfzW5kAIwUAazR0BlfII8Ow0I6uoVmI9MyAMwbMs8CExmDbk4zgu931MyO4OI4KrYflkRjOoTI+uM9d1vjotwKPu9QMk/sxzuO8POiVFcdZ1M2YBVsMEAKOqLvaPIe7mACuw0z/80SMH58SMplxlfiDhVi7dw2pltRhjKBQTQdrSja2KKTfE551NHuaZ0QVPvWYQUn31/Vm2nDvgjF4grVJx6suSvrvrSJ/6cSW2Oz9mf264uNrB806xZ1k/CZ49dUKgDEtlCROX2hfHpx8pGuuo3PpqYulw8fjndOp1yhgtNKRevJ1FyR2Ola+jXAjdnwTkZ6o896GdWdxDw7IxFg+0DpmXchTKSBWQnIuJn9u4j7dt+13UfHXEkXQOcuQ4kMhVtqsgUyPiQiPQfHw1NB2sRjmXKuTg1NwwBYLhtPtQX26eqTwGXPDOqvmcC4Hnwfrrad94GrVsOYTqUTkQY+iTlNe/6O1miSP/x0VB/+wMIDwHn/vtV1iQC4Xv95uUEWVCoL9Y5Z+gdovoyMHUFJHv88jmVy0vTuw7cZNv2YaA61Bfb7ZX5F8SaUv2xwZevAAAAAElFTkSuQmCC"

with open("path/to/lottie.json", "rb") as f:
    lottie_bytes = f.read()


def main(page: ft.Page):
    page.add(
        ft.Row(
            controls=[
                # ftl.Lottie(src="lottie.json"),
                ftl.Lottie(
                    src="https://raw.githubusercontent.com/xvrh/lottie-flutter/master/example/assets/Mobilo/A.json",
                ),
                ftl.Lottie(src=lottie_bytes),
                ftl.Lottie(src=base64.b64encode(lottie_bytes).decode("utf-8")),
            ]
        ),
        ft.Row(
            controls=[
                # ft.Image(src="image.png", width=100, height=100),
                ft.Image(
                    src="https://flet.dev/img/logo.svg",
                    width=100,
                    height=100,
                ),
                ft.Image(
                    src=b64,
                    width=100,
                    height=100,
                ),
                ft.Image(
                    src=base64.b64decode(image_b64),
                    width=100,
                    height=100,
                ),
            ]
        ),
        ft.Row(
            controls=[
                ft.CircleAvatar(
                    foreground_image_src=image_b64,
                    width=100,
                    height=100,
                ),
                ft.CircleAvatar(
                    foreground_image_src=base64.b64decode(image_b64),
                    width=100,
                    height=100,
                ),
            ]
        ),
    )


if __name__ == "__main__":
    ft.run(main, assets_dir="assets")

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @ndonkoHenri, your pull request is larger than the review limit of 150000 diff characters

Copilot finished reviewing on behalf of ndonkoHenri November 15, 2025 23:21
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR consolidates three separate properties (src, src_base64, src_bytes) into a single intelligent src property that can automatically detect and handle URLs, file paths, base64-encoded strings, and raw bytes. This is a breaking change that simplifies the API across multiple controls (Image, Lottie, Audio, CircleAvatar, DecorationImage, Canvas.Image).

Key changes:

  • Python API now uses Union[str, bytes] for the src property
  • Dart implementation uses ResolvedAssetSource utility to intelligently parse the source
  • Documentation and examples updated to reflect the unified API
  • Tests updated to use the new consolidated property

Reviewed Changes

Copilot reviewed 32 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
circle_avatar.py Changed foreground_image_src and background_image_src to accept Union[str, bytes]
bottom_sheet.py Documentation improvement (unrelated to main change)
image.py Removed src_base64 and src_bytes, consolidated into src: Union[str, bytes]
canvas/image.py Removed src_bytes, updated src to Optional[Union[str, bytes]]
box.py Removed src_base64 and src_bytes from DecorationImage, updated copy method
lottie.dart Uses ResolvedAssetSource instead of separate base64 handling
lottie.py Removed src_base64, changed default for enable_merge_paths to True
audio.dart Uses ResolvedAssetSource with listEquals for bytes comparison
audio.py Removed src_base64, consolidated into src: Optional[Union[str, bytes]]
strings.dart Added isBase64 and stripBase64DataHeader() extension methods
Various test files Updated to use consolidated src property

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

"""

src: Optional[str] = None
src: Union[str, bytes]
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The src property should be Optional[Union[str, bytes]] instead of requiring it, as there may be cases where error_content needs to be shown without a source. Looking at other controls like canvas/image.py which uses Optional[Union[str, bytes]], this should be consistent.

Copilot uses AI. Check for mistakes.
"""

src: Optional[str] = None
src: Union[str, bytes]
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to Image control, the src property should be Optional[Union[str, bytes]] for consistency and to allow for optional rendering with error_content fallback.

Suggested change
src: Union[str, bytes]
src: Optional[Union[str, bytes]]

Copilot uses AI. Check for mistakes.
Comment on lines 27 to 37
bool get isBase64 {
var s = stripBase64DataHeader().replaceAll(RegExp(r'\s+'), '');

try {
final normalized = base64.normalize(s);
base64.decode(normalized);
return true;
} catch (_) {
return false;
}
}
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The isBase64 getter performs two operations: normalization and decoding. If this is called frequently, consider caching the result or avoiding the decode step if normalization is sufficient for validation. The decode operation allocates memory that's immediately discarded.

Copilot uses AI. Check for mistakes.
Comment on lines 3 to +14
int arrayIndexOf(Uint8List haystack, Uint8List needle) {
var len = needle.length;
var limit = haystack.length - len;
final len = needle.length;
if (len == 0) return 0;
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The edge case handling for empty needle returns 0, which could be confusing. Consider documenting why empty needle returns 0 (typically means 'found at start') or consider returning -1 for consistency with 'not found' semantics.

Copilot uses AI. Check for mistakes.
Comment on lines +95 to +96
} else if (resolvedSrc.bytes != null &&
(_srcBytes == null || !listEquals(_srcBytes, resolvedSrc.bytes))) {
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using listEquals for comparing potentially large audio byte arrays on every update could be expensive. Consider using a hash or length check as a quick first pass before doing full byte comparison, or storing a hash of the bytes for efficient comparison.

Copilot uses AI. Check for mistakes.
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Nov 16, 2025

Deploying flet-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: f366d55
Status:⚡️  Build in progress...

View logs

@ndonkoHenri ndonkoHenri linked an issue Nov 17, 2025 that may be closed by this pull request
1 task
# Conflicts:
#	sdk/python/packages/flet/integration_tests/controls/core/test_image.py
Replaced ResolvedAssetSource.from(...get('src')) with getSrc('src') in audio and lottie Dart files for improved asset source resolution. Cleaned up argument formatting and improved readability in lottie.dart. Updated brush.py to use src_bytes instead of src for file saving. Removed unused page argument and debug print statements from image_switch_buffered.py.
* Update Flutter version to 3.38.2 and dependencies

Bumped the required Flutter version to 3.38.2 in .fvmrc and build.py. Updated several Dart dependencies in pubspec.lock and removed path_provider_foundation from macOS plugin registration to reflect dependency changes.

* Update ci.yml

* Update Flutter cache key format in CI workflow

Revised the cache-key and pub-cache-key formats in the CI workflow to use placeholders (:os:, :channel:, :version:, :hash:) instead of GitHub Actions variables. This may improve cache management and compatibility with the flutter-fvm-config-action.

* Update Flutter cache keys to include architecture

Modified cache-key and pub-cache-key in CI and macOS integration workflows to include architecture. This improves cache granularity and prevents issues when running workflows on different architectures.

* Disable cache in Flutter FVM setup actions

Set 'cache' to false in the flutter-fvm-config-action setup steps for both CI and macOS integration test workflows. This change disables caching to potentially resolve issues related to cache usage or improve workflow reliability.

* Add Flutter caching to CI workflows

Introduces a cache step for Flutter in both CI and macOS integration test workflows using actions/cache. This improves build performance by reusing Flutter dependencies between runs.

* Add step to print Flutter cache outputs in CI

Introduces a step in both CI and macOS integration test workflows to print the Flutter cache path and key outputs. This aids in debugging and verifying cache configuration during workflow runs.

* Update Flutter setup in CI workflows

Replaces kuhnroyal/flutter-fvm-config-action/setup with subosito/flutter-action for Flutter setup in both ci.yml and macos-integration-tests.yml. Adds a separate step to configure Flutter version using .fvmrc and removes printing of Flutter outputs.

* Add spacing option to CupertinoCheckbox label

Introduces a 'spacing' property to CupertinoCheckbox for customizing the space between the checkbox and its label. Updates Dart and Python implementations, integration tests, and golden images to reflect this change. Also refactors test cases for improved clarity and coverage.

Flutter change: flutter/flutter#172502

* Update golden images for macOS material tests

Refreshed golden images for submenu button and time picker integration tests on macOS to reflect recent UI or rendering changes.

* Improve mouse gesture handling in FlutterWidgetTester

Introduces proper mouse pointer exit before tap, long press, and text entry actions to avoid lingering gestures. Updates mouse hover logic to manage gesture lifecycle. Also updates navigation bar test destinations and golden images for macOS time picker and navigation bar.

* Update dropdown theme_1.png golden image

Replaces the macOS dropdown theme_1.png golden image in integration tests to reflect updated visual output or design changes.

* Update golden image for macOS menu bar test

Replaces the menu_bar_basic_open.png golden image used in integration tests for the macOS menu bar control. This ensures test accuracy with the latest UI changes.

* Remove unnecessary mouse exit calls in FlutterWidgetTester

Eliminated redundant _mouseExit() calls before tap, longPress, and enterText actions in FlutterWidgetTester to streamline test interactions. Also updated golden image for navigation bar theme on macOS.

* Add 'persist' option to SnackBar control

Introduces a 'persist' property to the SnackBar control in Dart and Python, allowing developers to specify whether the snack bar should remain visible after the timeout. Updates documentation and example usage to reflect the new option.

Breaking change: https://docs.flutter.dev/release/breaking-changes/snackbar-with-action-behavior-update

* Make spacing property optional in CupertinoCheckbox

Changed the type of the spacing property from Number to Optional[Number] in CupertinoCheckbox to allow for None values and improve flexibility.
@FeodorFitsner FeodorFitsner merged commit 3fb8a83 into main Nov 23, 2025
7 of 36 checks passed
@FeodorFitsner FeodorFitsner deleted the unified-src branch November 23, 2025 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants