diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml new file mode 100644 index 0000000000..8effaec2a7 --- /dev/null +++ b/.github/workflows/build-test.yml @@ -0,0 +1,193 @@ + +name: Flet Build Test + +on: + push: + paths: + - '.github/workflows/build-test.yml' + - '.fvmrc' + - 'client/**' + - 'sdk/python/packages/**' + - 'packages/flet/**' + - 'sdk/python/examples/apps/flet_build_test' + pull_request: + paths: + - '.github/workflows/build-test.yml' + - '.fvmrc' + - 'client/**' + - 'sdk/python/packages/**' + - 'packages/flet/**' + - 'sdk/python/examples/apps/flet_build_test' + workflow_dispatch: + +concurrency: + group: ci-${{ github.workflow }}-${{ github.event.pull_request.head.ref || github.ref_name }} + cancel-in-progress: true + +env: + UV_PYTHON: 3.12 + PYTHONUTF8: 1 + + # https://docs.flet.dev/publish/ + BUILD_NUMBER: 1 + BUILD_VERSION: 1.0.0 + TEMPLATE_REF: 0.81.0 + + # https://docs.flet.dev/reference/environment-variables + FLET_CLI_NO_RICH_OUTPUT: 1 + +jobs: + build: + name: Build (${{ matrix.name }}) + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + # -------- Desktop -------- + - name: linux + runner: ubuntu-latest + build_cmd: "flet build linux --yes --verbose --build-number=$BUILD_NUMBER --build-version=$BUILD_VERSION" + artifact_name: linux-build-artifact + artifact_path: build/linux + needs_linux_deps: true + + - name: macos + runner: macos-latest + build_cmd: "flet build macos --yes --verbose --build-number=$BUILD_NUMBER --build-version=$BUILD_VERSION" + artifact_name: macos-build-artifact + artifact_path: build/macos + needs_linux_deps: false + + - name: windows + runner: windows-latest + build_cmd: "flet build windows --yes --verbose --no-rich-output --build-number=$BUILD_NUMBER --build-version=$BUILD_VERSION" + artifact_name: windows-build-artifact + artifact_path: build/windows + needs_linux_deps: false + + # -------- Android -------- + - name: aab-ubuntu + runner: ubuntu-latest + build_cmd: "flet build aab --yes --verbose --build-number=$BUILD_NUMBER --build-version=$BUILD_VERSION" + artifact_name: aab-build-ubuntu-artifact + artifact_path: build/aab + needs_linux_deps: false + + - name: aab-macos + runner: macos-latest + build_cmd: "flet build aab --yes --verbose --build-number=$BUILD_NUMBER --build-version=$BUILD_VERSION" + artifact_name: aab-build-macos-artifact + artifact_path: build/aab + needs_linux_deps: false + + - name: aab-windows + runner: windows-latest + build_cmd: "flet build aab --yes --verbose --build-number=$BUILD_NUMBER --build-version=$BUILD_VERSION" + artifact_name: aab-build-windows-artifact + artifact_path: build/aab + needs_linux_deps: false + + - name: apk-ubuntu + runner: ubuntu-latest + build_cmd: "flet build apk --yes --verbose --build-number=$BUILD_NUMBER --build-version=$BUILD_VERSION" + artifact_name: apk-build-ubuntu-artifact + artifact_path: build/apk + needs_linux_deps: false + + - name: apk-macos + runner: macos-latest + build_cmd: "flet build apk --yes --verbose --build-number=$BUILD_NUMBER --build-version=$BUILD_VERSION" + artifact_name: apk-build-macos-artifact + artifact_path: build/apk + needs_linux_deps: false + + - name: apk-windows + runner: windows-latest + build_cmd: "flet build apk --yes --verbose --build-number=$BUILD_NUMBER --build-version=$BUILD_VERSION" + artifact_name: apk-build-windows-artifact + artifact_path: build/apk + needs_linux_deps: false + + # -------- iOS -------- + - name: ipa + runner: macos-latest + build_cmd: "flet build ipa --yes --verbose --build-number=$BUILD_NUMBER --build-version=$BUILD_VERSION" + artifact_name: ipa-build-artifact + artifact_path: build/ipa + needs_linux_deps: false + + # -------- Web -------- + - name: web-ubuntu + runner: ubuntu-latest + build_cmd: "flet build web --yes --verbose" + artifact_name: web-build-ubuntu-artifact + artifact_path: build/web + needs_linux_deps: false + + - name: web-macos + runner: macos-latest + build_cmd: "flet build web --yes --verbose" + artifact_name: web-build-macos-artifact + artifact_path: build/web + needs_linux_deps: false + + - name: web-windows + runner: windows-latest + build_cmd: "flet build web --yes --verbose" + artifact_name: web-build-windows-artifact + artifact_path: build/web + needs_linux_deps: false + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup uv + uses: astral-sh/setup-uv@v6 + + - name: Install Linux dependencies + if: matrix.needs_linux_deps + shell: bash + run: | + sudo apt update --allow-releaseinfo-change + sudo apt-get install -y --no-install-recommends \ + clang \ + ninja-build \ + libgtk-3-dev \ + libasound2-dev \ + libmpv-dev \ + mpv \ + libgstreamer1.0-dev \ + libgstreamer-plugins-base1.0-dev \ + libgstreamer-plugins-bad1.0-dev \ + gstreamer1.0-plugins-base \ + gstreamer1.0-plugins-good \ + gstreamer1.0-plugins-bad \ + gstreamer1.0-plugins-ugly \ + gstreamer1.0-libav \ + gstreamer1.0-tools \ + gstreamer1.0-x \ + gstreamer1.0-alsa \ + gstreamer1.0-gl \ + gstreamer1.0-gtk3 \ + gstreamer1.0-qt5 \ + gstreamer1.0-pulseaudio \ + pkg-config \ + libsecret-1-0 \ + libsecret-1-dev + sudo apt-get clean + + - name: Build app + shell: bash + working-directory: sdk/python/examples/apps/flet_build_test + run: | + uv run ${{ matrix.build_cmd }} --template-ref 0.81.0 + + - name: Upload Artifact + uses: actions/upload-artifact@v5.0.0 + with: + name: ${{ matrix.artifact_name }} + path: ${{ matrix.artifact_path }} + if-no-files-found: warn + overwrite: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8a2f1abaf..0a01d886b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,26 +1,26 @@ name: Build & Publish on: - push: - branches: - - '**' - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - paths: - - '.github/workflows/ci.yml' - - '.github/scripts/**' - - 'client/**' - - 'sdk/python/packages/**' - - 'packages/flet/**' - - '.fvmrc' - pull_request: - paths: - - '.github/workflows/ci.yml' - - '.github/scripts/**' - - 'client/**' - - 'sdk/python/packages/**' - - 'packages/flet/**' - - '.fvmrc' +# push: +# branches: +# - '**' +# tags: +# - 'v[0-9]+.[0-9]+.[0-9]+' +# paths: +# - '.github/workflows/ci.yml' +# - '.github/scripts/**' +# - 'client/**' +# - 'sdk/python/packages/**' +# - 'packages/flet/**' +# - '.fvmrc' +# pull_request: +# paths: +# - '.github/workflows/ci.yml' +# - '.github/scripts/**' +# - 'client/**' +# - 'sdk/python/packages/**' +# - 'packages/flet/**' +# - '.fvmrc' workflow_dispatch: permissions: diff --git a/.github/workflows/macos-integration-tests.yml b/.github/workflows/macos-integration-tests.yml index bf6ab18b47..acaa8781e7 100644 --- a/.github/workflows/macos-integration-tests.yml +++ b/.github/workflows/macos-integration-tests.yml @@ -1,22 +1,22 @@ name: macOS Integration Tests on: - push: - paths: - - '.github/workflows/macos-integration-tests.yml' - - 'sdk/python/packages/flet/src/**' - - 'sdk/python/packages/flet/integration_tests/**' - - 'packages/flet/**' - - 'client/**' - - '.fvmrc' - pull_request: - paths: - - '.github/workflows/macos-integration-tests.yml' - - 'sdk/python/packages/flet/src/**' - - 'sdk/python/packages/flet/integration_tests/**' - - 'packages/flet/**' - - 'client/**' - - '.fvmrc' +# push: +# paths: +# - '.github/workflows/macos-integration-tests.yml' +# - 'sdk/python/packages/flet/src/**' +# - 'sdk/python/packages/flet/integration_tests/**' +# - 'packages/flet/**' +# - 'client/**' +# - '.fvmrc' +# pull_request: +# paths: +# - '.github/workflows/macos-integration-tests.yml' +# - 'sdk/python/packages/flet/src/**' +# - 'sdk/python/packages/flet/integration_tests/**' +# - 'packages/flet/**' +# - 'client/**' +# - '.fvmrc' workflow_dispatch: # Ensure only one run per branch (PR or push), cancel older ones diff --git a/sdk/python/.pre-commit-config.yaml b/sdk/python/.pre-commit-config.yaml index 8458583dbf..68386d07c7 100644 --- a/sdk/python/.pre-commit-config.yaml +++ b/sdk/python/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.7 + rev: v0.14.13 hooks: # Run the linter. - id: ruff @@ -16,7 +16,7 @@ repos: - id: sort-all - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: end-of-file-fixer - id: trailing-whitespace diff --git a/sdk/python/Taskfile.yml b/sdk/python/Taskfile.yml index 5ea1bc715a..ad2c9302e3 100644 --- a/sdk/python/Taskfile.yml +++ b/sdk/python/Taskfile.yml @@ -13,18 +13,40 @@ tasks: - task --list setup: - desc: "Setup environment by installing all pyproject.toml dependencies and pre-commit hooks." + desc: "Setup/Sync environment by installing all Python dependencies and pre-commit hooks." + aliases: + - sync cmds: - - task: install - - task: pre-commit-install + - task: uv sync --group all + - task: pre-commit - venv-init: + venv: desc: "Initialize virtual environment." - aliases: - - venv cmds: - uv venv + pre-commit: + desc: "Install pre-commit hooks." + aliases: + - pc + - sync-pc + cmds: + - uv run pre-commit install + + pre-commit-run: + desc: "Run pre-commit hooks on all files of the repo." + aliases: + - run-pc + cmds: + - uv run pre-commit run --all-files + + pre-commit-update: + desc: "Upgrade versions of repos in .pre-commit-config.yaml to their latest." + aliases: + - update-pc + cmds: + - uv run pre-commit autoupdate + unit-tests: desc: "Run all unit tests." aliases: @@ -35,93 +57,29 @@ tasks: - uv run --group test pytest packages/flet/tests integration-tests: - desc: "Run all integration tests." + desc: "Run all integration tests. (can take a long while)" aliases: - itest - integration-test cmds: - - uv run pytest -s -o log_cli=true -o log_cli_level=DEBUG packages/flet/integration_tests - - control-integration-tests: - desc: "Run all controls integration tests." - aliases: - - control-itest - - control-integration-test - cmds: - - uv run pytest -s -o log_cli=true -o log_cli_level=DEBUG packages/flet/integration_tests/controls - - install: - desc: "Install all pyproject.toml dependencies present in 'all' dependency-group." - aliases: - - pyproject - - pyproject-setup - cmds: - - uv pip install -r pyproject.toml --group all + - uv run --group test pytest -s -o log_cli=true -o log_cli_level=DEBUG packages/flet/integration_tests serve-docs: desc: "Serve MkDocs documentation from the 'packages/flet' directory." aliases: - docs cmds: - - uv run --directory packages/flet --group docs mkdocs serve --dirtyreload + - uv run -group docs --directory packages/flet mkdocs serve --dirtyreload docs-coverage: desc: "Run docstring coverage report in the 'packages/flet' directory." cmds: - - uv run --directory packages/flet --group docs-coverage docstr-coverage - - pre-commit-install: - desc: "Install pre-commit hooks." - aliases: - - precommit-install - - pc-install - cmds: - - uv run pre-commit install - - pre-commit-run: - desc: "Run pre-commit hooks on all files of the repo." - aliases: - - precommit-run - - pc-run - cmds: - - uv run pre-commit run --all-files - - pre-commit-autoupdate: - desc: "Upgrade versions of repos in .pre-commit-config.yaml to their latest." - aliases: - - pc-update - - pc-autoupdate - - pre-commit-autoupdate - - precommit-autoupdate - cmds: - - uv run pre-commit autoupdate + - uv run -group docs-coverage --directory packages/flet docstr-coverage free-port-8550: desc: "Frees Unix port 8550 by killing any process using it. Useful when you receive 'Address already in use' error." prompt: "This will kill any process using port 8550. Do you want to continue?" aliases: - - free-port - free-8550 cmds: - kill -9 $(lsof -ti :8550) - - extensions-pre-commit-install: - desc: "Installs pre-commit hooks of all extensions." - aliases: - - pc-extensions - - extensions-pre-commit - - extensions-precommit - cmds: - - uv run --package flet-ads pre-commit install - - uv run --package flet-audio pre-commit install - - uv run --package flet-audio-recorder pre-commit install - - uv run --package flet-charts pre-commit install - - uv run --package flet-datatable2 pre-commit install - - uv run --package flet-flashlight pre-commit install - - uv run --package flet-geolocator pre-commit install - - uv run --package flet-lottie pre-commit install - - uv run --package flet-map pre-commit install - - uv run --package flet-permission-handler pre-commit install - - uv run --package flet-rive pre-commit install - - uv run --package flet-video pre-commit install - - uv run --package flet-webview pre-commit install diff --git a/sdk/python/examples/apps/flet_build_test/README.md b/sdk/python/examples/apps/flet_build_test/README.md new file mode 100644 index 0000000000..be8dd3ca47 --- /dev/null +++ b/sdk/python/examples/apps/flet_build_test/README.md @@ -0,0 +1,3 @@ +# flet-build-test + +A minimal Flet app used to validate the [`flet build`](https://docs.flet.dev/cli/flet-build/) across platforms. diff --git a/sdk/python/examples/apps/flet_build_test/pyproject.toml b/sdk/python/examples/apps/flet_build_test/pyproject.toml new file mode 100644 index 0000000000..11960ff58c --- /dev/null +++ b/sdk/python/examples/apps/flet_build_test/pyproject.toml @@ -0,0 +1,85 @@ +[project] +name = "flet_build_test" +version = "0.1.0" +description = "App to test flet build." +requires-python = ">=3.10" +authors = [{ name = "Appveyor Systems Inc.", email = "hello@flet.dev" }] + +dependencies = [ + "flet", + "flet-ads", + "flet-audio", + "flet-audio-recorder", + "flet-charts", + "flet-datatable2", + "flet-flashlight", + "flet-geolocator", + "flet-lottie", + "flet-map", + "flet-permission-handler", + "flet-rive", + "flet-secure-storage", + "flet-video", + "flet-webview", +] + +[dependency-groups] +dev = [ + "flet-cli", + "flet-desktop", + "flet-desktop-light", + "flet-web", +] + +[tool.uv.sources] +flet = { path = "../../../packages/flet", editable = true } +flet-cli = { path = "../../../packages/flet-cli", editable = true } +flet-desktop = { path = "../../../packages/flet-desktop", editable = true } +flet-desktop-light = { path = "../../../packages/flet-desktop-light", editable = true } +flet-web = { path = "../../../packages/flet-web", editable = true } +flet-ads = { path = "../../../packages/flet-ads", editable = true } +flet-audio = { path = "../../../packages/flet-audio", editable = true } +flet-audio-recorder = { path = "../../../packages/flet-audio-recorder", editable = true } +flet-charts = { path = "../../../packages/flet-charts", editable = true } +flet-datatable2 = { path = "../../../packages/flet-datatable2", editable = true } +flet-flashlight = { path = "../../../packages/flet-flashlight", editable = true } +flet-geolocator = { path = "../../../packages/flet-geolocator", editable = true } +flet-lottie = { path = "../../../packages/flet-lottie", editable = true } +flet-map = { path = "../../../packages/flet-map", editable = true } +flet-permission-handler = { path = "../../../packages/flet-permission-handler", editable = true } +flet-rive = { path = "../../../packages/flet-rive", editable = true } +flet-secure-storage = { path = "../../../packages/flet-secure-storage", editable = true } +flet-video = { path = "../../../packages/flet-video", editable = true } +flet-webview = { path = "../../../packages/flet-webview", editable = true } + +[tool.flet.dev_packages] +flet = "../../../packages/flet" +flet-ads = "../../../packages/flet-ads" +flet-audio = "../../../packages/flet-audio" +flet-audio-recorder = "../../../packages/flet-audio-recorder" +flet-charts = "../../../packages/flet-charts" +flet-datatable2 = "../../../packages/flet-datatable2" +flet-flashlight = "../../../packages/flet-flashlight" +flet-geolocator = "../../../packages/flet-geolocator" +flet-lottie = "../../../packages/flet-lottie" +flet-map = "../../../packages/flet-map" +flet-permission-handler = "../../../packages/flet-permission-handler" +flet-rive = "../../../packages/flet-rive" +flet-secure-storage = "../../../packages/flet-secure-storage" +flet-video = "../../../packages/flet-video" +flet-webview = "../../../packages/flet-webview" + +# Docs: https://docs.flet.dev/publish/ +[tool.flet] +product = "Flet Build Test" +artifact = "flet_build_test artifact" +project = "flet_build_test" +company = "Flet" +org = "com.flet" +copyright = "Copyright (C) 2025 by Flet" + +[tool.flet.app] +path = "src" + +[tool.flet.android.meta_data] +"com.google.android.gms.ads.APPLICATION_ID" = "ca-app-pub-3940256099942544~3347511713" diff --git a/sdk/python/examples/apps/flet_build_test/src/main.py b/sdk/python/examples/apps/flet_build_test/src/main.py new file mode 100644 index 0000000000..841a8da176 --- /dev/null +++ b/sdk/python/examples/apps/flet_build_test/src/main.py @@ -0,0 +1,59 @@ +import sys + +from modules.utils import greet + +import flet as ft +import flet_ads # noqa: F401 +import flet_audio # noqa: F401 +import flet_audio_recorder # noqa: F401 +import flet_charts # noqa: F401 +import flet_datatable2 # noqa: F401 +import flet_flashlight # noqa: F401 +import flet_geolocator # noqa: F401 +import flet_lottie # noqa: F401 +import flet_map # noqa: F401 +import flet_permission_handler # noqa: F401 +import flet_rive # noqa: F401 +import flet_video # noqa: F401 +import flet_webview # noqa: F401 + + +def main(page: ft.Page): + page.theme_mode = ft.ThemeMode.SYSTEM + page.horizontal_alignment = ft.CrossAxisAlignment.CENTER + page.vertical_alignment = ft.MainAxisAlignment.CENTER + + page.appbar = ft.AppBar( + title=ft.Text("Flet Build Test"), + actions=[ + ft.Container( + content=ft.Text(f"v{ft.__version__}", weight=ft.FontWeight.BOLD), + padding=ft.Padding.only(right=15), + ) + ], + ) + + page.floating_action_button = ft.FloatingActionButton( + icon=ft.Icons.INFO, + bgcolor=ft.Colors.BLUE, + on_click=lambda: page.show_dialog( + ft.AlertDialog( + title="Debug Info", + content=ft.Text(f"sys.path: {sys.path}"), + ) + ), + ) + + page.add( + ft.SafeArea( + content=ft.Column( + controls=[ + ft.Text(greet("Flet"), size=20, weight=ft.FontWeight.BOLD), + ], + ) + ) + ) + + +if __name__ == "__main__": + ft.run(main) diff --git a/sdk/python/examples/apps/flet_build_test/src/modules/utils.py b/sdk/python/examples/apps/flet_build_test/src/modules/utils.py new file mode 100644 index 0000000000..382d8c8b2a --- /dev/null +++ b/sdk/python/examples/apps/flet_build_test/src/modules/utils.py @@ -0,0 +1,3 @@ +def greet(name: str) -> str: + """A simple utility function that returns a greeting message.""" + return f"Hello, {name}!" diff --git a/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py b/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py index e44aef0899..916745dab8 100644 --- a/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py +++ b/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py @@ -76,7 +76,7 @@ def __init__(self, parser: argparse.ArgumentParser) -> None: "config_platform": "macos", "flutter_build_command": "macos", "status_text": "macOS bundle", - "outputs": ["build/macos/Build/Products/Release/{product_name}.app"], + "outputs": ["build/macos/Build/Products/Release/{artifact_name}.app"], "dist": "macos", "can_be_run_on": ["Darwin"], }, @@ -241,8 +241,14 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None: "--project", dest="project_name", required=False, - help="Project name for the executable/bundle. " - "It is used in metadata and bundle IDs", + help="Project name for bundle IDs and identifiers; used as the default " + "for artifact and product names", + ) + parser.add_argument( + "--artifact", + dest="artifact_name", + required=False, + help="Executable or bundle name on disk", ) parser.add_argument( "--description", @@ -254,8 +260,8 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None: "--product", dest="product_name", required=False, - help="Display name of the app that is shown in window titles " - "and about app dialogs", + help="Display name shown in app launchers, window titles, " + "and about dialogs.", ) parser.add_argument( "--org", @@ -366,7 +372,7 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None: dest="web_renderer", type=str.lower, choices=["auto", "canvaskit", "skwasm"], - help="Flutter web renderer to use (web only)", + help="Flutter web renderer to use (web only) [env: FLET_WEB_RENDERER=]", ) parser.add_argument( "--route-url-strategy", @@ -374,7 +380,8 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None: type=str.lower, choices=["path", "hash"], help="Base URL path to serve the app from. " - "Useful if the app is hosted in a subdirectory (web only)", + "Useful if the app is hosted in a subdirectory (web only) " + "[env: FLET_WEB_ROUTE_URL_STRATEGY=]", ) parser.add_argument( "--pwa-background-color", @@ -400,7 +407,8 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None: dest="no_cdn", action="store_true", default=False, - help="Disable loading of CanvasKit, Pyodide and fonts from CDN", + help="Disable loading of CanvasKit, Pyodide and fonts from CDN " + "[env: FLET_WEB_NO_CDN=]", ) parser.add_argument( "--split-per-abi", @@ -529,23 +537,26 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None: parser.add_argument( "--android-signing-key-store", dest="android_signing_key_store", - help="path to an upload keystore `.jks` file for Android apps", + help="path to an upload keystore `.jks` file for Android apps " + "[env: FLET_ANDROID_SIGNING_KEY_STORE=]", ) parser.add_argument( "--android-signing-key-store-password", dest="android_signing_key_store_password", - help="Android signing store password", + help="Android signing store password " + "[env: FLET_ANDROID_SIGNING_KEY_STORE_PASSWORD=]", ) parser.add_argument( "--android-signing-key-password", dest="android_signing_key_password", - help="Android signing key password", + help="Android signing key password " + "[env: FLET_ANDROID_SIGNING_KEY_PASSWORD=]", ) parser.add_argument( "--android-signing-key-alias", dest="android_signing_key_alias", - default="upload", - help="Android signing key alias", + default=None, + help="Android signing key alias [env: FLET_ANDROID_SIGNING_KEY_ALIAS=]", ) parser.add_argument( "--build-number", @@ -704,18 +715,26 @@ def setup_template_data(self): .strip("/") .strip() ) - project_name_orig = ( + project_name_raw = ( self.options.project_name or self.get_pyproject("project.name") - or self.get_pyproject("tool.poetry.name") or self.python_app_path.name ) - project_name_slug = slugify(cast(str, project_name_orig)) + project_name_slug = slugify(cast(str, project_name_raw)) project_name = project_name_slug.replace("-", "_") + artifact_name = ( + self.options.artifact_name + or self.get_pyproject("tool.flet.artifact") + or self.options.project_name + or self.get_pyproject("project.name") + or self.python_app_path.name + ) product_name = ( self.options.product_name or self.get_pyproject("tool.flet.product") - or project_name_orig + or self.options.project_name + or self.get_pyproject("project.name") + or self.python_app_path.name ) split_per_abi = ( @@ -947,6 +966,7 @@ def setup_template_data(self): "split_per_abi": split_per_abi, "project_name": project_name, "project_name_slug": project_name_slug, + "artifact_name": artifact_name, "product_name": product_name, "description": ( self.options.description @@ -988,7 +1008,11 @@ def setup_template_data(self): "scheme": deep_linking_scheme, "host": deep_linking_host, }, - "android_signing": self.options.android_signing_key_store is not None, + "android_signing": bool( + self.options.android_signing_key_store + or os.getenv("FLET_ANDROID_SIGNING_KEY_STORE") + or self.get_pyproject("tool.flet.android.signing.key_store") + ), }, "flutter": {"dependencies": list(self.flutter_dependencies.keys())}, "pyproject": self.get_pyproject(), @@ -1264,9 +1288,9 @@ def customize_icons(self): capture_output=self.verbose < 1, ) if icons_result.returncode != 0: - if icons_result.stdout: + if isinstance(icons_result.stdout, str): console.log(icons_result.stdout, style=verbose1_style) - if icons_result.stderr: + if isinstance(icons_result.stderr, str): console.log(icons_result.stderr, style=error_style) self.cleanup(icons_result.returncode) console.log(f"Generated app icons {self.emojis['checkmark']}") @@ -1514,9 +1538,9 @@ def customize_splash_images(self): capture_output=self.verbose < 1, ) if splash_result.returncode != 0: - if splash_result.stdout: + if isinstance(splash_result.stdout, str): console.log(splash_result.stdout, style=verbose1_style) - if splash_result.stderr: + if isinstance(splash_result.stderr, str): console.log(splash_result.stderr, style=error_style) self.cleanup(splash_result.returncode) console.log(f"Generated splash screens {self.emojis['checkmark']}") @@ -1728,9 +1752,9 @@ def package_python_app(self): ) if package_result.returncode != 0: - if package_result.stdout: + if isinstance(package_result.stdout, str): console.log(package_result.stdout, style=verbose1_style) - if package_result.stderr: + if isinstance(package_result.stderr, str): console.log(package_result.stderr, style=error_style) self.cleanup(package_result.returncode) @@ -1799,6 +1823,7 @@ def _run_flutter_command(self): android_signing_key_store = ( self.options.android_signing_key_store or self.get_pyproject("tool.flet.android.signing.key_store") + or os.getenv("FLET_ANDROID_SIGNING_KEY_STORE") ) if android_signing_key_store: build_env["FLET_ANDROID_SIGNING_KEY_STORE"] = android_signing_key_store @@ -1818,16 +1843,31 @@ def _run_flutter_command(self): key_password if key_password else key_store_password ) - android_signing_key_alias = ( - self.options.android_signing_key_alias - or self.get_pyproject("tool.flet.android.signing.key_alias") - ) - if android_signing_key_alias: + if android_signing_key_store: + android_signing_key_alias = ( + self.options.android_signing_key_alias + or self.get_pyproject("tool.flet.android.signing.key_alias") + or os.getenv("FLET_ANDROID_SIGNING_KEY_ALIAS") + or "upload" + ) build_env["FLET_ANDROID_SIGNING_KEY_ALIAS"] = android_signing_key_alias - if self.options.flutter_build_args: - for flutter_build_arg_arr in self.options.flutter_build_args: - build_args.extend(flutter_build_arg_arr) + flutter_build_args = ( + self.options.flutter_build_args + or self.get_pyproject( + f"tool.flet.{self.config_platform}.flutter.build_args" + ) + or self.get_pyproject("tool.flet.flutter.build_args") + ) + if flutter_build_args: + if isinstance(flutter_build_args, (list, tuple)): + for arg in flutter_build_args: + if isinstance(arg, (list, tuple)): + build_args.extend(arg) + elif isinstance(arg, str): + build_args.append(arg) + elif isinstance(flutter_build_args, str): + build_args.append(flutter_build_args) if self.verbose > 1: build_args.append("--verbose") @@ -1843,9 +1883,9 @@ def _run_flutter_command(self): build_result.returncode != 0 or "Encountered error while creating the IPA" in str(build_result.stderr) ): - if build_result.stdout: + if isinstance(build_result.stdout, str): console.log(build_result.stdout, style=verbose1_style) - if build_result.stderr: + if isinstance(build_result.stderr, str): console.log(build_result.stderr, style=error_style) self.cleanup(build_result.returncode if build_result.returncode else 1) @@ -1878,6 +1918,7 @@ def ignore(path, names): build_output_dir = ( str(self.flutter_dir.joinpath(build_output)) .replace("{arch}", arch) + .replace("{artifact_name}", self.template_data["artifact_name"]) .replace("{project_name}", self.template_data["project_name"]) .replace("{product_name}", self.template_data["product_name"]) ) diff --git a/sdk/python/packages/flet-cli/src/flet_cli/commands/flutter_base.py b/sdk/python/packages/flet-cli/src/flet_cli/commands/flutter_base.py index aca0ea5a6d..839d7b6f8a 100644 --- a/sdk/python/packages/flet-cli/src/flet_cli/commands/flutter_base.py +++ b/sdk/python/packages/flet-cli/src/flet_cli/commands/flutter_base.py @@ -71,7 +71,8 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None: "--no-rich-output", action="store_true", default=False, - help="Disable rich output and prefer plain text. Useful on Windows builds", + help="Disable rich output and prefer plain text. Useful on Windows builds" + "[env: FLET_CLI_NO_RICH_OUTPUT=]", ) parser.add_argument( "--yes", @@ -85,7 +86,8 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None: "--skip-flutter-doctor", action="store_true", default=False, - help="Skip running Flutter doctor upon failed builds", + help="Skip running Flutter doctor upon failed builds" + "[env: FLET_CLI_SKIP_FLUTTER_DOCTOR=]", ) def handle(self, options: argparse.Namespace) -> None: @@ -223,9 +225,9 @@ def install_flutter(self): capture_output=self.verbose < 1, ) if config_result.returncode != 0: - if config_result.stdout: + if isinstance(config_result.stdout, str): console.log(config_result.stdout, style=verbose1_style) - if config_result.stderr: + if isinstance(config_result.stderr, str): console.log(config_result.stderr, style=error_style) self.cleanup(config_result.returncode) @@ -260,9 +262,9 @@ def install_jdk(self): capture_output=self.verbose < 1, ) if config_result.returncode != 0: - if config_result.stdout: + if isinstance(config_result.stdout, str): console.log(config_result.stdout, style=verbose1_style) - if config_result.stderr: + if isinstance(config_result.stderr, str): console.log(config_result.stderr, style=error_style) self.cleanup(config_result.returncode) @@ -375,8 +377,10 @@ def run_flutter_doctor(self): cwd=os.getcwd(), capture_output=True, ) - if flutter_doctor.returncode == 0 and flutter_doctor.stdout: + if flutter_doctor.stdout: console.log(flutter_doctor.stdout, style=verbose1_style) + if flutter_doctor.stderr: + console.log(flutter_doctor.stderr, style=error_style) def update_status(self, status): if self.no_rich_output: diff --git a/sdk/python/packages/flet-cli/src/flet_cli/commands/publish.py b/sdk/python/packages/flet-cli/src/flet_cli/commands/publish.py index c51bcfea10..d7eb21e9fb 100644 --- a/sdk/python/packages/flet-cli/src/flet_cli/commands/publish.py +++ b/sdk/python/packages/flet-cli/src/flet_cli/commands/publish.py @@ -44,7 +44,7 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None: type=str, default=None, help="Path to a directory containing static assets " - "used by the app (e.g., images, fonts, icons)", + "used by the app (e.g., images, fonts, icons). [env: FLET_ASSETS_DIR=]", ) parser.add_argument( "--distpath", @@ -90,7 +90,7 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None: type=str.lower, choices=["auto", "canvaskit", "skwasm"], default="auto", - help="Flutter web renderer to use", + help="Flutter web renderer to use [env: FLET_WEB_RENDERER=]", ) parser.add_argument( "--route-url-strategy", @@ -98,7 +98,8 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None: type=str.lower, choices=["path", "hash"], default="path", - help="Controls how routes are handled in the browser", + help="Controls how routes are handled in the browser " + "[env: FLET_WEB_ROUTE_URL_STRATEGY=]", ) parser.add_argument( "--pwa-background-color", diff --git a/sdk/python/packages/flet-web/src/flet_web/fastapi/app.py b/sdk/python/packages/flet-web/src/flet_web/fastapi/app.py index 2bab513146..f2775d93b8 100644 --- a/sdk/python/packages/flet-web/src/flet_web/fastapi/app.py +++ b/sdk/python/packages/flet-web/src/flet_web/fastapi/app.py @@ -4,10 +4,10 @@ from typing import Callable, Optional, Union from fastapi import Request, WebSocket -from flet.controls.page import Page -from flet.controls.types import RouteUrlStrategy, WebRenderer from starlette.middleware.base import BaseHTTPMiddleware +from flet.controls.page import Page +from flet.controls.types import RouteUrlStrategy, WebRenderer from flet_web.fastapi.flet_app import ( DEFAULT_FLET_OAUTH_STATE_TIMEOUT, DEFAULT_FLET_SESSION_TIMEOUT, @@ -22,7 +22,7 @@ def app( main: Union[Callable[[Page], Awaitable], Callable[[Page], None]], - before_main: Union[Callable[[Page], Awaitable], Callable[[Page], None]], + before_main: Union[Callable[[Page], Awaitable], Callable[[Page], None]] = None, proxy_path: Optional[str] = None, assets_dir: Optional[str] = None, app_name: Optional[str] = None, @@ -41,30 +41,28 @@ def app( """ Mount all Flet FastAPI handlers in one call. - Parameters: - * `main` (function or coroutine) - application entry point - a method - called for newly connected user. Handler must have 1 parameter: `page` - `Page` - instance. - * `before_main` - a function that is called after Page was created, but before - calling `main`. - * `assets_dir` (str, optional) - an absolute path to app's assets directory. - * `app_name` (str, optional) - PWA application name. - * `app_short_name` (str, optional) - PWA application short name. - * `app_description` (str, optional) - PWA application description. - * `web_renderer` (WebRenderer) - web renderer defaulting to `WebRenderer.AUTO`. - * `route_url_strategy` (str) - routing URL strategy: `path` (default) or `hash`. - * `no_cdn` (bool) - do not load resources from CDN. - * `upload_dir` (str) - an absolute path to a directory with uploaded files. - * `upload_endpoint_path` (str, optional) - absolute URL of upload endpoint, - e.g. `/upload`. - * `max_upload_size` (str, int) - maximum size of a single upload, bytes. - Unlimited if `None`. - * `secret_key` (str, optional) - secret key to sign and verify upload requests. - * `session_timeout_seconds` (int, optional)- session lifetime, in seconds, after - user disconnected. - * `oauth_state_timeout_seconds` (int, optional) - OAuth state lifetime, in seconds, - which is a maximum allowed time between starting OAuth flow and redirecting - to OAuth callback URL. + Args: + main: Application entry point. It is called for newly connected users. + Handler (function or coroutine) must have 1 parameter of + instance [`Page`][flet.Page]. + before_main: Called after `Page` was created, but before calling `main`. + proxy_path: URL prefix when the app is mounted under a proxy. + assets_dir: an absolute path to app's assets directory. + app_name: PWA application name. + app_short_name: PWA application short name. + app_description: PWA application description. + web_renderer: web renderer defaulting to `WebRenderer.AUTO`. + route_url_strategy: routing URL strategy: `path` (default) or `hash`. + no_cdn: do not load resources from CDN. + upload_dir: an absolute path to a directory with uploaded files. + upload_endpoint_path: absolute URL of upload endpoint, e.g. `/upload`. + max_upload_size: maximum size of a single upload, bytes. Unlimited if `None`. + secret_key: secret key to sign and verify upload requests. + session_timeout_seconds: session lifetime, in seconds, + after the user disconnected. + oauth_state_timeout_seconds: OAuth state lifetime, in seconds, + which is the maximum allowed time between starting OAuth flow and + redirecting to OAuth callback URL. """ env_upload_dir = os.getenv("FLET_UPLOAD_DIR") diff --git a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app.py b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app.py index 43ed2e59d6..ce2e94c033 100644 --- a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app.py +++ b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app.py @@ -41,6 +41,25 @@ class FletApp(Connection): + """ + Handle Flet app WebSocket connections. + + Args: + loop: `asyncio` event loop (`asyncio.get_running_loop()`). + executor: Thread pool executor (`app_manager.executor`). + main: Application entry point - an async method called for newly + connected user. Handler coroutine must have + 1 parameter of instance `Page`. + before_main: Called before `main`. + session_timeout_seconds: Session lifetime, in seconds, + after user disconnected. + oauth_state_timeout_seconds: OAuth state lifetime, in seconds, which + is a maximum allowed time between starting OAuth flow + and redirecting to OAuth callback URL. + upload_endpoint_path: Absolute URL of upload endpoint, e.g. `/upload`. + secret_key: Secret key to sign upload requests. + """ + def __init__( self, loop: asyncio.AbstractEventLoop, @@ -52,23 +71,6 @@ def __init__( upload_endpoint_path: Optional[str] = None, secret_key: Optional[str] = None, ): - """ - Handle Flet app WebSocket connections. - - Parameters: - - * `session_handler` (Coroutine) - application entry point - an async method - called for newly connected user. Handler coroutine must have - 1 parameter: `page` - `Page` instance. - * `session_timeout_seconds` (int, optional) - session lifetime, in seconds, - after user disconnected. - * `oauth_state_timeout_seconds` (int, optional) - OAuth state lifetime, - in seconds, which is a maximum allowed time between starting OAuth flow - and redirecting to OAuth callback URL. - * `upload_endpoint_path` (str, optional) - absolute URL of upload endpoint, - e.g. `/upload`. - * `secret_key` (str, optional) - secret key to sign upload requests. - """ super().__init__() self.__id = random_string(8) logger.info(f"New FletApp: {self.__id}") @@ -102,9 +104,8 @@ async def handle(self, websocket: WebSocket): """ Handle WebSocket connection. - Parameters: - - * `websocket` (WebSocket) - Websocket instance. + Args: + websocket: WebSocket instance. """ self.__websocket = websocket diff --git a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_fastapi.py b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_fastapi.py index 75f25c71e3..281bb99dcd 100644 --- a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_fastapi.py +++ b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_fastapi.py @@ -2,15 +2,7 @@ import inspect from collections.abc import Awaitable, Coroutine, Sequence from contextlib import asynccontextmanager, suppress -from typing import ( - Any, - Callable, - Dict, - List, - Optional, - Type, - Union, -) +from typing import Any, Callable, Optional, Union import fastapi from fastapi.datastructures import Default @@ -29,42 +21,42 @@ def __init__( self, *, debug: bool = False, - routes: Optional[List[BaseRoute]] = None, + routes: Optional[list[BaseRoute]] = None, title: str = "FastAPI", summary: Optional[str] = None, description: str = "", version: str = "0.1.0", openapi_url: Optional[str] = "/openapi.json", - openapi_tags: Optional[List[Dict[str, Any]]] = None, - servers: Optional[List[Dict[str, Union[str, Any]]]] = None, + openapi_tags: Optional[list[dict[str, Any]]] = None, + servers: Optional[list[dict[str, Union[str, Any]]]] = None, dependencies: Optional[Sequence[Depends]] = None, - default_response_class: Type[Response] = Default(JSONResponse), + default_response_class: type[Response] = Default(JSONResponse), redirect_slashes: bool = True, docs_url: Optional[str] = "/docs", redoc_url: Optional[str] = "/redoc", swagger_ui_oauth2_redirect_url: Optional[str] = "/docs/oauth2-redirect", - swagger_ui_init_oauth: Optional[Dict[str, Any]] = None, + swagger_ui_init_oauth: Optional[dict[str, Any]] = None, middleware: Optional[Sequence[Middleware]] = None, exception_handlers: Optional[ - Dict[ - Union[int, Type[Exception]], + dict[ + Union[int, type[Exception]], Callable[[Request, Any], Coroutine[Any, Any, Response]], ] ] = None, on_startup: Optional[Sequence[Callable[[], Optional[Awaitable]]]] = None, on_shutdown: Optional[Sequence[Callable[[], Optional[Awaitable]]]] = None, terms_of_service: Optional[str] = None, - contact: Optional[Dict[str, Union[str, Any]]] = None, - license_info: Optional[Dict[str, Union[str, Any]]] = None, + contact: Optional[dict[str, Union[str, Any]]] = None, + license_info: Optional[dict[str, Union[str, Any]]] = None, openapi_prefix: str = "", root_path: str = "", root_path_in_servers: bool = True, - responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, - callbacks: Optional[List[BaseRoute]] = None, + responses: Optional[dict[Union[int, str], dict[str, Any]]] = None, + callbacks: Optional[list[BaseRoute]] = None, webhooks: Optional[fastapi.routing.APIRouter] = None, deprecated: Optional[bool] = None, include_in_schema: bool = True, - swagger_ui_parameters: Optional[Dict[str, Any]] = None, + swagger_ui_parameters: Optional[dict[str, Any]] = None, generate_unique_id_function: Callable[ [fastapi.routing.APIRoute], str ] = Default(generate_unique_id), diff --git a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_static_files.py b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_static_files.py index a2985d0429..a0c8951a23 100644 --- a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_static_files.py +++ b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_static_files.py @@ -26,18 +26,16 @@ class FletStaticFiles(StaticFiles): """ Serve Flet app static files. - Parameters: - - * `app_mount_path` (str) - absolute URL of Flet app. Default is `/`. - * `assets_dir` (str, optional) - an absolute path to app's assets directory. - * `app_name` (str, optional) - PWA application name. - * `app_short_name` (str, optional) - PWA application short name. - * `app_description` (str, optional) - PWA application description. - * `web_renderer` (WebRenderer) - web renderer defaulting to `WebRenderer.AUTO`. - * `route_url_strategy` (str) - routing URL strategy: `path` (default) or `hash`. - * `no_cdn` - do not load CanvasKit, Pyodide and fonts from CDN - * `websocket_endpoint_path` (str, optional) - absolute URL of Flet app - WebSocket handler. Default is `{app_mount_path}/ws`. + Args: + assets_dir: An absolute path to app's assets directory. + app_name: PWA application name. + app_short_name: PWA application short name. + app_description: PWA application description. + web_renderer: Type of web renderer. + route_url_strategy: Routing URL strategy. + no_cdn: Whether not load CanvasKit, Pyodide, and fonts from CDN. + websocket_endpoint_path: Absolute URL of Flet app WebSocket handler. + Defaults to `/ws`. """ def __init__( diff --git a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_upload.py b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_upload.py index 0ea0f953a3..2b0591f24c 100644 --- a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_upload.py +++ b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_upload.py @@ -16,12 +16,10 @@ class FletUpload: """ Flet app uploads handler. - Parameters: - - * `upload_dir` (str) - an absolute path to a directory with uploaded files. - * `max_upload_size` (str, int) - maximum size of a single upload, bytes. - Unlimited if `None`. - * `secret_key` (str, optional) - secret key to sign and verify upload requests. + Args: + upload_dir: An absolute path to a directory with uploaded files. + max_upload_size: maximum size of a single upload, bytes. Unlimited if `None`. + secret_key: secret key to sign and verify upload requests. """ def __init__( @@ -45,13 +43,12 @@ def __init__( logger.info(f"Upload path configured: {self.__upload_dir}") - """ - Handle file upload. - - Upload must be an non-encoded (raw) file in the request body. - """ - async def handle(self, request: Request): + """ + Handle file upload. + + Upload must be an non-encoded (raw) file in the request body. + """ query_params = request.query_params file_name = query_params.get("f") expire_str = query_params.get("e") @@ -100,7 +97,7 @@ async def handle(self, request: Request): detail="Invalid upload destination", ) - # create directory if not exists + # create a directory if it doesn't exist dest_dir = os.path.dirname(full_path) os.makedirs(dest_dir, exist_ok=True) diff --git a/sdk/python/packages/flet-web/src/flet_web/fastapi/serve_fastapi_web_app.py b/sdk/python/packages/flet-web/src/flet_web/fastapi/serve_fastapi_web_app.py index 1057373f48..74be559814 100644 --- a/sdk/python/packages/flet-web/src/flet_web/fastapi/serve_fastapi_web_app.py +++ b/sdk/python/packages/flet-web/src/flet_web/fastapi/serve_fastapi_web_app.py @@ -3,10 +3,10 @@ from typing import Any, Optional, Union import uvicorn -from flet.controls.types import RouteUrlStrategy, WebRenderer import flet_web.fastapi import flet_web.fastapi as flet_fastapi +from flet.controls.types import RouteUrlStrategy, WebRenderer logger = logging.getLogger(flet_fastapi.__name__) diff --git a/sdk/python/packages/flet/docs/audio/index.md b/sdk/python/packages/flet/docs/audio/index.md index 5a02bd3015..154086be69 100644 --- a/sdk/python/packages/flet/docs/audio/index.md +++ b/sdk/python/packages/flet/docs/audio/index.md @@ -9,9 +9,9 @@ Allows playing audio in [Flet](https://flet.dev) apps. ## Platform Support -| Platform | Windows | macOS | Linux | iOS | Android | Web | -|----------|---------|-------|-------|-----|---------|-----| -| Supported| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| Platform | Windows | macOS | Linux | iOS | Android | Web | +|-----------|---------|-------|-------|-----|---------|-----| +| Supported | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ## Usage @@ -21,7 +21,6 @@ To use `Audio` control add `flet-audio` package to your project dependencies: ```bash uv add flet-audio ``` - /// /// tab | pip ```bash @@ -31,25 +30,43 @@ pip install flet-audio # (1)! 1. After this, you will have to manually add this package to your `requirements.txt` or `pyproject.toml`. /// -## Example +/// admonition | Linux requirements + type: note +To play audio on Linux (or [WSL](https://docs.microsoft.com/en-us/windows/wsl/about)) you need to +install [`GStreamer`](https://github.com/GStreamer/gstreamer) library. -```python ---8<-- "{{ examples }}/example_1.py" +To install the minimal set of GStreamer libs on Ubuntu/Debian, run: + +```bash +sudo apt install libgtk-3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev ``` -/// admonition | Linux/WSL (Windows Subsystem for Linux) - type: note -To play audio on Linux/WSL you need to install [`GStreamer`](https://github.com/GStreamer/gstreamer) library. +To install the full set: + +```bash +sudo apt install \ + libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev \ + gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad \ + gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools \ + gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 \ + gstreamer1.0-qt5 gstreamer1.0-pulseaudio +``` If you receive `error while loading shared libraries: libgstapp-1.0.so.0`, it means `GStreamer` is not installed in your WSL environment. +Install the full set of GStreamer libs, as shown above. + +See [this guide](https://gstreamer.freedesktop.org/documentation/installing/on-linux.html?gi-language=c) +for installing on other Linux distributions. +/// -To install it, run the following command: +## Examples -```bash -apt install -y libgstreamer1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools +### Basic example + +```python +--8<-- "{{ examples }}/example_1.py" ``` -/// ## Description diff --git a/sdk/python/packages/flet/docs/audio/types/audio_duration_change_event.md b/sdk/python/packages/flet/docs/audio/types/audiodurationchangeevent.md similarity index 100% rename from sdk/python/packages/flet/docs/audio/types/audio_duration_change_event.md rename to sdk/python/packages/flet/docs/audio/types/audiodurationchangeevent.md diff --git a/sdk/python/packages/flet/docs/audio/types/audio_position_change_event.md b/sdk/python/packages/flet/docs/audio/types/audiopositionchangeevent.md similarity index 100% rename from sdk/python/packages/flet/docs/audio/types/audio_position_change_event.md rename to sdk/python/packages/flet/docs/audio/types/audiopositionchangeevent.md diff --git a/sdk/python/packages/flet/docs/audio/types/audio_state.md b/sdk/python/packages/flet/docs/audio/types/audiostate.md similarity index 100% rename from sdk/python/packages/flet/docs/audio/types/audio_state.md rename to sdk/python/packages/flet/docs/audio/types/audiostate.md diff --git a/sdk/python/packages/flet/docs/audio/types/audio_state_change_event.md b/sdk/python/packages/flet/docs/audio/types/audiostatechangeevent.md similarity index 100% rename from sdk/python/packages/flet/docs/audio/types/audio_state_change_event.md rename to sdk/python/packages/flet/docs/audio/types/audiostatechangeevent.md diff --git a/sdk/python/packages/flet/docs/audio/types/release_mode.md b/sdk/python/packages/flet/docs/audio/types/releasemode.md similarity index 100% rename from sdk/python/packages/flet/docs/audio/types/release_mode.md rename to sdk/python/packages/flet/docs/audio/types/releasemode.md diff --git a/sdk/python/packages/flet/docs/audio_recorder/types/android_audio_source.md b/sdk/python/packages/flet/docs/audio_recorder/types/androidaudiosource.md similarity index 100% rename from sdk/python/packages/flet/docs/audio_recorder/types/android_audio_source.md rename to sdk/python/packages/flet/docs/audio_recorder/types/androidaudiosource.md diff --git a/sdk/python/packages/flet/docs/audio_recorder/types/android_recorder_configuration.md b/sdk/python/packages/flet/docs/audio_recorder/types/androidrecorderconfiguration.md similarity index 100% rename from sdk/python/packages/flet/docs/audio_recorder/types/android_recorder_configuration.md rename to sdk/python/packages/flet/docs/audio_recorder/types/androidrecorderconfiguration.md diff --git a/sdk/python/packages/flet/docs/audio_recorder/types/audio_encoder.md b/sdk/python/packages/flet/docs/audio_recorder/types/audioencoder.md similarity index 100% rename from sdk/python/packages/flet/docs/audio_recorder/types/audio_encoder.md rename to sdk/python/packages/flet/docs/audio_recorder/types/audioencoder.md diff --git a/sdk/python/packages/flet/docs/audio_recorder/types/audio_recorder_configuration.md b/sdk/python/packages/flet/docs/audio_recorder/types/audiorecorderconfiguration.md similarity index 100% rename from sdk/python/packages/flet/docs/audio_recorder/types/audio_recorder_configuration.md rename to sdk/python/packages/flet/docs/audio_recorder/types/audiorecorderconfiguration.md diff --git a/sdk/python/packages/flet/docs/audio_recorder/types/audio_recorder_state.md b/sdk/python/packages/flet/docs/audio_recorder/types/audiorecorderstate.md similarity index 100% rename from sdk/python/packages/flet/docs/audio_recorder/types/audio_recorder_state.md rename to sdk/python/packages/flet/docs/audio_recorder/types/audiorecorderstate.md diff --git a/sdk/python/packages/flet/docs/audio_recorder/types/audio_recorder_state_change_event.md b/sdk/python/packages/flet/docs/audio_recorder/types/audiorecorderstatechangeevent.md similarity index 100% rename from sdk/python/packages/flet/docs/audio_recorder/types/audio_recorder_state_change_event.md rename to sdk/python/packages/flet/docs/audio_recorder/types/audiorecorderstatechangeevent.md diff --git a/sdk/python/packages/flet/docs/audio_recorder/types/input_device.md b/sdk/python/packages/flet/docs/audio_recorder/types/inputdevice.md similarity index 100% rename from sdk/python/packages/flet/docs/audio_recorder/types/input_device.md rename to sdk/python/packages/flet/docs/audio_recorder/types/inputdevice.md diff --git a/sdk/python/packages/flet/docs/audio_recorder/types/ios_audio_category_option.md b/sdk/python/packages/flet/docs/audio_recorder/types/iosaudiocategoryoption.md similarity index 100% rename from sdk/python/packages/flet/docs/audio_recorder/types/ios_audio_category_option.md rename to sdk/python/packages/flet/docs/audio_recorder/types/iosaudiocategoryoption.md diff --git a/sdk/python/packages/flet/docs/audio_recorder/types/ios_recorder_configuration.md b/sdk/python/packages/flet/docs/audio_recorder/types/iosrecorderconfiguration.md similarity index 100% rename from sdk/python/packages/flet/docs/audio_recorder/types/ios_recorder_configuration.md rename to sdk/python/packages/flet/docs/audio_recorder/types/iosrecorderconfiguration.md diff --git a/sdk/python/packages/flet/docs/charts/bar_chart.md b/sdk/python/packages/flet/docs/charts/barchart.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/bar_chart.md rename to sdk/python/packages/flet/docs/charts/barchart.md diff --git a/sdk/python/packages/flet/docs/charts/candlestick_chart.md b/sdk/python/packages/flet/docs/charts/candlestickchart.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/candlestick_chart.md rename to sdk/python/packages/flet/docs/charts/candlestickchart.md diff --git a/sdk/python/packages/flet/docs/charts/index.md b/sdk/python/packages/flet/docs/charts/index.md index 9505582b34..60535c1b48 100644 --- a/sdk/python/packages/flet/docs/charts/index.md +++ b/sdk/python/packages/flet/docs/charts/index.md @@ -34,11 +34,11 @@ pip install flet-charts # (1)! ## Available Charts -- [`BarChart`](bar_chart.md) -- [`CandlestickChart`](candlestick_chart.md) -- [`LineChart`](line_chart.md) -- [`MatplotlibChart`](matplotlib_chart.md) -- [`PieChart`](pie_chart.md) -- [`PlotlyChart`](plotly_chart.md) -- [`RadarChart`](radar_chart.md) -- [`ScatterChart`](scatter_chart.md) +- [`BarChart`](barchart.md) +- [`CandlestickChart`](candlestickchart.md) +- [`LineChart`](linechart.md) +- [`MatplotlibChart`](matplotlibchart.md) +- [`PieChart`](piechart.md) +- [`PlotlyChart`](plotlychart.md) +- [`RadarChart`](radarchart.md) +- [`ScatterChart`](scatterchart.md) diff --git a/sdk/python/packages/flet/docs/charts/line_chart.md b/sdk/python/packages/flet/docs/charts/linechart.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/line_chart.md rename to sdk/python/packages/flet/docs/charts/linechart.md diff --git a/sdk/python/packages/flet/docs/charts/matplotlib_chart.md b/sdk/python/packages/flet/docs/charts/matplotlibchart.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/matplotlib_chart.md rename to sdk/python/packages/flet/docs/charts/matplotlibchart.md diff --git a/sdk/python/packages/flet/docs/charts/pie_chart.md b/sdk/python/packages/flet/docs/charts/piechart.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/pie_chart.md rename to sdk/python/packages/flet/docs/charts/piechart.md diff --git a/sdk/python/packages/flet/docs/charts/plotly_chart.md b/sdk/python/packages/flet/docs/charts/plotlychart.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/plotly_chart.md rename to sdk/python/packages/flet/docs/charts/plotlychart.md diff --git a/sdk/python/packages/flet/docs/charts/radar_chart.md b/sdk/python/packages/flet/docs/charts/radarchart.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/radar_chart.md rename to sdk/python/packages/flet/docs/charts/radarchart.md diff --git a/sdk/python/packages/flet/docs/charts/scatter_chart.md b/sdk/python/packages/flet/docs/charts/scatterchart.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/scatter_chart.md rename to sdk/python/packages/flet/docs/charts/scatterchart.md diff --git a/sdk/python/packages/flet/docs/charts/types/bar_chart_event.md b/sdk/python/packages/flet/docs/charts/types/barchartevent.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/bar_chart_event.md rename to sdk/python/packages/flet/docs/charts/types/barchartevent.md diff --git a/sdk/python/packages/flet/docs/charts/types/bar_chart_group.md b/sdk/python/packages/flet/docs/charts/types/barchartgroup.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/bar_chart_group.md rename to sdk/python/packages/flet/docs/charts/types/barchartgroup.md diff --git a/sdk/python/packages/flet/docs/charts/types/bar_chart_rod.md b/sdk/python/packages/flet/docs/charts/types/barchartrod.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/bar_chart_rod.md rename to sdk/python/packages/flet/docs/charts/types/barchartrod.md diff --git a/sdk/python/packages/flet/docs/charts/types/bar_chart_rod_stack_item.md b/sdk/python/packages/flet/docs/charts/types/barchartrodstackitem.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/bar_chart_rod_stack_item.md rename to sdk/python/packages/flet/docs/charts/types/barchartrodstackitem.md diff --git a/sdk/python/packages/flet/docs/charts/types/bar_chart_rod_tooltip.md b/sdk/python/packages/flet/docs/charts/types/barchartrodtooltip.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/bar_chart_rod_tooltip.md rename to sdk/python/packages/flet/docs/charts/types/barchartrodtooltip.md diff --git a/sdk/python/packages/flet/docs/charts/types/bar_chart_tooltip.md b/sdk/python/packages/flet/docs/charts/types/barcharttooltip.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/bar_chart_tooltip.md rename to sdk/python/packages/flet/docs/charts/types/barcharttooltip.md diff --git a/sdk/python/packages/flet/docs/charts/types/bar_chart_tooltip_direction.md b/sdk/python/packages/flet/docs/charts/types/barcharttooltipdirection.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/bar_chart_tooltip_direction.md rename to sdk/python/packages/flet/docs/charts/types/barcharttooltipdirection.md diff --git a/sdk/python/packages/flet/docs/charts/types/candlestick_chart_event.md b/sdk/python/packages/flet/docs/charts/types/candlestickchartevent.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/candlestick_chart_event.md rename to sdk/python/packages/flet/docs/charts/types/candlestickchartevent.md diff --git a/sdk/python/packages/flet/docs/charts/types/candlestick_chart_spot.md b/sdk/python/packages/flet/docs/charts/types/candlestickchartspot.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/candlestick_chart_spot.md rename to sdk/python/packages/flet/docs/charts/types/candlestickchartspot.md diff --git a/sdk/python/packages/flet/docs/charts/types/candlestick_chart_spot_tooltip.md b/sdk/python/packages/flet/docs/charts/types/candlestickchartspottooltip.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/candlestick_chart_spot_tooltip.md rename to sdk/python/packages/flet/docs/charts/types/candlestickchartspottooltip.md diff --git a/sdk/python/packages/flet/docs/charts/types/candlestick_chart_tooltip.md b/sdk/python/packages/flet/docs/charts/types/candlestickcharttooltip.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/candlestick_chart_tooltip.md rename to sdk/python/packages/flet/docs/charts/types/candlestickcharttooltip.md diff --git a/sdk/python/packages/flet/docs/charts/types/chart_axis.md b/sdk/python/packages/flet/docs/charts/types/chartaxis.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/chart_axis.md rename to sdk/python/packages/flet/docs/charts/types/chartaxis.md diff --git a/sdk/python/packages/flet/docs/charts/types/chart_axis_label.md b/sdk/python/packages/flet/docs/charts/types/chartaxislabel.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/chart_axis_label.md rename to sdk/python/packages/flet/docs/charts/types/chartaxislabel.md diff --git a/sdk/python/packages/flet/docs/charts/types/chart_circle_point.md b/sdk/python/packages/flet/docs/charts/types/chartcirclepoint.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/chart_circle_point.md rename to sdk/python/packages/flet/docs/charts/types/chartcirclepoint.md diff --git a/sdk/python/packages/flet/docs/charts/types/chart_cross_point.md b/sdk/python/packages/flet/docs/charts/types/chartcrosspoint.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/chart_cross_point.md rename to sdk/python/packages/flet/docs/charts/types/chartcrosspoint.md diff --git a/sdk/python/packages/flet/docs/charts/types/chart_data_point_tooltip.md b/sdk/python/packages/flet/docs/charts/types/chartdatapointtooltip.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/chart_data_point_tooltip.md rename to sdk/python/packages/flet/docs/charts/types/chartdatapointtooltip.md diff --git a/sdk/python/packages/flet/docs/charts/types/chart_event_type.md b/sdk/python/packages/flet/docs/charts/types/charteventtype.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/chart_event_type.md rename to sdk/python/packages/flet/docs/charts/types/charteventtype.md diff --git a/sdk/python/packages/flet/docs/charts/types/chart_grid_lines.md b/sdk/python/packages/flet/docs/charts/types/chartgridlines.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/chart_grid_lines.md rename to sdk/python/packages/flet/docs/charts/types/chartgridlines.md diff --git a/sdk/python/packages/flet/docs/charts/types/chart_point_line.md b/sdk/python/packages/flet/docs/charts/types/chartpointline.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/chart_point_line.md rename to sdk/python/packages/flet/docs/charts/types/chartpointline.md diff --git a/sdk/python/packages/flet/docs/charts/types/chart_point_shape.md b/sdk/python/packages/flet/docs/charts/types/chartpointshape.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/chart_point_shape.md rename to sdk/python/packages/flet/docs/charts/types/chartpointshape.md diff --git a/sdk/python/packages/flet/docs/charts/types/chart_square_point.md b/sdk/python/packages/flet/docs/charts/types/chartsquarepoint.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/chart_square_point.md rename to sdk/python/packages/flet/docs/charts/types/chartsquarepoint.md diff --git a/sdk/python/packages/flet/docs/charts/types/horizontal_alignment.md b/sdk/python/packages/flet/docs/charts/types/horizontalalignment.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/horizontal_alignment.md rename to sdk/python/packages/flet/docs/charts/types/horizontalalignment.md diff --git a/sdk/python/packages/flet/docs/charts/types/line_chart_data.md b/sdk/python/packages/flet/docs/charts/types/linechartdata.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/line_chart_data.md rename to sdk/python/packages/flet/docs/charts/types/linechartdata.md diff --git a/sdk/python/packages/flet/docs/charts/types/line_chart_data_point.md b/sdk/python/packages/flet/docs/charts/types/linechartdatapoint.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/line_chart_data_point.md rename to sdk/python/packages/flet/docs/charts/types/linechartdatapoint.md diff --git a/sdk/python/packages/flet/docs/charts/types/line_chart_data_point_tooltip.md b/sdk/python/packages/flet/docs/charts/types/linechartdatapointtooltip.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/line_chart_data_point_tooltip.md rename to sdk/python/packages/flet/docs/charts/types/linechartdatapointtooltip.md diff --git a/sdk/python/packages/flet/docs/charts/types/line_chart_event.md b/sdk/python/packages/flet/docs/charts/types/linechartevent.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/line_chart_event.md rename to sdk/python/packages/flet/docs/charts/types/linechartevent.md diff --git a/sdk/python/packages/flet/docs/charts/types/line_chart_event_spot.md b/sdk/python/packages/flet/docs/charts/types/linecharteventspot.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/line_chart_event_spot.md rename to sdk/python/packages/flet/docs/charts/types/linecharteventspot.md diff --git a/sdk/python/packages/flet/docs/charts/types/line_chart_tooltip.md b/sdk/python/packages/flet/docs/charts/types/linecharttooltip.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/line_chart_tooltip.md rename to sdk/python/packages/flet/docs/charts/types/linecharttooltip.md diff --git a/sdk/python/packages/flet/docs/charts/types/pie_chart_event.md b/sdk/python/packages/flet/docs/charts/types/piechartevent.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/pie_chart_event.md rename to sdk/python/packages/flet/docs/charts/types/piechartevent.md diff --git a/sdk/python/packages/flet/docs/charts/types/pie_chart_section.md b/sdk/python/packages/flet/docs/charts/types/piechartsection.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/pie_chart_section.md rename to sdk/python/packages/flet/docs/charts/types/piechartsection.md diff --git a/sdk/python/packages/flet/docs/charts/types/radar_chart_event.md b/sdk/python/packages/flet/docs/charts/types/radarchartevent.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/radar_chart_event.md rename to sdk/python/packages/flet/docs/charts/types/radarchartevent.md diff --git a/sdk/python/packages/flet/docs/charts/types/radar_chart_title.md b/sdk/python/packages/flet/docs/charts/types/radarcharttitle.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/radar_chart_title.md rename to sdk/python/packages/flet/docs/charts/types/radarcharttitle.md diff --git a/sdk/python/packages/flet/docs/charts/types/radar_data_set.md b/sdk/python/packages/flet/docs/charts/types/radardataset.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/radar_data_set.md rename to sdk/python/packages/flet/docs/charts/types/radardataset.md diff --git a/sdk/python/packages/flet/docs/charts/types/radar_data_set_entry.md b/sdk/python/packages/flet/docs/charts/types/radardatasetentry.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/radar_data_set_entry.md rename to sdk/python/packages/flet/docs/charts/types/radardatasetentry.md diff --git a/sdk/python/packages/flet/docs/charts/types/radar_shape.md b/sdk/python/packages/flet/docs/charts/types/radarshape.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/radar_shape.md rename to sdk/python/packages/flet/docs/charts/types/radarshape.md diff --git a/sdk/python/packages/flet/docs/charts/types/scatter_chart_event.md b/sdk/python/packages/flet/docs/charts/types/scatterchartevent.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/scatter_chart_event.md rename to sdk/python/packages/flet/docs/charts/types/scatterchartevent.md diff --git a/sdk/python/packages/flet/docs/charts/types/scatter_chart_spot.md b/sdk/python/packages/flet/docs/charts/types/scatterchartspot.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/scatter_chart_spot.md rename to sdk/python/packages/flet/docs/charts/types/scatterchartspot.md diff --git a/sdk/python/packages/flet/docs/charts/types/scatter_chart_spot_tooltip.md b/sdk/python/packages/flet/docs/charts/types/scatterchartspottooltip.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/scatter_chart_spot_tooltip.md rename to sdk/python/packages/flet/docs/charts/types/scatterchartspottooltip.md diff --git a/sdk/python/packages/flet/docs/charts/types/scatter_chart_tooltip.md b/sdk/python/packages/flet/docs/charts/types/scattercharttooltip.md similarity index 100% rename from sdk/python/packages/flet/docs/charts/types/scatter_chart_tooltip.md rename to sdk/python/packages/flet/docs/charts/types/scattercharttooltip.md diff --git a/sdk/python/packages/flet/docs/controls/page.md b/sdk/python/packages/flet/docs/controls/page.md index a83a777bfb..2cbe5d586e 100644 --- a/sdk/python/packages/flet/docs/controls/page.md +++ b/sdk/python/packages/flet/docs/controls/page.md @@ -31,10 +31,19 @@ Shows how to lock your app to specific device orientations ### Hidden app window on startup +A Flet desktop app (Windows, macOS, or Linux) can start with its window hidden. +This lets your app perform initial setup (for example, add content, resize +or position the window) before showing it to the user. + +In the example below, the window is resized and centered before becoming visible: + ```python --8<-- "{{ examples }}/window_hidden_on_start.py" ``` +If you need this feature when packaging a desktop app using +[`flet build`](../cli/flet-build.md), see [this](../publish/index.md#hidden-app-window-on-startup). + ### Toggle semantics debugger ```python diff --git a/sdk/python/packages/flet/docs/datatable2/types/data_column_size.md b/sdk/python/packages/flet/docs/datatable2/types/datacolumnsize.md similarity index 100% rename from sdk/python/packages/flet/docs/datatable2/types/data_column_size.md rename to sdk/python/packages/flet/docs/datatable2/types/datacolumnsize.md diff --git a/sdk/python/packages/flet/docs/fastapi/app.md b/sdk/python/packages/flet/docs/fastapi/app.md new file mode 100644 index 0000000000..ecda80de19 --- /dev/null +++ b/sdk/python/packages/flet/docs/fastapi/app.md @@ -0,0 +1 @@ +::: flet_web.fastapi.app diff --git a/sdk/python/packages/flet/docs/fastapi/app_manager.md b/sdk/python/packages/flet/docs/fastapi/app_manager.md new file mode 100644 index 0000000000..94306be135 --- /dev/null +++ b/sdk/python/packages/flet/docs/fastapi/app_manager.md @@ -0,0 +1 @@ +{{ class_all_options("flet.fastapi.app_manager") }} diff --git a/sdk/python/packages/flet/docs/fastapi/fastapi.md b/sdk/python/packages/flet/docs/fastapi/fastapi.md new file mode 100644 index 0000000000..aec05677a9 --- /dev/null +++ b/sdk/python/packages/flet/docs/fastapi/fastapi.md @@ -0,0 +1 @@ +{{ class_all_options("flet.fastapi.FastAPI") }} diff --git a/sdk/python/packages/flet/docs/fastapi/fletapp.md b/sdk/python/packages/flet/docs/fastapi/fletapp.md new file mode 100644 index 0000000000..c8d6e29450 --- /dev/null +++ b/sdk/python/packages/flet/docs/fastapi/fletapp.md @@ -0,0 +1 @@ +{{ class_all_options("flet.fastapi.FletApp") }} diff --git a/sdk/python/packages/flet/docs/fastapi/fletstaticfiles.md b/sdk/python/packages/flet/docs/fastapi/fletstaticfiles.md new file mode 100644 index 0000000000..ff8e6a50d0 --- /dev/null +++ b/sdk/python/packages/flet/docs/fastapi/fletstaticfiles.md @@ -0,0 +1 @@ +{{ class_all_options("flet.fastapi.FletStaticFiles") }} diff --git a/sdk/python/packages/flet/docs/fastapi/fletupload.md b/sdk/python/packages/flet/docs/fastapi/fletupload.md new file mode 100644 index 0000000000..7517365095 --- /dev/null +++ b/sdk/python/packages/flet/docs/fastapi/fletupload.md @@ -0,0 +1 @@ +{{ class_all_options("flet.fastapi.FletUpload") }} diff --git a/sdk/python/packages/flet/docs/geolocator/types/foreground_notification_configuration.md b/sdk/python/packages/flet/docs/geolocator/types/foregroundnotificationconfiguration.md similarity index 100% rename from sdk/python/packages/flet/docs/geolocator/types/foreground_notification_configuration.md rename to sdk/python/packages/flet/docs/geolocator/types/foregroundnotificationconfiguration.md diff --git a/sdk/python/packages/flet/docs/geolocator/types/geolocator_android_configuration.md b/sdk/python/packages/flet/docs/geolocator/types/geolocatorandroidconfiguration.md similarity index 100% rename from sdk/python/packages/flet/docs/geolocator/types/geolocator_android_configuration.md rename to sdk/python/packages/flet/docs/geolocator/types/geolocatorandroidconfiguration.md diff --git a/sdk/python/packages/flet/docs/geolocator/types/geolocator_configuration.md b/sdk/python/packages/flet/docs/geolocator/types/geolocatorconfiguration.md similarity index 100% rename from sdk/python/packages/flet/docs/geolocator/types/geolocator_configuration.md rename to sdk/python/packages/flet/docs/geolocator/types/geolocatorconfiguration.md diff --git a/sdk/python/packages/flet/docs/geolocator/types/geolocator_ios_activity_type.md b/sdk/python/packages/flet/docs/geolocator/types/geolocatoriosactivitytype.md similarity index 100% rename from sdk/python/packages/flet/docs/geolocator/types/geolocator_ios_activity_type.md rename to sdk/python/packages/flet/docs/geolocator/types/geolocatoriosactivitytype.md diff --git a/sdk/python/packages/flet/docs/geolocator/types/geolocator_ios_configuration.md b/sdk/python/packages/flet/docs/geolocator/types/geolocatoriosconfiguration.md similarity index 100% rename from sdk/python/packages/flet/docs/geolocator/types/geolocator_ios_configuration.md rename to sdk/python/packages/flet/docs/geolocator/types/geolocatoriosconfiguration.md diff --git a/sdk/python/packages/flet/docs/geolocator/types/geolocator_permission_status.md b/sdk/python/packages/flet/docs/geolocator/types/geolocatorpermissionstatus.md similarity index 100% rename from sdk/python/packages/flet/docs/geolocator/types/geolocator_permission_status.md rename to sdk/python/packages/flet/docs/geolocator/types/geolocatorpermissionstatus.md diff --git a/sdk/python/packages/flet/docs/geolocator/types/geolocator_position.md b/sdk/python/packages/flet/docs/geolocator/types/geolocatorposition.md similarity index 100% rename from sdk/python/packages/flet/docs/geolocator/types/geolocator_position.md rename to sdk/python/packages/flet/docs/geolocator/types/geolocatorposition.md diff --git a/sdk/python/packages/flet/docs/geolocator/types/geolocator_position_accuracy.md b/sdk/python/packages/flet/docs/geolocator/types/geolocatorpositionaccuracy.md similarity index 100% rename from sdk/python/packages/flet/docs/geolocator/types/geolocator_position_accuracy.md rename to sdk/python/packages/flet/docs/geolocator/types/geolocatorpositionaccuracy.md diff --git a/sdk/python/packages/flet/docs/geolocator/types/geolocator_position_change_event.md b/sdk/python/packages/flet/docs/geolocator/types/geolocatorpositionchangeevent.md similarity index 100% rename from sdk/python/packages/flet/docs/geolocator/types/geolocator_position_change_event.md rename to sdk/python/packages/flet/docs/geolocator/types/geolocatorpositionchangeevent.md diff --git a/sdk/python/packages/flet/docs/geolocator/types/geolocator_web_configuration.md b/sdk/python/packages/flet/docs/geolocator/types/geolocatorwebconfiguration.md similarity index 100% rename from sdk/python/packages/flet/docs/geolocator/types/geolocator_web_configuration.md rename to sdk/python/packages/flet/docs/geolocator/types/geolocatorwebconfiguration.md diff --git a/sdk/python/packages/flet/docs/index.md b/sdk/python/packages/flet/docs/index.md index fa68651fd2..1ea97f2181 100644 --- a/sdk/python/packages/flet/docs/index.md +++ b/sdk/python/packages/flet/docs/index.md @@ -33,7 +33,7 @@ def main(page: ft.Page): ft.run(main) ``` -To run the app, [install `flet`](/getting-started/installation/): +To run the app, [install `flet`](getting-started/installation.md): ```bash pip install 'flet[all]' diff --git a/sdk/python/packages/flet/docs/map/circle_layer.md b/sdk/python/packages/flet/docs/map/circlelayer.md similarity index 100% rename from sdk/python/packages/flet/docs/map/circle_layer.md rename to sdk/python/packages/flet/docs/map/circlelayer.md diff --git a/sdk/python/packages/flet/docs/map/circle_marker.md b/sdk/python/packages/flet/docs/map/circlemarker.md similarity index 100% rename from sdk/python/packages/flet/docs/map/circle_marker.md rename to sdk/python/packages/flet/docs/map/circlemarker.md diff --git a/sdk/python/packages/flet/docs/map/image_source_attribution.md b/sdk/python/packages/flet/docs/map/imagesourceattribution.md similarity index 100% rename from sdk/python/packages/flet/docs/map/image_source_attribution.md rename to sdk/python/packages/flet/docs/map/imagesourceattribution.md diff --git a/sdk/python/packages/flet/docs/map/index.md b/sdk/python/packages/flet/docs/map/index.md index cb4b0333e0..58c21e416f 100644 --- a/sdk/python/packages/flet/docs/map/index.md +++ b/sdk/python/packages/flet/docs/map/index.md @@ -41,8 +41,8 @@ pip install flet-map # (1)! ## Reference - [`Map`](map.md) -- Layers: [`TileLayer`](tile_layer.md), [`MarkerLayer`](marker_layer.md), [`CircleLayer`](circle_layer.md), [`PolygonLayer`](polygon_layer.md), [`PolylineLayer`](polyline_layer.md) -- Markers and overlays: [`Marker`](marker.md), [`CircleMarker`](circle_marker.md), [`PolygonMarker`](polygon_marker.md), [`PolylineMarker`](polyline_marker.md) -- Attributions: [`SimpleAttribution`](simple_attribution.md), [`RichAttribution`](rich_attribution.md), [`SourceAttribution`](source_attribution.md) +- Layers: [`TileLayer`](tilelayer.md), [`MarkerLayer`](markerlayer.md), [`CircleLayer`](circlelayer.md), [`PolygonLayer`](polygonlayer.md), [`PolylineLayer`](polylinelayer.md) +- Markers and overlays: [`Marker`](marker.md), [`CircleMarker`](circlemarker.md), [`PolygonMarker`](polygonmarker.md), [`PolylineMarker`](polylinemarker.md) +- Attributions: [`SimpleAttribution`](simpleattribution.md), [`RichAttribution`](richattribution.md), [`SourceAttribution`](sourceattribution.md) -See the [types](types/attribution_alignment.md) section for additional configuration helpers. +See the [types](types/attributionalignment.md) section for additional configuration helpers. diff --git a/sdk/python/packages/flet/docs/map/map_layer.md b/sdk/python/packages/flet/docs/map/maplayer.md similarity index 100% rename from sdk/python/packages/flet/docs/map/map_layer.md rename to sdk/python/packages/flet/docs/map/maplayer.md diff --git a/sdk/python/packages/flet/docs/map/marker_layer.md b/sdk/python/packages/flet/docs/map/markerlayer.md similarity index 100% rename from sdk/python/packages/flet/docs/map/marker_layer.md rename to sdk/python/packages/flet/docs/map/markerlayer.md diff --git a/sdk/python/packages/flet/docs/map/polygon_layer.md b/sdk/python/packages/flet/docs/map/polygonlayer.md similarity index 100% rename from sdk/python/packages/flet/docs/map/polygon_layer.md rename to sdk/python/packages/flet/docs/map/polygonlayer.md diff --git a/sdk/python/packages/flet/docs/map/polygon_marker.md b/sdk/python/packages/flet/docs/map/polygonmarker.md similarity index 100% rename from sdk/python/packages/flet/docs/map/polygon_marker.md rename to sdk/python/packages/flet/docs/map/polygonmarker.md diff --git a/sdk/python/packages/flet/docs/map/polyline_layer.md b/sdk/python/packages/flet/docs/map/polylinelayer.md similarity index 100% rename from sdk/python/packages/flet/docs/map/polyline_layer.md rename to sdk/python/packages/flet/docs/map/polylinelayer.md diff --git a/sdk/python/packages/flet/docs/map/polyline_marker.md b/sdk/python/packages/flet/docs/map/polylinemarker.md similarity index 100% rename from sdk/python/packages/flet/docs/map/polyline_marker.md rename to sdk/python/packages/flet/docs/map/polylinemarker.md diff --git a/sdk/python/packages/flet/docs/map/rich_attribution.md b/sdk/python/packages/flet/docs/map/richattribution.md similarity index 100% rename from sdk/python/packages/flet/docs/map/rich_attribution.md rename to sdk/python/packages/flet/docs/map/richattribution.md diff --git a/sdk/python/packages/flet/docs/map/simple_attribution.md b/sdk/python/packages/flet/docs/map/simpleattribution.md similarity index 100% rename from sdk/python/packages/flet/docs/map/simple_attribution.md rename to sdk/python/packages/flet/docs/map/simpleattribution.md diff --git a/sdk/python/packages/flet/docs/map/source_attribution.md b/sdk/python/packages/flet/docs/map/sourceattribution.md similarity index 100% rename from sdk/python/packages/flet/docs/map/source_attribution.md rename to sdk/python/packages/flet/docs/map/sourceattribution.md diff --git a/sdk/python/packages/flet/docs/map/text_source_attribution.md b/sdk/python/packages/flet/docs/map/textsourceattribution.md similarity index 100% rename from sdk/python/packages/flet/docs/map/text_source_attribution.md rename to sdk/python/packages/flet/docs/map/textsourceattribution.md diff --git a/sdk/python/packages/flet/docs/map/tile_layer.md b/sdk/python/packages/flet/docs/map/tilelayer.md similarity index 100% rename from sdk/python/packages/flet/docs/map/tile_layer.md rename to sdk/python/packages/flet/docs/map/tilelayer.md diff --git a/sdk/python/packages/flet/docs/map/types/attribution_alignment.md b/sdk/python/packages/flet/docs/map/types/attributionalignment.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/attribution_alignment.md rename to sdk/python/packages/flet/docs/map/types/attributionalignment.md diff --git a/sdk/python/packages/flet/docs/map/types/camera_fit.md b/sdk/python/packages/flet/docs/map/types/camerafit.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/camera_fit.md rename to sdk/python/packages/flet/docs/map/types/camerafit.md diff --git a/sdk/python/packages/flet/docs/map/types/cursor_keyboard_rotation_configuration.md b/sdk/python/packages/flet/docs/map/types/cursorkeyboardrotationconfiguration.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/cursor_keyboard_rotation_configuration.md rename to sdk/python/packages/flet/docs/map/types/cursorkeyboardrotationconfiguration.md diff --git a/sdk/python/packages/flet/docs/map/types/cursor_rotation_behaviour.md b/sdk/python/packages/flet/docs/map/types/cursorrotationbehaviour.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/cursor_rotation_behaviour.md rename to sdk/python/packages/flet/docs/map/types/cursorrotationbehaviour.md diff --git a/sdk/python/packages/flet/docs/map/types/dashed_stroke_pattern.md b/sdk/python/packages/flet/docs/map/types/dashedstrokepattern.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/dashed_stroke_pattern.md rename to sdk/python/packages/flet/docs/map/types/dashedstrokepattern.md diff --git a/sdk/python/packages/flet/docs/map/types/dotted_stroke_pattern.md b/sdk/python/packages/flet/docs/map/types/dottedstrokepattern.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/dotted_stroke_pattern.md rename to sdk/python/packages/flet/docs/map/types/dottedstrokepattern.md diff --git a/sdk/python/packages/flet/docs/map/types/fade_in_tile_display.md b/sdk/python/packages/flet/docs/map/types/fadeintiledisplay.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/fade_in_tile_display.md rename to sdk/python/packages/flet/docs/map/types/fadeintiledisplay.md diff --git a/sdk/python/packages/flet/docs/map/types/instantaneous_tile_display.md b/sdk/python/packages/flet/docs/map/types/instantaneoustiledisplay.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/instantaneous_tile_display.md rename to sdk/python/packages/flet/docs/map/types/instantaneoustiledisplay.md diff --git a/sdk/python/packages/flet/docs/map/types/interaction_configuration.md b/sdk/python/packages/flet/docs/map/types/interactionconfiguration.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/interaction_configuration.md rename to sdk/python/packages/flet/docs/map/types/interactionconfiguration.md diff --git a/sdk/python/packages/flet/docs/map/types/interaction_flag.md b/sdk/python/packages/flet/docs/map/types/interactionflag.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/interaction_flag.md rename to sdk/python/packages/flet/docs/map/types/interactionflag.md diff --git a/sdk/python/packages/flet/docs/map/types/keyboard_configuration.md b/sdk/python/packages/flet/docs/map/types/keyboardconfiguration.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/keyboard_configuration.md rename to sdk/python/packages/flet/docs/map/types/keyboardconfiguration.md diff --git a/sdk/python/packages/flet/docs/map/types/map_event.md b/sdk/python/packages/flet/docs/map/types/mapevent.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/map_event.md rename to sdk/python/packages/flet/docs/map/types/mapevent.md diff --git a/sdk/python/packages/flet/docs/map/types/map_event_source.md b/sdk/python/packages/flet/docs/map/types/mapeventsource.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/map_event_source.md rename to sdk/python/packages/flet/docs/map/types/mapeventsource.md diff --git a/sdk/python/packages/flet/docs/map/types/map_hover_event.md b/sdk/python/packages/flet/docs/map/types/maphoverevent.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/map_hover_event.md rename to sdk/python/packages/flet/docs/map/types/maphoverevent.md diff --git a/sdk/python/packages/flet/docs/map/types/map_latitude_longitude.md b/sdk/python/packages/flet/docs/map/types/maplatitudelongitude.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/map_latitude_longitude.md rename to sdk/python/packages/flet/docs/map/types/maplatitudelongitude.md diff --git a/sdk/python/packages/flet/docs/map/types/map_latitude_longitude_bounds.md b/sdk/python/packages/flet/docs/map/types/maplatitudelongitudebounds.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/map_latitude_longitude_bounds.md rename to sdk/python/packages/flet/docs/map/types/maplatitudelongitudebounds.md diff --git a/sdk/python/packages/flet/docs/map/types/map_pointer_event.md b/sdk/python/packages/flet/docs/map/types/mappointerevent.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/map_pointer_event.md rename to sdk/python/packages/flet/docs/map/types/mappointerevent.md diff --git a/sdk/python/packages/flet/docs/map/types/map_position_change_event.md b/sdk/python/packages/flet/docs/map/types/mappositionchangeevent.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/map_position_change_event.md rename to sdk/python/packages/flet/docs/map/types/mappositionchangeevent.md diff --git a/sdk/python/packages/flet/docs/map/types/map_tap_event.md b/sdk/python/packages/flet/docs/map/types/maptapevent.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/map_tap_event.md rename to sdk/python/packages/flet/docs/map/types/maptapevent.md diff --git a/sdk/python/packages/flet/docs/map/types/multi_finger_gesture.md b/sdk/python/packages/flet/docs/map/types/multifingergesture.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/multi_finger_gesture.md rename to sdk/python/packages/flet/docs/map/types/multifingergesture.md diff --git a/sdk/python/packages/flet/docs/map/types/pattern_fit.md b/sdk/python/packages/flet/docs/map/types/patternfit.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/pattern_fit.md rename to sdk/python/packages/flet/docs/map/types/patternfit.md diff --git a/sdk/python/packages/flet/docs/map/types/solid_stroke_pattern.md b/sdk/python/packages/flet/docs/map/types/solidstrokepattern.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/solid_stroke_pattern.md rename to sdk/python/packages/flet/docs/map/types/solidstrokepattern.md diff --git a/sdk/python/packages/flet/docs/map/types/stroke_pattern.md b/sdk/python/packages/flet/docs/map/types/strokepattern.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/stroke_pattern.md rename to sdk/python/packages/flet/docs/map/types/strokepattern.md diff --git a/sdk/python/packages/flet/docs/map/types/tile_display.md b/sdk/python/packages/flet/docs/map/types/tiledisplay.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/tile_display.md rename to sdk/python/packages/flet/docs/map/types/tiledisplay.md diff --git a/sdk/python/packages/flet/docs/map/types/tile_layer_evict_error_tile_strategy.md b/sdk/python/packages/flet/docs/map/types/tilelayerevicterrortilestrategy.md similarity index 100% rename from sdk/python/packages/flet/docs/map/types/tile_layer_evict_error_tile_strategy.md rename to sdk/python/packages/flet/docs/map/types/tilelayerevicterrortilestrategy.md diff --git a/sdk/python/packages/flet/docs/permission_handler/types/permission_status.md b/sdk/python/packages/flet/docs/permission_handler/types/permissionstatus.md similarity index 100% rename from sdk/python/packages/flet/docs/permission_handler/types/permission_status.md rename to sdk/python/packages/flet/docs/permission_handler/types/permissionstatus.md diff --git a/sdk/python/packages/flet/docs/publish/android.md b/sdk/python/packages/flet/docs/publish/android.md index b276a1b1f9..8c2ce2bb51 100644 --- a/sdk/python/packages/flet/docs/publish/android.md +++ b/sdk/python/packages/flet/docs/publish/android.md @@ -5,32 +5,42 @@ title: Packaging app for Android Instructions for packaging a Flet app into an Android APK and Android App Bundle (AAB). -**See complementary information [here](index.md).** +/// admonition | Info + type: tip +This guide provides detailed on Android-specific information. +Complementary and more general information is available [here](index.md). +/// ## Prerequisites ### Android SDK -The build process requires both **Java** ([JDK](https://de.wikipedia.org/wiki/Java_Development_Kit)) -and the **Android SDK**. +The build process requires both **Java** (JDK 17) and the **Android SDK**. If either component is missing or an incompatible version is detected, the required tools will be **automatically installed** during the first run of the [`flet build`](../cli/flet-build.md) command. -- The JDK will be installed in `$HOME/java/{version}`. -- If **Android Studio** is installed, Flet CLI will automatically use the Android SDK bundled with it. - Otherwise, a standalone Android SDK will be installed in: - `$HOME/Android/sdk` +- The JDK is installed in `$HOME/java/` (for example, `17.0.13+11`). +- If [**Android Studio**](https://developer.android.com/studio) is installed, Flet CLI will use its SDK: + - macOS: `~/Library/Android/sdk` + - Windows: `%LOCALAPPDATA%\Android\Sdk` + - Linux: `~/Android/Sdk` +- Otherwise, a standalone Android SDK is installed in: + - macOS/Linux: `~/Android/sdk` + - Windows: `%USERPROFILE%\Android\sdk` + +`ANDROID_HOME` and `ANDROID_SDK_ROOT` are also respected if set. ### Android wheels for binary Python packages -Binary Python packages (in contrast to "pure" Python packages written in Python only) are packages that partially -written in C, Rust or other languages producing native code. Example packages are `numpy`, `cryptography`, or `pydantic-core`. +Binary Python packages (in contrast to "pure" Python packages written in Python only) +are packages that are partially written in C, Rust, or other languages producing native code. +Example packages are `numpy`, `cryptography`, or `pydantic-core`. Make sure all non-pure (binary) packages used in your Flet app have [pre-built wheels for Android](../reference/binary-packages-android-ios.md). -## `flet build apk` +## `flet build apk` /// admonition | Note This command can be run on a **macOS**, **Linux**, or **Windows**. @@ -48,66 +58,55 @@ For Play Store deployment, it’s recommended to: ### Split APK per ABI -Different Android devices use different CPUs, which in turn support different instruction sets. -Each combination of CPU and instruction set has its own [Application Binary Interface (ABI)](https://developer.android.com/ndk/guides/abis). +Android devices use different CPUs, so APKs can target different +[Application Binary Interfaces (ABIs)](https://developer.android.com/ndk/guides/abis). -By default, Flet will build a "fat" APK which includes binaries for both -[`arm64-v8a`](https://developer.android.com/ndk/guides/abis#arm64-v8a) and -[`armeabi-v7a`](https://developer.android.com/ndk/guides/abis#v7a) architectures. +By default, Flet builds a single "fat" APK that contains +native binaries for all supported ABIs. This maximizes +device compatibility but increases APK size. -You can split fat APK into smaller APKs for each platform as follows: +Enabling ABI splits produces one APK per ABI, which reduces file size but +requires distributing the correct APK for each device. -/// tab | `pyproject.toml` +#### Supported target architectures -/// tab | `[tool.flet.android]` -```toml -[tool.flet.android] -split_per_abi = true -``` -/// +The following target architectures are supported: -/// -/// tab | `flet build` -```bash -flet build apk --split-per-abi -``` -/// - -/// admonition | Note - type: caution -Splitting APKs per ABI will generate multiple APK files, each targeting a specific architecture. -Make sure to distribute the correct APK to users based on their device's CPU architecture, -as installing an incompatible APK will result in installation failure. -/// - -### Installing APK to a device - -The easiest way to install APK to your device is to use the -[Android Debug Bridge](https://developer.android.com/tools/adb) (adb) tool, -a command-line tool that can communicate between your computer and your Android device. +- [`arm64-v8a`](https://developer.android.com/ndk/guides/abis#arm64-v8a) +- [`armeabi-v7a`](https://developer.android.com/ndk/guides/abis#v7a) +- [`x86_64`](https://developer.android.com/ndk/guides/abis#86-64) +- [`x86`](https://developer.android.com/ndk/guides/abis#x86) -`adb` is a part of the Android SDK. On macOS, for example, if the Android SDK was -installed with Android Studio its location will be at `~/Library/Android/sdk/platform-tools/adb`. +#### Resolution order -Refer to this [guide](https://www.makeuseof.com/install-apps-via-adb-android/) for -more information about installing and using `adb` on various platforms. +Its value is determined in the following order of precedence: -To install an APK to a device run the following command: +1. [`--split-per-abi`](../cli/flet-build.md#-split-per-abi) +2. `[tool.flet.android].split_per_abi` +3. `false` -``` -adb install -``` +When enabled, 3 APKs are produced by default, one for each of the following ABIs: `arm64-v8a`, +`armeabi-v7a`, and `x86_64`. These can be customized by setting [`target architectures`](index.md#target-architecture). -If more than one device is connected to your computer (say, emulator and a physical phone) you can -use `-s` option to specify which device you want to install `.apk` on: +#### Example +/// tab | `flet build` +```bash +flet build apk --split-per-abi ``` -adb -s install +/// +/// tab | `pyproject.toml` +```toml +[tool.flet.android] +split_per_abi = true ``` +/// -where `` can be found with `adb devices` command. +## `flet build aab` -## `flet build aab` +/// admonition | Note +This command can be run on a **macOS**, **Linux**, or **Windows**. +/// Builds a **release** [Android App Bundle (AAB)](https://developer.android.com/guide/app-bundle) file. @@ -117,6 +116,10 @@ and are intended for publishing to app stores such as the [Google Play Store](ht It is recommended to use this AAB format (instead of [APK](#flet-build-apk)) for publishing to the Google Play Store due to its optimized app size. +If you need to limit the ABIs included in the bundle, use +[`--arch`](index.md#target-architecture) / `[tool.flet.android].target_arch` +while `split_per_abi` is `false`. + ## Signing an Android bundle Android requires that all APKs be digitally signed with a certificate before they are installed @@ -138,6 +141,11 @@ To create your app signing key, use Play App Signing as described in the To sign your app, use the following instructions. +/// admonition | Note +If you don't provide an upload keystore, release builds are signed with the +debug key. This is fine for local testing but cannot be uploaded to the Play Store. +/// + ### Create an upload keystore If you have an existing keystore, skip to the next step. @@ -160,7 +168,7 @@ If not, create one using one of the following methods: -alias upload ``` You will be prompted for several details, such as a keystore password, - a key alias, your names and location. Remember the password and alias + a key alias, your names, and location. Remember the password and alias for use in the [configuration](#configuration) step below. A file named `upload-keystore.jks` will be created in your home directory. @@ -183,45 +191,55 @@ If not, create one using one of the following methods: Keep your `keystore` file private; never check it into public source control! /// -### Configuration - -#### Key alias +### Key alias An alias name for the key within the keystore. +#### Resolution order + +Its value is determined in the following order of precedence: + +1. [`--android-signing-key-alias`](../cli/flet-build.md#-android-signing-key-alias) +2. `FLET_ANDROID_SIGNING_KEY_ALIAS` +3. `[tool.flet.android.signing].key_alias` +4. `"upload"` + +#### Example + /// tab | `flet build` ```bash flet build aab --android-signing-key-alias value ``` /// /// tab | `pyproject.toml` - -/// tab | `[tool.flet.android]` -```toml -[tool.flet.android] -signing.key_alias = "value" -``` -/// -/// tab | `[tool.flet.android.signing]` ```toml [tool.flet.android.signing] key_alias = "value" ``` /// - -/// -/// tab | Environment Variable -```bash +/// tab | `.env` +```dotenv FLET_ANDROID_SIGNING_KEY_ALIAS="value" ``` /// -#### Key store +### Key store The path to the keystore file (with extension `.jks`). -If you used the cli commands above as-is, this file might be located at `/Users//upload-keystore.jks` on macOS -or `C:\\Users\\\\upload-keystore.jks` on Windows. +If you used the CLI commands [above](#create-an-upload-keystore) as-is, this file might be +located at `/Users//upload-keystore.jks` on macOS +or `C:\Users\\upload-keystore.jks` on Windows. + +#### Resolution order + +Its value is determined in the following order of precedence: + +1. [`--android-signing-key-store`](../cli/flet-build.md#-android-signing-key-store) +2. `[tool.flet.android.signing].key_store` +3. `FLET_ANDROID_SIGNING_KEY_STORE` + +#### Example /// tab | `flet build` ```bash @@ -229,27 +247,30 @@ flet build aab --android-signing-key-store path/to/store.jks ``` /// /// tab | `pyproject.toml` - -/// tab | `[tool.flet.android]` -```toml -[tool.flet.android] -signing.key_store = "path/to/store.jks" -``` -/// -/// tab | `[tool.flet.android.signing]` ```toml [tool.flet.android.signing] key_store = "path/to/store.jks" ``` /// - +/// tab | `.env` +```dotenv +FLET_ANDROID_SIGNING_KEY_STORE="path/to/store.jks" +``` /// -#### Key store password +### Key store password A password to unlock the keystore file (can contain multiple key entries). -If not provided, defaults to the [key password](#key-password) +#### Resolution order + +Its value is determined in the following order of precedence: + +1. [`--android-signing-key-store-password`](../cli/flet-build.md#-android-signing-key-store-password) +2. `FLET_ANDROID_SIGNING_KEY_STORE_PASSWORD` +3. [key password](#key-password) + +#### Example /// tab | `flet build` ```bash @@ -257,22 +278,28 @@ flet build aab --android-signing-key-store-password value ``` /// /// tab | `pyproject.toml` - For security reasons, the keystore password is not read from `pyproject.toml` to prevent accidental exposure in source control. See the other tabs for supported alternatives. - /// -/// tab | Environment Variable -```bash +/// tab | `.env` +```dotenv FLET_ANDROID_SIGNING_KEY_STORE_PASSWORD="value" ``` /// -#### Key password +### Key password A password used to access the private key inside the keystore. -If not provided, defaults to the [key store password](#key-store-password) +#### Resolution order + +Its value is determined in the following order of precedence: + +1. [`--android-signing-key-password`](../cli/flet-build.md#-android-signing-key-password) +2. `FLET_ANDROID_SIGNING_KEY_PASSWORD` +3. [key store password](#key-store-password) + +#### Example /// tab | `flet build` ```bash @@ -280,51 +307,51 @@ flet build aab --android-signing-key-password value ``` /// /// tab | `pyproject.toml` - For security reasons, the keystore password is not read from `pyproject.toml` to prevent accidental exposure in source control. See the other tabs for supported alternatives. - /// -/// tab | Environment Variable -```bash +/// tab | `.env` +```dotenv FLET_ANDROID_SIGNING_KEY_PASSWORD="value" ``` /// -## Disable splash screen +## Android Manifest -The [splash screen](index.md#splash-screen) is enabled/shown by default. +The [Android Manifest](https://developer.android.com/guide/topics/manifest/manifest-intro) describes +essential information about your app to the Android build tools, +the Android operating system, and Google Play. The file in which this information is written +is `AndroidManifest.xml`, which gets populated with the information you provide. -It can be disabled as follows: +### Application attributes -/// tab | `flet build` -```bash -flet build apk --no-android-splash -``` -/// -/// tab | `pyproject.toml` +You can add or override attributes on the `` element of the +`AndroidManifest.xml` file in the [build template](index.md#build-template). -/// tab | `[tool.flet]` -```toml -[tool.flet] -splash.android = false -``` -/// -/// tab | `[tool.flet.splash]` +#### Resolution order + +Its value is determined in the following order of precedence: + +1. `[tool.flet.android.manifest_application]` + +#### Example + +/// tab | `pyproject.toml` ```toml -[tool.flet.splash] -android = false +[tool.flet.android.manifest_application] +usesCleartextTraffic = "true" +allowBackup = "false" ``` /// -/// +In the [`AndroidManifest.xml`](index.md#build-template), it will be translated accordingly into this: -## Android Manifest - -The [Android Manifest](https://developer.android.com/guide/topics/manifest/manifest-intro) describes -essential information about your app to the Android build tools, -the Android operating system, and Google Play. The file in which this information is written -is `AndroidManifest.xml`, which gets populated with the information you provide. +```xml + + +``` ### Meta-data @@ -334,13 +361,18 @@ More information [here](https://developer.android.com/guide/topics/manifest/meta A meta-data item is composed of: - `name`: A unique name for the item, usually with a Java-style naming convention, for example `"com.sample.project.activity.fred"`. -- `value`: The value of the item. The following types are supported: - - **String**: use double backslashes (`\\`) to escape characters, such as `\\n` for a new line and `\\uxxxxx` for a Unicode character - - **Integer**: for example `123` - - **Boolean**: either `"true"` or `"false"` - - **Float**: for example `1.23` +- `value`: The value of the item. Android supports strings, integers, booleans, and floats. + Flet writes values as strings, so pass the literal value you want Android to read + (for example `"true"`, `"123"`, `"1.23"`). + +#### Resolution order -You can configure meta-data as follows: +Its value is determined in the following order of precedence: + +1. [`--android-meta-data`](../cli/flet-build.md#-android-meta-data) +2. `[tool.flet.android.meta_data]` + +#### Example /// tab | `flet build` ```bash @@ -348,25 +380,14 @@ flet build apk --android-meta-data name_1=value_1 name_2=value_2 ``` /// /// tab | `pyproject.toml` - -/// tab | `[tool.flet.android]` -```toml -[tool.flet.android] -meta_data."name_1" = value_1 -meta_data."name_2" = value_2 -``` -/// -/// tab | `[tool.flet.android.meta_data]` ```toml [tool.flet.android.meta_data] -"name_1" = value_1 -"name_2" = value_2 +"name_1" = "value_1" +"name_2" = "value_2" ``` /// -/// - -And it will be translated accordingly into this in the `AndroidManifest.xml`: +In the [`AndroidManifest.xml`](index.md#build-template), it will be translated accordingly into this: ```xml @@ -385,107 +406,117 @@ More information [here](https://developer.android.com/guide/topics/manifest/uses These attribute values are case-sensitive. - `required`: A boolean value (`True` or `False`) that indicates whether the application requires the feature specified by the `name`. -You can configure features as follows: +#### Resolution order + +Its value is determined in the following order of precedence: + +1. [`--android-features`](../cli/flet-build.md#-android-features) +2. `[tool.flet.android.feature]` +3. [`Permissions`](index.md#permissions) +4. defaults: `android.software.leanback=false`, `android.hardware.touchscreen=false` + +#### Example /// tab | `flet build` ```bash -flet build apk --android-features name_1=required_1 name_2=required_2 +flet build apk --android-features android.hardware.camera=True android.hardware.location.gps=False ``` /// /// tab | `pyproject.toml` - -/// tab | `[tool.flet.android]` -```toml -[tool.flet.android] -feature."name_1" = required_1 -feature."name_2" = required_2 -``` -/// -/// tab | `[tool.flet.android.feature]` ```toml -[tool.flet.android.meta_data] -"name_1" = required_1 -"name_2" = required_2 +[tool.flet.android.feature] +"android.hardware.camera" = true +"android.hardware.location.gps" = false ``` /// -/// - -And it will be translated accordingly into this in the `AndroidManifest.xml`: +In the [`AndroidManifest.xml`](index.md#build-template), it will be translated accordingly into this: ```xml - - + + ``` -Where the `required` value is either `true` or `false`. - -Below are default/pre-configured features: - -- `"android.software.leanback" = False` -- `"android.hardware.touchscreen" = False` - ### Permissions -Configuring Android permissions and features to be written into `AndroidManifest.xml`: - -``` -flet build --android-permissions permission=True|False ... --android-features feature_name=True|False -``` +Use cross-platform permissions from [Permissions](index.md#permissions) when possible, +and add Android-specific permissions or features here. -For example: +#### Resolution order -``` -flet build \ - --android-permissions android.permission.READ_EXTERNAL_STORAGE=True \ - android.permission.WRITE_EXTERNAL_STORAGE=True \ - --android-features android.hardware.location.network=False -``` +Its value is determined in the following order of precedence: -Default Android permissions: +1. [`--android-permissions`](../cli/flet-build.md#-android-permissions) +2. `[tool.flet.android.permission]` +3. [`--permissions`](index.md#permissions) / `[tool.flet].permissions` +4. defaults: `android.permission.INTERNET=true` -* `android.permission.INTERNET` +CLI values are `True` or `False` (case-sensitive). In `pyproject.toml`, use `true`/`false`. -Default permissions can be disabled with `--android-permissions` option and `False` value, for example: +#### Example +/// tab | `flet build` +```bash +flet build apk --android-permissions android.permission.READ_EXTERNAL_STORAGE=True android.permission.WRITE_EXTERNAL_STORAGE=True ``` -flet build --android-permissions android.permission.INTERNET=False +/// +/// tab | `pyproject.toml` +```toml +[tool.flet.android.permission] +"android.permission.READ_EXTERNAL_STORAGE" = true +"android.permission.WRITE_EXTERNAL_STORAGE" = true ``` +/// -Default Android features: +In the [`AndroidManifest.xml`](index.md#build-template), it will be translated accordingly into this: -* `android.software.leanback=False` (`False` means it's written in manifest as `android:required="false"`) -* `android.hardware.touchscreen=False` +```xml + + + + +``` -Configuring permissions and features in `pyproject.toml` (notice quotes `"` around key names): +## ADB Tips -```toml -[tool.flet.android.permission] # --android-permissions -"android.permission.CAMERA" = true -"android.permission.CAMERA" = true +[Android Debug Bridge (adb)](https://developer.android.com/tools/adb) is a +command-line tool included in the Android SDK that lets you communicate +with Android devices and emulators. -[tool.flet.android.feature] # --android-features -"android.hardware.camera" = false -``` +If you installed Android Studio on macOS, +`adb` is typically located at: `~/Library/Android/sdk/platform-tools/adb`. -## ADB Tips +See this [guide](https://www.makeuseof.com/install-apps-via-adb-android/) for +help installing and using adb on different platforms. -To run interactive commands inside simulator or device: +1. To run interactive commands inside an Android simulator or device: + ```bash + adb shell + ``` -``` -adb shell -``` +2. To overcome "permissions denied" error while trying to browse file system in interactive Android shell: + ```bash + su + ``` -To overcome "permissions denied" error while trying to browse file system in interactive Android shell: +3. To download a file from a device to your local computer: + ```bash + adb pull + ``` -``` -su -``` +4. To install an APK on an Android device: + ```bash + adb install + ``` -To download a file from a device to your local computer: + This works for both physical devices and emulators. If more than one device is connected, specify the target device: + ```bash + adb -s install + ``` -``` -adb pull -``` + You can list available devices with: + ```bash + adb devices + ``` diff --git a/sdk/python/packages/flet/docs/publish/index.md b/sdk/python/packages/flet/docs/publish/index.md index 22505f7a69..0457de3598 100644 --- a/sdk/python/packages/flet/docs/publish/index.md +++ b/sdk/python/packages/flet/docs/publish/index.md @@ -1,14 +1,14 @@ -# Publishing Flet app +# Publishing a Flet app -Flet CLI provides [`flet build`](../cli/flet-build.md) command that allows packaging Flet app into a standalone executable -or install package for distribution. +Flet CLI provides the [`flet build`](../cli/flet-build.md) command to package a +Flet app into a standalone executable or installable package for distribution. ## Prerequisites ### Platform matrix -The following matrix shows which OS you should run `flet build` command on in -order to build a package for specific platform: +Use the following matrix to choose which OS to run `flet build` +on for each target platform: