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: a31b0a0
Status: ✅  Deploy successful!
Preview URL: https://f8ddf9f9.flet-docs.pages.dev
Branch Preview URL: https://unified-src.flet-docs.pages.dev

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: V1: Slider on_change data is None v1: Harmonize src attribute across controls

3 participants