diff --git a/cookiecutter.json b/cookiecutter.json index 21c3a26..95fbf1d 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -10,7 +10,6 @@ "copyright": "Copyright (c) 2023 Your Company", "flutter": null, "sep": "/", - "hide_loading_animation": true, "bundle_id": "{{ cookiecutter.bundle_id if 'bundle_id' in cookiecutter else cookiecutter.org_name + '.' + cookiecutter.project_name_slug }}", "org_name_2": "{{ cookiecutter.bundle_id.rsplit('.', 1)[0] if 'bundle_id' in cookiecutter else cookiecutter.org_name if 'org_name' in cookiecutter else 'com.flet' }}", "ios_provisioning_profile": "", @@ -28,5 +27,6 @@ "pwa_theme_color": "#0175C2", "split_per_abi": false, "options": null, - "pyproject": null + "pyproject": null, + "_extensions": ["cookiecutter_extensions.FletExtension"] } \ No newline at end of file diff --git a/cookiecutter_extensions.py b/cookiecutter_extensions.py new file mode 100644 index 0000000..89719c3 --- /dev/null +++ b/cookiecutter_extensions.py @@ -0,0 +1,22 @@ +from jinja2 import pass_context +from jinja2.ext import Extension + + +class FletExtension(Extension): + def __init__(self, environment): + super(FletExtension, self).__init__(environment) + environment.globals["get_pyproject"] = self.get_pyproject + + @pass_context + def get_pyproject(self, context, setting): + pyproject = context.get("cookiecutter", {}).get("pyproject", {}) + + if not setting: + return pyproject + + d = pyproject + for k in setting.split("."): + d = d.get(k) + if d is None: + return None + return d diff --git a/{{cookiecutter.out_dir}}/_macros.jinja2 b/{{cookiecutter.out_dir}}/_macros.jinja2 deleted file mode 100644 index 1cfe0cc..0000000 --- a/{{cookiecutter.out_dir}}/_macros.jinja2 +++ /dev/null @@ -1,16 +0,0 @@ -{# _macros.jinja2 #} - -{% macro get_value(dict, path) %} - {# Split the path into keys #} - {% set keys = path.split('.') %} - {% if keys and dict is mapping and keys[0] in dict %} - {% set next_value = dict[keys[0]] %} - {% if keys | length == 1 %} - {{ next_value }} - {% else %} - {{ get_value(next_value, keys[1:] | join('.')) }} - {% endif %} - {% else %} - {{ "" }} - {% endif %} -{% endmacro %} \ No newline at end of file diff --git a/{{cookiecutter.out_dir}}/android/app/build.gradle b/{{cookiecutter.out_dir}}/android/app/build.gradle index 29ea442..8149dfa 100644 --- a/{{cookiecutter.out_dir}}/android/app/build.gradle +++ b/{{cookiecutter.out_dir}}/android/app/build.gradle @@ -1,4 +1,3 @@ -{% import "_macros.jinja2" as macros %} plugins { id "com.android.application" id "kotlin-android" @@ -50,8 +49,8 @@ android { main.java.srcDirs += 'src/main/kotlin' } - {% set min_sdk_version = macros.get_value(cookiecutter.pyproject, "tool.flet.android.min_sdk_version") | trim %} - {% set target_sdk_version = macros.get_value(cookiecutter.pyproject, "tool.flet.android.target_sdk_version") | trim %} + {% set min_sdk_version = get_pyproject("tool.flet.android.min_sdk_version") %} + {% set target_sdk_version = get_pyproject("tool.flet.android.target_sdk_version") %} defaultConfig { applicationId "{{ cookiecutter.org_name_2 }}.{{ cookiecutter.package_name }}" diff --git a/{{cookiecutter.out_dir}}/lib/main.dart b/{{cookiecutter.out_dir}}/lib/main.dart index dd1c379..0bf4927 100644 --- a/{{cookiecutter.out_dir}}/lib/main.dart +++ b/{{cookiecutter.out_dir}}/lib/main.dart @@ -14,6 +14,25 @@ import 'package:window_manager/window_manager.dart'; import "python.dart"; +/* +{% set show_boot_screen = get_pyproject("tool.flet." ~ cookiecutter.options.config_platform ~ ".app.boot_screen.show") + or get_pyproject("tool.flet.app.boot_screen.show") + or False %} +{% set boot_screen_message = get_pyproject("tool.flet." ~ cookiecutter.options.config_platform ~ ".app.boot_screen.message") + or get_pyproject("tool.flet.app.boot_screen.message") %} + +{% set show_startup_screen = get_pyproject("tool.flet." ~ cookiecutter.options.config_platform ~ ".app.startup_screen.show") + or get_pyproject("tool.flet.app.startup_screen.show") + or False %} +{% set startup_screen_message = get_pyproject("tool.flet." ~ cookiecutter.options.config_platform ~ ".app.startup_screen.message") + or get_pyproject("tool.flet.app.startup_screen.message") %} + +show_boot_screen: {{ show_boot_screen }} +boot_screen_message: {{ boot_screen_message }} +show_startup_screen: {{ show_startup_screen }} +startup_screen_message: {{ startup_screen_message }} +*/ + {% for dep in cookiecutter.flutter.dependencies %} import 'package:{{ dep }}/{{ dep }}.dart' as {{ dep }}; {% endfor %} @@ -22,9 +41,10 @@ const bool isProduction = bool.fromEnvironment('dart.vm.product'); const assetPath = "app/app.zip"; const pythonModuleName = "{{ cookiecutter.python_module_name }}"; -final hideLoadingPage = - bool.tryParse("{{ cookiecutter.hide_loading_animation }}".toLowerCase()) ?? - true; +final showAppBootScreen = bool.tryParse("{{ show_boot_screen }}".toLowerCase()) ?? false; +const appBootScreenMessage = '{{ boot_screen_message | default("Preparing the app for its first launch…", true) }}'; +final showAppStartupScreen = bool.tryParse("{{ show_startup_screen }}".toLowerCase()) ?? false; +const appStartupScreenMessage = '{{ startup_screen_message | default("Getting things ready…", true) }}'; List createControlFactories = [ {% for dep in cookiecutter.flutter.dependencies %} @@ -53,7 +73,8 @@ void main(List args) async { ? FletApp( pageUrl: pageUrl, assetsDir: assetsDir, - hideLoadingPage: hideLoadingPage, + showAppStartupScreen: showAppStartupScreen, + appStartupScreenMessage: appStartupScreenMessage, createControlFactories: createControlFactories) : FutureBuilder( future: runPythonApp(args), @@ -71,7 +92,8 @@ void main(List args) async { return FletApp( pageUrl: pageUrl, assetsDir: assetsDir, - hideLoadingPage: hideLoadingPage, + showAppStartupScreen: showAppStartupScreen, + appStartupScreenMessage: appStartupScreenMessage, createControlFactories: createControlFactories); } }); @@ -83,7 +105,7 @@ void main(List args) async { text: snapshot.error.toString())); } else { // loading - return const MaterialApp(home: BlankScreen()); + return MaterialApp(home: showAppBootScreen ? const BootScreen() : const BlankScreen()); } })); } @@ -294,6 +316,34 @@ class ErrorScreen extends StatelessWidget { } } +class BootScreen extends StatelessWidget { + const BootScreen({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + width: 30, + height: 30, + child: CircularProgressIndicator(strokeWidth: 3), + ), + const SizedBox( + height: 10, + ), + Text(appBootScreenMessage, style: Theme.of(context).textTheme.bodySmall,) + ], + ), + ), + ); + } +} + class BlankScreen extends StatelessWidget { const BlankScreen({ super.key, diff --git a/{{cookiecutter.out_dir}}/pubspec.yaml b/{{cookiecutter.out_dir}}/pubspec.yaml index 3a12eac..06d01b5 100644 --- a/{{cookiecutter.out_dir}}/pubspec.yaml +++ b/{{cookiecutter.out_dir}}/pubspec.yaml @@ -21,13 +21,13 @@ dependencies: window_manager: ^0.4.3 dependency_overrides: - flet: 0.27.4 + #flet: 0.27.4 - # flet: - # git: - # path: packages/flet - # ref: main - # url: https://github.com/flet-dev/flet.git + flet: + git: + path: packages/flet + ref: feodor/flet-0-27-5-fixes + url: https://github.com/flet-dev/flet.git # serious_python: # git: @@ -121,14 +121,10 @@ flutter_native_splash: # 768 pixels in diameter. image: "images/icon.png" - # Splash screen background color. - color: "#ffffff" - # The image_dark, color_dark, icon_background_color_dark, and branding_dark set values that # apply when the device is in dark mode. If they are not specified, the app will use the # parameters from above. image_dark: "images/icon.png" - color_dark: "#333333" # The android, ios and web parameters can be used to disable generating a splash screen on a given # platform.