Compare commits

...

101 Commits
main ... 0.27.1

Author SHA1 Message Date
TheEthicalBoy 504ec17fd6
`flet: 0.27.1` in dependency_overrides 2025-02-23 15:41:39 +01:00
Feodor Fitsner f45821c6af
Create proguard-rules.pro (#40) 2025-02-22 16:12:47 -08:00
Feodor Fitsner 070537e4b0 flet: 0.27.0 2025-02-21 18:59:07 -08:00
Feodor Fitsner 9043b531ab Misc template var fixes for 0.27.0 2025-02-21 16:46:00 -08:00
Feodor Fitsner a49c9f3d86 serious_python: 0.9.0 2025-02-19 17:30:49 -08:00
Feodor Fitsner 2043b4a1cb
for 0.27.0 iOS packaging improved (#39)
* Override serious_python

* Fix yaml

* Manual signing and provisioning profile

* Introduce bundle_id and project_name

* Fix dict checks

* exportOptions.plist

* Output all vars

* Move .vars

* Fix expor options template

* Format template

* Pyodide 0.27.2

* Add teamid

* Added "ios_signing_certificate" var

* serious_python:main

* Fake run script to sign iOS bundle frameworks

* Updated sign script

* Explicitly sign .py files

* Remove custom code signing

* Use serious_python:resources branch

* return to main

* resources branch

* Add build_arch for Android

* Rename build_arch to target_arch

* Fix target_arch def value

* Hide target_arch inside options

* serious_python:main

* .plist to support arrays

* Add closing if

* fix template

* Another template fix

* Remove comments

* macOS plist to support arrays
2025-02-18 15:38:30 -08:00
Feodor Fitsner c99bd8f120
0.26.0 fix for flet-ads and others (#37)
* Relax Flet req

* Flet override
2025-01-27 10:24:48 -08:00
Feodor Fitsner 08844c6e1d Use Flet 0.26.0 2025-01-26 13:13:06 -08:00
Feodor Fitsner a80ff08a9b fix _args list 2025-01-21 13:50:29 -08:00
Feodor Fitsner 29c074847e dependency_overrides.flet 2025-01-21 11:07:08 -08:00
Feodor Fitsner 6a773c37f7 Override webview_flutter_android: ^4.0.0 2025-01-16 10:51:45 -08:00
Feodor Fitsner a090ff82dc
Changes to 0.26.0 (#36)
* serious_python 0.8.4

* flet: 0.25.2

* file_picker: ^8.1.5

* file_picker: 8.1.4

* file_picker: 8.1.5

* file_picker: 8.1.4

* Remove file_picker override

* serious_python 0.8.4

* initialize_ctypes and serious_python 0.8.7 (#34)

* serious_python: 0.8.6

* Added initialize_ctypes override

* serious_python: 0.8.7

* Use Flet package from Git/flutter-extensions

* feodor/flutter-extensions

* Remove NDK, update minSdkVersion

* wakelock_plus: ^1.2.10

* Update gradle.properties

* Changes to 0.26.0-dev (#35)

* Added support for developer mode

* Do not run runPythonApp() in developer mode

* Import crtfifi in try..catch

* Flet ref changed to `main`
2025-01-16 10:01:13 -08:00
Feodor Fitsner d4bb8781d9
serious_python 0.8.3 (#33) 2024-12-04 12:41:42 -08:00
Feodor Fitsner 810cedd458 Merge branch '0.25.0' of https://github.com/flet-dev/flet-build-template into 0.25.0 2024-11-29 16:40:36 -08:00
Feodor Fitsner 7f2e57aa9a flet: 0.25.1 2024-11-29 16:40:35 -08:00
Feodor Fitsner 0d7f36b47c
Fix app close for macOS in 0.25.0 (#31)
* Deep linking settings

* Update web template

* Fix template

* Fix web template again

* Bump dev_dependencies

* Add flutter_bootstrap.js

* Use project_name_slug variable

* web mobile-web-app-capable

* externalNativeBuild

* Remove externalNativeBuild

* serious_python: 0.8.2

* Added sys.argv support

* Pass argv

* pwa_background_color and pwa_theme_color options

* Fix pwa_background_color in template

* Fix pwa_background_color again

* Set default pwa_background_color

* pwa white background

* Use pid for sockets

* Move setupDesktop()

* Update MainFlutterWindow.swift

* Rewrite setupDesktop

* Use windowManager.setSkipTaskbar

* Hide Linux window

* Prevent quit on close

* FLET_HIDE_APP_ON_START

* Default adaptive_icon_background, adaptive_icon_foreground

* FLET_APP_CONSOLE variable

* Add support for android meta-data

* Fix backslash in outLogFilename

* Fix rive_common build on Linux

* Enable logging

* Update AppDelegate.swift

* Enable --debug
2024-11-29 14:31:33 -08:00
Feodor Fitsner 8bcd4e1ee7 Flet 0.25.0 2024-11-28 16:38:22 -08:00
Feodor Fitsner cc5df08f38 Rename FLET_APP_DATA to FLET_APP_STORAGE_DATA 2024-11-26 09:52:37 -08:00
Feodor Fitsner a6f8ef257e
Rive and main.dart fixes for 0.25.0 (#29) 2024-11-25 09:19:39 -08:00
Feodor Fitsner 222dc57a6f
Fix Windows builds for 0.25.0 (#26) 2024-11-08 17:01:10 -08:00
Feodor Fitsner fecd2df8c2
Changes to 0.25.0 (#25)
* Deep linking settings

* Update web template

* Fix template

* Fix web template again

* Bump dev_dependencies

* Add flutter_bootstrap.js

* Use project_name_slug variable

* web mobile-web-app-capable

* externalNativeBuild

* Remove externalNativeBuild

* serious_python: 0.8.2

* Added sys.argv support

* Pass argv

* pwa_background_color and pwa_theme_color options

* Fix pwa_background_color in template

* Fix pwa_background_color again

* Set default pwa_background_color

* pwa white background

* Use pid for sockets

* Move setupDesktop()

* Update MainFlutterWindow.swift

* Rewrite setupDesktop

* Use windowManager.setSkipTaskbar

* Hide Linux window

* Prevent quit on close

* FLET_HIDE_APP_ON_START

* Default adaptive_icon_background, adaptive_icon_foreground

* FLET_APP_CONSOLE variable

* Add support for android meta-data
2024-11-08 09:14:48 -08:00
Feodor Fitsner 893e7d9fd5
Desktop fixes for 0.25.0 (#24)
* Deep linking settings

* Update web template

* Fix template

* Fix web template again

* Bump dev_dependencies

* Add flutter_bootstrap.js

* Use project_name_slug variable

* web mobile-web-app-capable

* externalNativeBuild

* Remove externalNativeBuild

* serious_python: 0.8.2

* Added sys.argv support

* Pass argv

* pwa_background_color and pwa_theme_color options

* Fix pwa_background_color in template

* Fix pwa_background_color again

* Set default pwa_background_color

* pwa white background

* Use pid for sockets

* Move setupDesktop()

* Update MainFlutterWindow.swift

* Rewrite setupDesktop

* Use windowManager.setSkipTaskbar

* Hide Linux window

* Prevent quit on close

* FLET_HIDE_APP_ON_START
2024-11-05 11:29:21 -08:00
Feodor Fitsner 287ee5350f
Changes for 0.25.0 (#23)
* Deep linking settings

* Update web template

* Fix template

* Fix web template again

* Bump dev_dependencies

* Add flutter_bootstrap.js

* Use project_name_slug variable

* web mobile-web-app-capable

* externalNativeBuild

* Remove externalNativeBuild

* serious_python: 0.8.2

* Added sys.argv support

* Pass argv

* pwa_background_color and pwa_theme_color options

* Fix pwa_background_color in template

* Fix pwa_background_color again

* Set default pwa_background_color

* pwa white background
2024-11-05 09:40:08 -08:00
Feodor Fitsner 1a557571ff Set CRYPTOGRAPHY_OPENSSL_NO_LEGACY 2024-10-23 14:09:14 -07:00
Feodor Fitsner 879bc4e2cd
web template updated, `project_name_slug` introduced (#21)
* Deep linking settings

* Update web template

* Fix template

* Fix web template again

* Bump dev_dependencies

* Add flutter_bootstrap.js

* Use project_name_slug variable

* web mobile-web-app-capable
2024-10-15 18:51:15 -07:00
Feodor Fitsner 38c001dd2e serious_python: 0.8.1 2024-10-15 12:49:09 -07:00
Feodor Fitsner 8cf6a6a777 IPHONEOS_DEPLOYMENT_TARGET = 13.0 2024-10-15 09:43:48 -07:00
Feodor Fitsner 2c08be510e Bump iOS to 13.0 2024-10-15 09:37:34 -07:00
Feodor Fitsner 5b00ffb439
For Flet 0.25.0 (#20)
* path to serious_python

* full path to serious_python

* doNotStrip

* change abi filters order

* change order again

* split_per_abi

* make an error in template

* Fix template

* Test info_plist

* info plist complete

* Fix elif

* Another fix

* Another try

* simplify if

* simple test

* no v

* remove everything

* remove other options

* restore infoplist

* equal not is

* one line

* add macos_entitlements

* empty list

* empty array

* macos entitlements

* No hard-coded entitlements

* Android manifest

* Fix manifest

* Fix template again

* Remove hard-coded permissions

* Fix template

* true and false

* remove hard-coded permissions

* Android deep linking

Close #4025

* Template cleanup

* Signing Android builds

* Fix signing options

* Set FLET_APP_DATA and FLET_APP_TEMP dirs for the app

* Pyodide 0.26.2

* serious_python: 0.8.0
2024-10-09 12:18:32 -07:00
Feodor Fitsner 4d4420a369 Pin serious_python and flet packages to 0.7.1 and 0.24.1 2024-10-04 17:32:54 -07:00
Feodor Fitsner a334ffce32 Use Flet 0.24.0 2024-08-31 13:06:35 -07:00
syle 2ef869dcb6
geolocator foreground/background service additions (#19) 2024-08-28 19:16:45 -07:00
syle 751dd24874
Adding Google TV support (#16) 2024-08-06 08:48:19 -07:00
Feodor Fitsner 34c35a5b01 "web" package override 2024-08-05 10:41:14 -07:00
Feodor Fitsner a471e02725 Remove doNotStrip 2024-07-24 20:59:30 +02:00
Feodor Fitsner f8d79be167 Fix packagingOptions. doNotStrip 2024-07-24 20:59:30 +02:00
Feodor Fitsner c3415d600e Disable LLVM stripping of libpythonbundle.so 2024-07-24 20:59:29 +02:00
Feodor Fitsner dd93c8ae6d Disable impeller 2024-07-24 20:59:29 +02:00
Feodor Fitsner b63cdfe089 Remove torch_light override
It should be fixed with torch_light 1.1.0
2024-07-24 20:59:28 +02:00
TheEthicalBoy 73cae4ec99 MacOS: Add more permissions to `DebugProfile.entitlements` 2024-07-24 20:59:28 +02:00
TheEthicalBoy ceaf31531e MacOS: Add more permissions to `Release.entitlements` 2024-07-24 20:59:27 +02:00
TheEthicalBoy fc515f77c5 Add location permission to `Info.plist` 2024-07-24 20:59:27 +02:00
TheEthicalBoy dc8a457647 Add location permissions to `Info.plist` 2024-07-24 20:59:26 +02:00
TheEthicalBoy b5b455d0de Add more Permissions to `AndroidManifest.xml` 2024-07-24 20:59:26 +02:00
Feodor Fitsner 3d0975eb2b Use Flet 0.23.2 2024-07-24 20:59:26 +02:00
Feodor Fitsner c467094581 Squashed commit of the following:
commit 0ab693b566
Author: Feodor Fitsner <feodor@appveyor.com>
Date:   Mon Jun 24 16:15:52 2024 -0700

    Add x86_64 arch
2024-06-24 19:46:52 -07:00
Feodor Fitsner b1c6b15da5
Flet 0.23.1 - disable Impeller, enable legacy packaging, serious_python 0.7.1 (#14)
* serious_python 0.7.1

* useLegacyPackaging true

* Disable impeller

* Remove Flutter test
2024-06-21 13:07:25 -07:00
Feodor Fitsner 652bbfa243
Kotlin 1.9.0, Geolocator bump (#13)
* geolocator: ^12.0.0

* geolocator_android: ^4.6.0

* Kotlin 1.9.0

* Kotlin 1.9.24

* AGP 8.5.0

* Rollback AGP 8.3.1

* torch_light from github

* Add pubspec.lock

* Updated pubspec.lock

* conditional dependencies

* Fix ifs
2024-06-19 22:37:08 -07:00
Feodor Fitsner 6067841b81
Merge pull request #12 from flet-dev/0.23.1-kotlin-1.8
Update Kotlin and NDK for 0.23.1
2024-06-19 17:00:34 -07:00
Feodor Fitsner 24d1a7056e flet: ^0.23.1 2024-06-19 16:54:24 -07:00
Feodor Fitsner a58c6ffa92 ndkVersion "25.1.8937393" 2024-06-19 16:38:03 -07:00
Feodor Fitsner 0ca26dd6b5 ndkVersion "26.3.11579264" 2024-06-19 16:27:40 -07:00
Feodor Fitsner 9c399dfaae Override serious_python_platform_interface 2024-06-19 16:04:30 -07:00
Feodor Fitsner f42393a5ae override serious_python_android only 2024-06-19 16:03:08 -07:00
Feodor Fitsner 6377f131b8 Fix path 2024-06-19 16:01:39 -07:00
Feodor Fitsner 5b39497d20 Use serious_python from github 2024-06-19 16:00:16 -07:00
Feodor Fitsner e7ecd3baff Bump gradle 8.3.1 2024-06-19 15:50:46 -07:00
Feodor Fitsner 6da7a3ae8f record: ^5.1.1 2024-06-19 15:47:48 -07:00
Feodor Fitsner 2eb1727362 Rollback Kotlin version 2024-06-19 15:45:08 -07:00
Feodor Fitsner e7a3ede0ee gradle:8.4.1 2024-06-19 14:54:51 -07:00
Feodor Fitsner 516518871e Kotlin 1.8.21 2024-06-19 14:46:32 -07:00
Feodor Fitsner 6e2e7eebc8 Flet 0.23.0 2024-06-19 14:39:58 -07:00
Feodor Fitsner 1f4cb54e9a Fix crash on Linux 2024-06-19 12:35:26 -07:00
Feodor Fitsner 0178bd5f23 Bump Flet 0.23.1 2024-06-19 11:04:46 -07:00
Feodor Fitsner 0eac4d4c5b
Merge pull request #11 from flet-dev/0.23.0-fix1
Fix dependencies
2024-06-19 10:07:55 -07:00
Feodor Fitsner 4447012691 Override wakelock_plus and package_info_plus deps 2024-06-19 10:04:03 -07:00
Feodor Fitsner 3c41d5cb1c kotlin_version = '1.7.22' 2024-06-19 09:48:44 -07:00
Feodor Fitsner 03d7a63609 Flet 0.23 2024-06-19 09:44:43 -07:00
Feodor Fitsner f1c45f90b4
Merge pull request #10 from flet-dev/impeller
Enable impeller on macOS and Android
2024-06-14 10:18:50 -07:00
TheEthicalBoy 1d28e0fbdb
Merge branch '0.22.1' into impeller 2024-06-14 12:18:14 +02:00
ndonkoHenri b69b87efb3 enable impeller 2024-06-14 12:14:14 +02:00
Feodor Fitsner 1cc0c49f29 minSdkVersion 23 for Android app 2024-06-13 11:52:50 -07:00
Feodor Fitsner 326209fdbf Use Flet 0.22.1 2024-04-30 12:05:58 -07:00
Feodor Fitsner a88b3b8e48 Squashed commit of the following:
commit cb9af5b9a64396835120754eb085a62fcc0b558b
Author: Feodor Fitsner <feodor@appveyor.com>
Date:   Mon Apr 29 11:32:15 2024 -0700

    Add NSMicrophoneUsageDescription to Info.plist
2024-04-29 11:36:46 -07:00
Feodor Fitsner 14a925be08 Fix for apps with numpy on macOS
https://github.com/flet-dev/serious-python/issues/85#issuecomment-2065000974
2024-04-18 12:17:32 -07:00
Feodor Fitsner 9496a9b3de Use Flet 0.22.0 2024-04-12 10:13:59 -07:00
Feodor Fitsner 7bc5081b00 Squashed commit of the following:
commit e8217a057a
Author: Feodor Fitsner <feodor@appveyor.com>
Date:   Mon Mar 11 11:11:48 2024 -0700

    Squashed commit of the following:

    commit 7660adc12c
    Author: Feodor Fitsner <feodor@appveyor.com>
    Date:   Mon Mar 11 11:11:30 2024 -0700

        minSdkVersion 21
2024-03-11 11:12:05 -07:00
Feodor Fitsner e2ab18efdd Use Flet 0.21.2 2024-03-07 08:57:54 -08:00
Feodor Fitsner 0b83309df0 Use Flet 0.21.1 2024-03-06 13:24:17 -08:00
Feodor Fitsner 27a2ec266e Use Flet 0.21.0 2024-03-06 11:04:10 -08:00
Feodor Fitsner 4ffc1adf42 android:label="{{ cookiecutter.product_name }}" 2024-02-20 14:12:50 -08:00
Feodor Fitsner 52d86b3bd3 flet: ^0.20.2 2024-02-17 14:47:05 -08:00
Feodor Fitsner 50c7144fca cupertino_icons: ^1.0.6 2024-02-17 09:47:56 -08:00
Feodor Fitsner 26b3c9a244
Merge pull request #7 from flet-dev/0.20.0-fix1
0.20.1 fixes
2024-02-16 17:39:15 -08:00
Feodor Fitsner d96ce5a571 Use Flet 0.20.1 2024-02-16 17:38:57 -08:00
Feodor Fitsner d48614191d Fix settings.gradle 2024-02-16 12:19:14 -08:00
Feodor Fitsner 5e1d40c94c Remove minSdkVersion 21 2024-02-16 12:16:41 -08:00
Feodor Fitsner a233de7547 Fix type of `createControlFactories` 2024-02-15 10:59:07 -08:00
Feodor Fitsner c25fa1db79 Fix `createControlFactories` 2024-02-14 18:51:11 -08:00
Feodor Fitsner b6b6f3426f
Merge pull request #6 from flet-dev/0.20.0-dev
Flet 0.20.0
2024-02-14 18:07:12 -08:00
Feodor Fitsner bd9285b831 Use Flet 0.20.0 2024-02-14 18:06:36 -08:00
Feodor Fitsner 6c78ea8471 Move ensureInitialized 2024-02-09 12:53:58 -08:00
Feodor Fitsner 2546c20766 {{ dep }}.ensureInitialized() 2024-02-09 12:47:09 -08:00
Feodor Fitsner 5a1fc38804 Pyodide v0.25.0 2024-02-04 09:44:50 -08:00
Feodor Fitsner 52ebf16507 var createControlFactories 2024-01-23 11:19:11 -08:00
Feodor Fitsner 4fa29e6f5d flutter_dependencies didn't work 2024-01-23 10:59:23 -08:00
Feodor Fitsner aadcfb3baa Back flutter_dependencies 2024-01-23 10:57:49 -08:00
Feodor Fitsner 31dca2b5e5 "flutter": null 2024-01-23 10:54:27 -08:00
Feodor Fitsner 417ae1c0c7 Remove from cookiecutter.json 2024-01-23 10:52:58 -08:00
Feodor Fitsner 3d3a54c486 Fix cookiecutter.flutter.dependencies 2024-01-23 10:51:54 -08:00
Feodor Fitsner 438daea208 Add flutter_dependencies 2024-01-23 10:47:34 -08:00
37 changed files with 728 additions and 335 deletions

View File

@ -2,17 +2,30 @@
"out_dir": "", "out_dir": "",
"python_module_name": "main", "python_module_name": "main",
"project_name": "", "project_name": "",
"project_name_slug": "",
"project_description": "", "project_description": "",
"product_name": "{{ cookiecutter.project_name }}", "product_name": "{{ cookiecutter.project_name }}",
"org_name": "com.flet", "org_name": "{{ cookiecutter.org_name if 'org_name' in cookiecutter else 'com.flet' }}",
"company_name": "Your Company", "company_name": "Your Company",
"copyright": "Copyright (c) 2023 Your Company", "copyright": "Copyright (c) 2023 Your Company",
"flutter": null,
"sep": "/", "sep": "/",
"kotlin_dir": "{{ cookiecutter.org_name.replace('.', cookiecutter.sep) }}{{ cookiecutter.sep }}{{ cookiecutter.project_name }}{{ cookiecutter.sep }}",
"hide_loading_animation": true, "hide_loading_animation": true,
"team_id": "", "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": "",
"ios_export_method": "",
"ios_signing_certificate": "",
"ios_export_options": {},
"ios_team_id": "",
"package_name": "{{ cookiecutter.bundle_id.rsplit('.', 1)[-1].replace('-', '_') if 'bundle_id' in cookiecutter else cookiecutter.project_name }}",
"kotlin_dir": "{{ cookiecutter.org_name_2.replace('.', cookiecutter.sep) }}{{ cookiecutter.sep }}{{ cookiecutter.package_name }}{{ cookiecutter.sep }}",
"base_url": "/", "base_url": "/",
"route_url_strategy": "path", "route_url_strategy": "path",
"web_renderer": "canvaskit", "web_renderer": "canvaskit",
"use_color_emoji": "false" "use_color_emoji": "false",
"pwa_background_color": "#FFFFFF",
"pwa_theme_color": "#0175C2",
"split_per_abi": false,
"options": null
} }

View File

@ -0,0 +1,3 @@
{% for key, value in cookiecutter.items() -%}
{{ key }}: {{ value }}
{% endfor %}

View File

@ -23,9 +23,18 @@ if (flutterVersionName == null) {
} }
android { android {
namespace "{{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}" namespace "{{ cookiecutter.org_name_2 }}.{{ cookiecutter.package_name }}"
compileSdkVersion flutter.compileSdkVersion compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
packagingOptions {
jniLibs {
useLegacyPackaging true
}
doNotStrip "*/arm64-v8a/libpython*.so"
doNotStrip "*/armeabi-v7a/libpython*.so"
doNotStrip "*/x86/libpython*.so"
doNotStrip "*/x86_64/libpython*.so"
}
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
@ -41,25 +50,37 @@ android {
} }
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "{{ cookiecutter.org_name_2 }}.{{ cookiecutter.package_name }}"
applicationId "{{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion flutter.minSdkVersion minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
// flet: split_per_abi {% if not cookiecutter.split_per_abi %}
ndk { ndk {
abiFilters 'arm64-v8a', 'armeabi-v7a' abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86_64'
}
// flet: end of split_per_abi {% endif %}
}
// flet: android_signing {% if cookiecutter.options.android_signing %}
signingConfigs {
release {
keyAlias System.getenv('FLET_ANDROID_SIGNING_KEY_ALIAS')
keyPassword System.getenv('FLET_ANDROID_SIGNING_KEY_PASSWORD')
storeFile System.getenv('FLET_ANDROID_SIGNING_KEY_STORE') ? file(System.getenv('FLET_ANDROID_SIGNING_KEY_STORE')) : null
storePassword System.getenv('FLET_ANDROID_SIGNING_KEY_STORE_PASSWORD')
} }
} }
// flet: end of android_signing {% endif %}
buildTypes { buildTypes {
release { release {
// TODO: Add your own signing config for the release build. // flet: android_signing {% if cookiecutter.options.android_signing %}
// Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.release
// {% else %}
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
// flet: end of android_signing {% endif %}
} }
} }
} }

View File

@ -0,0 +1,2 @@
-keep class com.flet.serious_python_android.** { *; }
-keepnames class * { *; }

View File

@ -3,5 +3,6 @@
the Flutter tool needs it to communicate with the running application the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.
--> -->
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest> </manifest>

View File

@ -1,9 +1,20 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/> <!-- flet: permission {% for k, v in cookiecutter.options.android_permissions.items() %} {% if v == True %} -->
<uses-permission android:name="{{ k }}" />
<!-- flet: enf of permission {% endif %} {% endfor %} -->
<!-- flet: feature {% for k, v in cookiecutter.options.android_features.items() %} -->
<uses-feature android:name="{{ k }}" android:required="{% if v == True %}true{% else %}false{% endif %}" />
<!-- flet: end of feature {% endfor %} -->
<application <application
android:label="{{ cookiecutter.project_name }}" android:label="{{ cookiecutter.product_name }}"
android:name="${applicationName}" android:name="${applicationName}"
android:enableOnBackInvokedCallback="true"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<!-- flet: meta-data {% for k, v in cookiecutter.options.android_meta_data.items() %} -->
<meta-data android:name="{{ k }}" android:value="{{ v }}" />
<!-- flet: end of meta-data {% endfor %} -->
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"
@ -21,9 +32,20 @@
android:resource="@style/NormalTheme" android:resource="@style/NormalTheme"
/> />
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" /> <!-- Google TV -->
</intent-filter> </intent-filter>
<!-- flet: deep linking {% if cookiecutter.options.deep_linking.scheme and cookiecutter.options.deep_linking.host %} -->
<meta-data android:name="flutter_deeplinking_enabled" android:value="true" />
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="{{ cookiecutter.options.deep_linking.scheme }}"
android:host="{{ cookiecutter.options.deep_linking.host }}" />
</intent-filter>
<!-- flet: end of deep linking {% endif %} -->
</activity> </activity>
<!-- Don't delete the meta-data below. <!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->

View File

@ -1,4 +1,4 @@
package {{ cookiecutter.org_name }}.{{ cookiecutter.project_name }} package {{ cookiecutter.org_name_2 }}.{{ cookiecutter.package_name }}
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity

View File

@ -3,5 +3,6 @@
the Flutter tool needs it to communicate with the running application the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.
--> -->
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest> </manifest>

View File

@ -1,12 +1,11 @@
buildscript { buildscript {
ext.kotlin_version = '1.7.10' ext.kotlin_version = '1.9.24'
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.4.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }

View File

@ -1,3 +1,3 @@
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true

View File

@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip

View File

@ -10,11 +10,20 @@ pluginManagement {
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
plugins { plugins {
id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
} }
} }
include ":app" plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.3.1" apply false
}
apply from: "${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle/app_plugin_loader.gradle" include ":app"

View File

@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project # Uncomment this line to define a global platform for your project
platform :ios, '12.0' platform :ios, '13.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency. # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true' ENV['COCOAPODS_DISABLE_STATS'] = 'true'

View File

@ -345,7 +345,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -360,9 +360,16 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
{% if cookiecutter.team_id %} {% if cookiecutter.ios_team_id %}
DEVELOPMENT_TEAM = {{ cookiecutter.team_id }}; DEVELOPMENT_TEAM = "{{ cookiecutter.ios_team_id }}";
{% endif %}
{% if cookiecutter.ios_signing_certificate %}
CODE_SIGN_IDENTITY = "{{ cookiecutter.ios_signing_certificate }}";
{% endif %}
{% if cookiecutter.ios_provisioning_profile %}
PROVISIONING_PROFILE_SPECIFIER = "{{ cookiecutter.ios_provisioning_profile }}";
{% endif %} {% endif %}
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@ -370,7 +377,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }};
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@ -387,7 +394,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -405,7 +412,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@ -421,7 +428,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@ -475,7 +482,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -524,7 +531,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -541,9 +548,16 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
{% if cookiecutter.team_id %} {% if cookiecutter.ios_team_id %}
DEVELOPMENT_TEAM = {{ cookiecutter.team_id }}; DEVELOPMENT_TEAM = "{{ cookiecutter.ios_team_id }}";
{% endif %}
{% if cookiecutter.ios_signing_certificate %}
CODE_SIGN_IDENTITY = "{{ cookiecutter.ios_signing_certificate }}";
{% endif %}
{% if cookiecutter.ios_provisioning_profile %}
PROVISIONING_PROFILE_SPECIFIER = "{{ cookiecutter.ios_provisioning_profile }}";
{% endif %} {% endif %}
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@ -551,7 +565,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }};
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -566,9 +580,16 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
{% if cookiecutter.team_id %} {% if cookiecutter.ios_team_id %}
DEVELOPMENT_TEAM = {{ cookiecutter.team_id }}; DEVELOPMENT_TEAM = "{{ cookiecutter.ios_team_id }}";
{% endif %}
{% if cookiecutter.ios_signing_certificate %}
CODE_SIGN_IDENTITY = "{{ cookiecutter.ios_signing_certificate }}";
{% endif %}
{% if cookiecutter.ios_provisioning_profile %}
PROVISIONING_PROFILE_SPECIFIER = "{{ cookiecutter.ios_provisioning_profile }}";
{% endif %} {% endif %}
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@ -576,7 +597,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }};
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;

View File

@ -1,7 +1,7 @@
import UIKit import UIKit
import Flutter import Flutter
@UIApplicationMain @main
@objc class AppDelegate: FlutterAppDelegate { @objc class AppDelegate: FlutterAppDelegate {
override func application( override func application(
_ application: UIApplication, _ application: UIApplication,

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
@ -23,7 +23,7 @@
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string> <string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true />
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIMainStoryboardFile</key> <key>UIMainStoryboardFile</key>
@ -42,8 +42,60 @@
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>CADisableMinimumFrameDurationOnPhone</key> <key>CADisableMinimumFrameDurationOnPhone</key>
<true/> <true />
<key>UIApplicationSupportsIndirectInputEvents</key> <key>UIApplicationSupportsIndirectInputEvents</key>
<true/> <true />
</dict> <key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true />
</dict>
<!-- flet: deep linking {% if cookiecutter.options.deep_linking.scheme and cookiecutter.options.deep_linking.host%} -->
<key>FlutterDeepLinkingEnabled</key>
<true />
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>{{ cookiecutter.options.deep_linking.host }}</string>
<key>CFBundleURLSchemes</key>
<array>
<string>{{ cookiecutter.options.deep_linking.scheme }}</string>
</array>
</dict>
</array>
<!-- flet: end of deep linking {% endif %} -->
{% macro render_dict(d) -%}
{% for key, value in d.items() -%}
<key>{{ key }}</key>
{% if value is string -%}
<string>{{ value }}</string>
{% elif value is boolean -%}
<{{ "true" if value else "false" }}/>
{% elif value is mapping -%}
<dict>
{{ render_dict(value) }}
</dict>
{% elif value is sequence -%} {# Support for lists/arrays #}
<array>
{% for item in value -%}
{% if item is string -%}
<string>{{ item }}</string>
{% elif item is boolean -%}
<{{ "true" if item else "false" }}/>
{% elif item is mapping -%}
<dict>
{{ render_dict(item) }}
</dict>
{% endif -%}
{% endfor -%}
</array>
{% endif -%}
{% endfor -%}
{% endmacro -%}
{{ render_dict(cookiecutter.options.info_plist) }}
</dict>
</plist> </plist>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>{{ cookiecutter.ios_export_method }}</string>
<key>provisioningProfiles</key>
<dict>
<key>{{ cookiecutter.bundle_id }}</key>
<string>{{ cookiecutter.ios_provisioning_profile }}</string>
</dict>
{% if cookiecutter.ios_team_id %}
<key>teamID</key>
<string>{{ cookiecutter.ios_team_id }}</string>
{% endif %}
{% if cookiecutter.ios_signing_certificate %}
<key>signingCertificate</key>
<string>{{ cookiecutter.ios_signing_certificate }}</string>
{% endif %}
{% macro render_dict(d) -%}
{% for key, value in d.items() -%}
<key>{{ key }}</key>
{% if value is string -%}
<string>{{ value }}</string>
{% elif value is boolean -%}
<{{ "true" if value else "false" }}/>
{% elif value is mapping -%}
<dict>
{{ render_dict(value) }}
</dict>
{% elif value is sequence -%} {# Support for lists/arrays #}
<array>
{% for item in value -%}
{% if item is string -%}
<string>{{ item }}</string>
{% elif item is boolean -%}
<{{ "true" if item else "false" }}/>
{% elif item is mapping -%}
<dict>
{{ render_dict(item) }}
</dict>
{% endif -%}
{% endfor -%}
</array>
{% endif -%}
{% endfor -%}
{% endmacro -%}
{{ render_dict(cookiecutter.ios_export_options) }}
</dict>
</plist>

View File

@ -5,9 +5,18 @@ import 'package:flet/flet.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart' as path_provider;
import 'package:serious_python/serious_python.dart'; import 'package:serious_python/serious_python.dart';
import 'package:url_strategy/url_strategy.dart'; import 'package:url_strategy/url_strategy.dart';
import 'package:window_manager/window_manager.dart';
import "python.dart";
{% for dep in cookiecutter.flutter.dependencies %}
import 'package:{{ dep }}/{{ dep }}.dart' as {{ dep }};
{% endfor %}
const bool isProduction = bool.fromEnvironment('dart.vm.product'); const bool isProduction = bool.fromEnvironment('dart.vm.product');
@ -16,82 +25,38 @@ const pythonModuleName = "{{ cookiecutter.python_module_name }}";
final hideLoadingPage = final hideLoadingPage =
bool.tryParse("{{ cookiecutter.hide_loading_animation }}".toLowerCase()) ?? bool.tryParse("{{ cookiecutter.hide_loading_animation }}".toLowerCase()) ??
true; true;
const outLogFilename = "out.log";
const errorExitCode = 100;
const pythonScript = """ List<CreateControlFactory> createControlFactories = [
import certifi, os, runpy, socket, sys, traceback {% for dep in cookiecutter.flutter.dependencies %}
{{ dep }}.createControl,
{% endfor %}
];
os.environ["REQUESTS_CA_BUNDLE"] = certifi.where() String outLogFilename = "";
os.environ["SSL_CERT_FILE"] = certifi.where()
if os.getenv("FLET_PLATFORM") == "android":
import ssl
def create_default_context(
purpose=ssl.Purpose.SERVER_AUTH, *, cafile=None, capath=None, cadata=None
):
return ssl.create_default_context(
purpose=purpose, cafile=certifi.where(), capath=capath, cadata=cadata
)
ssl._create_default_https_context = create_default_context
out_file = open("$outLogFilename", "w+", buffering=1)
callback_socket_addr = os.environ.get("FLET_PYTHON_CALLBACK_SOCKET_ADDR")
if ":" in callback_socket_addr:
addr, port = callback_socket_addr.split(":")
callback_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
callback_socket.connect((addr, int(port)))
else:
callback_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
callback_socket.connect(callback_socket_addr)
sys.stdout = sys.stderr = out_file
def flet_exit(code=0):
callback_socket.sendall(str(code).encode())
out_file.close()
callback_socket.close()
sys.exit = flet_exit
ex = None
try:
runpy.run_module("{module_name}", run_name="__main__")
except Exception as e:
ex = e
traceback.print_exception(e)
sys.exit(0 if ex is None else $errorExitCode)
""";
// global vars // global vars
List<String> _args = [];
String pageUrl = ""; String pageUrl = "";
String assetsDir = ""; String assetsDir = "";
String appDir = ""; String appDir = "";
Map<String, String> environmentVariables = {}; Map<String, String> environmentVariables = {};
void main() async { void main(List<String> args) async {
if (isProduction) { _args = List<String>.from(args);
// ignore: avoid_returning_null_for_void
debugPrint = (String? message, {int? wrapWidth}) => null;
}
runApp(FutureBuilder( runApp(FutureBuilder(
future: prepareApp(), future: prepareApp(),
builder: (BuildContext context, AsyncSnapshot snapshot) { builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
// OK - start Python program // OK - start Python program
return kIsWeb return kIsWeb || (isDesktopPlatform() && _args.isNotEmpty)
? FletApp( ? FletApp(
pageUrl: pageUrl, pageUrl: pageUrl,
assetsDir: assetsDir, assetsDir: assetsDir,
hideLoadingPage: hideLoadingPage, hideLoadingPage: hideLoadingPage,
) createControlFactories: createControlFactories)
: FutureBuilder( : FutureBuilder(
future: runPythonApp(), future: runPythonApp(args),
builder: builder:
(BuildContext context, AsyncSnapshot<String?> snapshot) { (BuildContext context, AsyncSnapshot<String?> snapshot) {
if (snapshot.hasData || snapshot.hasError) { if (snapshot.hasData || snapshot.hasError) {
@ -107,7 +72,7 @@ void main() async {
pageUrl: pageUrl, pageUrl: pageUrl,
assetsDir: assetsDir, assetsDir: assetsDir,
hideLoadingPage: hideLoadingPage, hideLoadingPage: hideLoadingPage,
); createControlFactories: createControlFactories);
} }
}); });
} else if (snapshot.hasError) { } else if (snapshot.hasError) {
@ -124,6 +89,19 @@ void main() async {
} }
Future prepareApp() async { Future prepareApp() async {
if (!_args.contains("--debug")) {
// ignore: avoid_returning_null_for_void
debugPrint = (String? message, {int? wrapWidth}) => null;
} else {
_args.remove("--debug");
}
await setupDesktop();
{% for dep in cookiecutter.flutter.dependencies %}
{{ dep }}.ensureInitialized();
{% endfor %}
if (kIsWeb) { if (kIsWeb) {
// web mode - connect via HTTP // web mode - connect via HTTP
pageUrl = Uri.base.toString(); pageUrl = Uri.base.toString();
@ -131,9 +109,22 @@ Future prepareApp() async {
if (routeUrlStrategy == "path") { if (routeUrlStrategy == "path") {
setPathUrlStrategy(); setPathUrlStrategy();
} }
} else if (_args.isNotEmpty && isDesktopPlatform()) {
// developer mode
debugPrint("Flet app is running in Developer mode");
pageUrl = _args[0];
if (_args.length > 1) {
var pidFilePath = _args[1];
debugPrint("Args contain a path to PID file: $pidFilePath}");
var pidFile = await File(pidFilePath).create();
await pidFile.writeAsString("$pid");
}
if (_args.length > 2) {
assetsDir = _args[2];
debugPrint("Args contain a path assets directory: $assetsDir}");
}
} else { } else {
await setupDesktop(); // production mode
// extract app from asset // extract app from asset
appDir = await extractAssetZip(assetPath, checkHash: true); appDir = await extractAssetZip(assetPath, checkHash: true);
@ -142,6 +133,29 @@ Future prepareApp() async {
assetsDir = path.join(appDir, "assets"); assetsDir = path.join(appDir, "assets");
// configure apps DATA and TEMP directories
WidgetsFlutterBinding.ensureInitialized();
var appTempPath = (await path_provider.getApplicationCacheDirectory()).path;
var appDataPath =
(await path_provider.getApplicationDocumentsDirectory()).path;
if (defaultTargetPlatform != TargetPlatform.iOS &&
defaultTargetPlatform != TargetPlatform.android) {
// append app name to the path and create dir
PackageInfo packageInfo = await PackageInfo.fromPlatform();
appDataPath = path.join(appDataPath, "flet", packageInfo.packageName);
if (!await Directory(appDataPath).exists()) {
await Directory(appDataPath).create(recursive: true);
}
}
environmentVariables["FLET_APP_STORAGE_DATA"] = appDataPath;
environmentVariables["FLET_APP_STORAGE_TEMP"] = appTempPath;
outLogFilename = path.join(appTempPath, "console.log");
environmentVariables["FLET_APP_CONSOLE"] = outLogFilename;
environmentVariables["FLET_PLATFORM"] = environmentVariables["FLET_PLATFORM"] =
defaultTargetPlatform.name.toLowerCase(); defaultTargetPlatform.name.toLowerCase();
@ -152,7 +166,7 @@ Future prepareApp() async {
environmentVariables["FLET_SERVER_PORT"] = tcpPort.toString(); environmentVariables["FLET_SERVER_PORT"] = tcpPort.toString();
} else { } else {
// use UDS on other platforms // use UDS on other platforms
pageUrl = "flet.sock"; pageUrl = "flet_$pid.sock";
environmentVariables["FLET_SERVER_UDS_PATH"] = pageUrl; environmentVariables["FLET_SERVER_UDS_PATH"] = pageUrl;
} }
} }
@ -160,8 +174,13 @@ Future prepareApp() async {
return ""; return "";
} }
Future<String?> runPythonApp() async { Future<String?> runPythonApp(List<String> args) async {
var script = pythonScript.replaceAll('{module_name}', pythonModuleName); var argvItems = args.map((a) => "\"${a.replaceAll('"', '\\"')}\"");
var argv = "[${argvItems.isNotEmpty ? argvItems.join(',') : '""'}]";
var script = pythonScript
.replaceAll("{outLogFilename}", outLogFilename.replaceAll("\\", "\\\\"))
.replaceAll('{module_name}', pythonModuleName)
.replaceAll('{argv}', argv);
var completer = Completer<String>(); var completer = Completer<String>();
@ -176,7 +195,7 @@ Future<String?> runPythonApp() async {
'Python output TCP Server is listening on port ${outSocketServer.port}'); 'Python output TCP Server is listening on port ${outSocketServer.port}');
socketAddr = "$tcpAddr:${outSocketServer.port}"; socketAddr = "$tcpAddr:${outSocketServer.port}";
} else { } else {
socketAddr = "stdout.sock"; socketAddr = "stdout_$pid.sock";
if (await File(socketAddr).exists()) { if (await File(socketAddr).exists()) {
await File(socketAddr).delete(); await File(socketAddr).delete();
} }
@ -295,3 +314,25 @@ Future<int> getUnusedPort() {
return port; return port;
}); });
} }
Future setupDesktop() async {
if (isDesktopPlatform()) {
WidgetsFlutterBinding.ensureInitialized();
await windowManager.ensureInitialized();
Map<String, String> env = Platform.environment;
var hideWindowOnStart = env["FLET_HIDE_WINDOW_ON_START"];
var hideAppOnStart = env["FLET_HIDE_APP_ON_START"];
debugPrint("hideWindowOnStart: $hideWindowOnStart");
debugPrint("hideAppOnStart: $hideAppOnStart");
await windowManager.waitUntilReadyToShow(null, () async {
if (hideWindowOnStart == null && hideAppOnStart == null) {
await windowManager.show();
await windowManager.focus();
} else if (hideAppOnStart != null) {
await windowManager.setSkipTaskbar(true);
}
});
}
}

View File

@ -0,0 +1,104 @@
const errorExitCode = 100;
const pythonScript = """
import os, runpy, socket, sys, traceback
# fix for cryptography package
os.environ["CRYPTOGRAPHY_OPENSSL_NO_LEGACY"] = "1"
# fix for: https://github.com/flet-dev/serious-python/issues/85#issuecomment-2065000974
os.environ["OPENBLAS_NUM_THREADS"] = "1"
def initialize_ctypes():
import ctypes.util
import os
import pathlib
import sys
android_native_lib_dir = os.getenv("ANDROID_NATIVE_LIBRARY_DIR")
def find_library_override_imp(name: str):
if name is None:
return None
if pathlib.Path(name).exists():
return name
if sys.platform == "ios":
for lf in [
f"Frameworks/{name}.framework/{name}",
f"Frameworks/lib{name}.framework/lib{name}",
]:
lib_path = pathlib.Path(sys.executable).parent.joinpath(lf)
if lib_path.exists():
return str(lib_path)
elif android_native_lib_dir:
for lf in [f"lib{name}.so", f"{name}.so", name]:
lib_path = pathlib.Path(android_native_lib_dir).joinpath(lf)
if lib_path.exists():
return str(lib_path)
return None
find_library_original = ctypes.util.find_library
def find_library_override(name):
return find_library_override_imp(name) or find_library_original(name)
ctypes.util.find_library = find_library_override
CDLL_init_original = ctypes.CDLL.__init__
def CDLL_init_override(self, name, *args, **kwargs):
CDLL_init_original(
self, find_library_override_imp(name) or name, *args, **kwargs
)
ctypes.CDLL.__init__ = CDLL_init_override
initialize_ctypes()
out_file = open("{outLogFilename}", "w+", buffering=1)
callback_socket_addr = os.getenv("FLET_PYTHON_CALLBACK_SOCKET_ADDR")
if ":" in callback_socket_addr:
addr, port = callback_socket_addr.split(":")
callback_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
callback_socket.connect((addr, int(port)))
else:
callback_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
callback_socket.connect(callback_socket_addr)
sys.stdout = sys.stderr = out_file
def flet_exit(code=0):
callback_socket.sendall(str(code).encode())
out_file.close()
callback_socket.close()
sys.exit = flet_exit
ex = None
try:
import certifi
os.environ["REQUESTS_CA_BUNDLE"] = certifi.where()
os.environ["SSL_CERT_FILE"] = certifi.where()
if os.getenv("FLET_PLATFORM") == "android":
import ssl
def create_default_context(
purpose=ssl.Purpose.SERVER_AUTH, *, cafile=None, capath=None, cadata=None
):
return ssl.create_default_context(
purpose=purpose, cafile=certifi.where(), capath=capath, cadata=cadata
)
ssl._create_default_https_context = create_default_context
sys.argv = {argv}
runpy.run_module("{module_name}", run_name="__main__")
except Exception as e:
ex = e
traceback.print_exception(e)
sys.exit(0 if ex is None else 100)
""";

View File

@ -7,7 +7,7 @@ project(runner LANGUAGES CXX)
set(BINARY_NAME "{{ cookiecutter.project_name }}") set(BINARY_NAME "{{ cookiecutter.project_name }}")
# The unique GTK application identifier for this application. See: # The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID # https://wiki.gnome.org/HowDoI/ChooseApplicationID
set(APPLICATION_ID "{{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}") set(APPLICATION_ID "{{ cookiecutter.bundle_id }}")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake. # versions of CMake.
@ -41,7 +41,7 @@ endif()
# of modifying this function. # of modifying this function.
function(APPLY_STANDARD_SETTINGS TARGET) function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_14) target_compile_features(${TARGET} PUBLIC cxx_std_14)
target_compile_options(${TARGET} PRIVATE -Wall -Werror) target_compile_options(${TARGET} PRIVATE -Wall -Werror -Wno-unused-variable -Wno-unused-function)
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>") target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>") target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
endfunction() endfunction()
@ -138,6 +138,12 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST})
endif() endif()
endforeach(plugin) endforeach(plugin)
# Copy the native assets provided by the build.dart from all packages.
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
# Fully re-copy the assets directory on each build to avoid having stale files # Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install. # from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets") set(FLUTTER_ASSET_DIR_NAME "flutter_assets")

View File

@ -6,20 +6,20 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <audioplayers_linux/audioplayers_linux_plugin.h> #include <record_linux/record_linux_plugin.h>
#include <screen_retriever/screen_retriever_plugin.h> #include <screen_retriever_linux/screen_retriever_linux_plugin.h>
#include <serious_python_linux/serious_python_linux_plugin.h> #include <serious_python_linux/serious_python_linux_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h> #include <url_launcher_linux/url_launcher_plugin.h>
#include <window_manager/window_manager_plugin.h> #include <window_manager/window_manager_plugin.h>
#include <window_to_front/window_to_front_plugin.h> #include <window_to_front/window_to_front_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) audioplayers_linux_registrar = g_autoptr(FlPluginRegistrar) record_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "AudioplayersLinuxPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "RecordLinuxPlugin");
audioplayers_linux_plugin_register_with_registrar(audioplayers_linux_registrar); record_linux_plugin_register_with_registrar(record_linux_registrar);
g_autoptr(FlPluginRegistrar) screen_retriever_registrar = g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin");
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar); screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar);
g_autoptr(FlPluginRegistrar) serious_python_linux_registrar = g_autoptr(FlPluginRegistrar) serious_python_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "SeriousPythonLinuxPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "SeriousPythonLinuxPlugin");
serious_python_linux_plugin_register_with_registrar(serious_python_linux_registrar); serious_python_linux_plugin_register_with_registrar(serious_python_linux_registrar);

View File

@ -3,8 +3,8 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
audioplayers_linux record_linux
screen_retriever screen_retriever_linux
serious_python_linux serious_python_linux
url_launcher_linux url_launcher_linux
window_manager window_manager

View File

@ -7,19 +7,17 @@
#include "flutter/generated_plugin_registrant.h" #include "flutter/generated_plugin_registrant.h"
struct _MyApplication struct _MyApplication {
{
GtkApplication parent_instance; GtkApplication parent_instance;
char **dart_entrypoint_arguments; char** dart_entrypoint_arguments;
}; };
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
// Implements GApplication::activate. // Implements GApplication::activate.
static void my_application_activate(GApplication *application) static void my_application_activate(GApplication* application) {
{ MyApplication* self = MY_APPLICATION(application);
MyApplication *self = MY_APPLICATION(application); GtkWindow* window =
GtkWindow *window =
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
// Use a header bar when running in GNOME as this is the common style used // Use a header bar when running in GNOME as this is the common style used
@ -31,36 +29,31 @@ static void my_application_activate(GApplication *application)
// if future cases occur). // if future cases occur).
gboolean use_header_bar = TRUE; gboolean use_header_bar = TRUE;
#ifdef GDK_WINDOWING_X11 #ifdef GDK_WINDOWING_X11
GdkScreen *screen = gtk_window_get_screen(window); GdkScreen* screen = gtk_window_get_screen(window);
if (GDK_IS_X11_SCREEN(screen)) if (GDK_IS_X11_SCREEN(screen)) {
{ const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
const gchar *wm_name = gdk_x11_screen_get_window_manager_name(screen); if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
if (g_strcmp0(wm_name, "GNOME Shell") != 0)
{
use_header_bar = FALSE; use_header_bar = FALSE;
} }
} }
#endif #endif
if (use_header_bar) if (use_header_bar) {
{ GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
gtk_widget_show(GTK_WIDGET(header_bar)); gtk_widget_show(GTK_WIDGET(header_bar));
gtk_header_bar_set_title(header_bar, "{{ cookiecutter.product_name }}"); gtk_header_bar_set_title(header_bar, "{{ cookiecutter.product_name }}");
gtk_header_bar_set_show_close_button(header_bar, TRUE); gtk_header_bar_set_show_close_button(header_bar, TRUE);
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
} } else {
else
{
gtk_window_set_title(window, "{{ cookiecutter.product_name }}"); gtk_window_set_title(window, "{{ cookiecutter.product_name }}");
} }
gtk_window_set_default_size(window, 1280, 720); gtk_window_set_default_size(window, 1280, 720);
gtk_widget_show(GTK_WIDGET(window)); gtk_widget_realize(GTK_WIDGET(window));
g_autoptr(FlDartProject) project = fl_dart_project_new(); g_autoptr(FlDartProject) project = fl_dart_project_new();
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
FlView *view = fl_view_new(project); FlView* view = fl_view_new(project);
gtk_widget_show(GTK_WIDGET(view)); gtk_widget_show(GTK_WIDGET(view));
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
@ -70,15 +63,13 @@ static void my_application_activate(GApplication *application)
} }
// Implements GApplication::local_command_line. // Implements GApplication::local_command_line.
static gboolean my_application_local_command_line(GApplication *application, gchar ***arguments, int *exit_status) static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
{ MyApplication* self = MY_APPLICATION(application);
MyApplication *self = MY_APPLICATION(application);
// Strip out the first argument as it is the binary name. // Strip out the first argument as it is the binary name.
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
g_autoptr(GError) error = nullptr; g_autoptr(GError) error = nullptr;
if (!g_application_register(application, nullptr, &error)) if (!g_application_register(application, nullptr, &error)) {
{
g_warning("Failed to register: %s", error->message); g_warning("Failed to register: %s", error->message);
*exit_status = 1; *exit_status = 1;
return TRUE; return TRUE;
@ -90,25 +81,42 @@ static gboolean my_application_local_command_line(GApplication *application, gch
return TRUE; return TRUE;
} }
// Implements GApplication::startup.
static void my_application_startup(GApplication* application) {
//MyApplication* self = MY_APPLICATION(object);
// Perform any actions required at application startup.
G_APPLICATION_CLASS(my_application_parent_class)->startup(application);
}
// Implements GApplication::shutdown.
static void my_application_shutdown(GApplication* application) {
//MyApplication* self = MY_APPLICATION(object);
// Perform any actions required at application shutdown.
G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application);
}
// Implements GObject::dispose. // Implements GObject::dispose.
static void my_application_dispose(GObject *object) static void my_application_dispose(GObject* object) {
{ MyApplication* self = MY_APPLICATION(object);
MyApplication *self = MY_APPLICATION(object);
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
G_OBJECT_CLASS(my_application_parent_class)->dispose(object); G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
} }
static void my_application_class_init(MyApplicationClass *klass) static void my_application_class_init(MyApplicationClass* klass) {
{
G_APPLICATION_CLASS(klass)->activate = my_application_activate; G_APPLICATION_CLASS(klass)->activate = my_application_activate;
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
G_APPLICATION_CLASS(klass)->startup = my_application_startup;
G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown;
G_OBJECT_CLASS(klass)->dispose = my_application_dispose; G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
} }
static void my_application_init(MyApplication *self) {} static void my_application_init(MyApplication* self) {}
MyApplication *my_application_new() MyApplication* my_application_new() {
{
return MY_APPLICATION(g_object_new(my_application_get_type(), return MY_APPLICATION(g_object_new(my_application_get_type(),
"application-id", APPLICATION_ID, "application-id", APPLICATION_ID,
"flags", G_APPLICATION_NON_UNIQUE, "flags", G_APPLICATION_NON_UNIQUE,

View File

@ -5,24 +5,26 @@
import FlutterMacOS import FlutterMacOS
import Foundation import Foundation
import audioplayers_darwin
import package_info_plus import package_info_plus
import path_provider_foundation import path_provider_foundation
import screen_retriever import record_darwin
import screen_retriever_macos
import serious_python_darwin import serious_python_darwin
import shared_preferences_foundation import shared_preferences_foundation
import url_launcher_macos import url_launcher_macos
import wakelock_plus
import window_manager import window_manager
import window_to_front import window_to_front
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin")) RecordPlugin.register(with: registry.registrar(forPlugin: "RecordPlugin"))
ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin"))
SeriousPythonPlugin.register(with: registry.registrar(forPlugin: "SeriousPythonPlugin")) SeriousPythonPlugin.register(with: registry.registrar(forPlugin: "SeriousPythonPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
WindowToFrontPlugin.register(with: registry.registrar(forPlugin: "WindowToFrontPlugin")) WindowToFrontPlugin.register(with: registry.registrar(forPlugin: "WindowToFrontPlugin"))
} }

View File

@ -384,7 +384,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{ cookiecutter.project_name }}.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/{{ cookiecutter.project_name }}"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{ cookiecutter.project_name }}.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/{{ cookiecutter.project_name }}";
@ -398,7 +398,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{ cookiecutter.project_name }}.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/{{ cookiecutter.project_name }}"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{ cookiecutter.project_name }}.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/{{ cookiecutter.project_name }}";
@ -412,7 +412,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{ cookiecutter.project_name }}.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/{{ cookiecutter.project_name }}"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{ cookiecutter.project_name }}.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/{{ cookiecutter.project_name }}";

View File

@ -8,7 +8,7 @@
PRODUCT_NAME = {{ cookiecutter.product_name }} PRODUCT_NAME = {{ cookiecutter.product_name }}
// The application's bundle identifier // The application's bundle identifier
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name }} PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}
// The copyright displayed in application information // The copyright displayed in application information
PRODUCT_COPYRIGHT = {{ cookiecutter.copyright }}. All rights reserved. PRODUCT_COPYRIGHT = {{ cookiecutter.copyright }}. All rights reserved.

View File

@ -1,12 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>com.apple.security.app-sandbox</key> <!-- flet: entitlement {% for k, v in cookiecutter.options.macos_entitlements.items() %} -->
<false/> <key>{{ k }}</key>
<key>com.apple.security.cs.allow-jit</key> <!-- flet: True {% if v == True %} -->
<true/> <true />
<key>com.apple.security.network.server</key> <!-- flet: False {% elif v == False %} -->
<true/> <false />
</dict> <!-- flet: end of entitlement {% endif %} {% endfor %} -->
</dict>
</plist> </plist>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
@ -28,5 +28,35 @@
<string>MainMenu</string> <string>MainMenu</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string>NSApplication</string> <string>NSApplication</string>
</dict>
{% macro render_dict(d) -%}
{% for key, value in d.items() -%}
<key>{{ key }}</key>
{% if value is string -%}
<string>{{ value }}</string>
{% elif value is boolean -%}
<{{ "true" if value else "false" }}/>
{% elif value is mapping -%}
<dict>
{{ render_dict(value) }}
</dict>
{% elif value is sequence -%} {# Support for lists/arrays #}
<array>
{% for item in value -%}
{% if item is string -%}
<string>{{ item }}</string>
{% elif item is boolean -%}
<{{ "true" if item else "false" }}/>
{% elif item is mapping -%}
<dict>
{{ render_dict(item) }}
</dict>
{% endif -%}
{% endfor -%}
</array>
{% endif -%}
{% endfor -%}
{% endmacro -%}
{{ render_dict(cookiecutter.options.info_plist) }}
</dict>
</plist> </plist>

View File

@ -1,5 +1,6 @@
import Cocoa import Cocoa
import FlutterMacOS import FlutterMacOS
import window_manager
class MainFlutterWindow: NSWindow { class MainFlutterWindow: NSWindow {
override func awakeFromNib() { override func awakeFromNib() {
@ -12,4 +13,9 @@ class MainFlutterWindow: NSWindow {
super.awakeFromNib() super.awakeFromNib()
} }
override public func order(_ place: NSWindow.OrderingMode, relativeTo otherWin: Int) {
super.order(place, relativeTo: otherWin)
hiddenWindowAtLaunch()
}
} }

View File

@ -1,8 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>com.apple.security.app-sandbox</key> <!-- flet: entitlement {% for k, v in cookiecutter.options.macos_entitlements.items() %} -->
<false/> <key>{{ k }}</key>
</dict> <!-- flet: True {% if v == True %} -->
<true />
<!-- flet: False {% elif v == False %} -->
<false />
<!-- flet: end of entitlement {% endif %} {% endfor %} -->
</dict>
</plist> </plist>

View File

@ -1,5 +1,5 @@
name: {{ cookiecutter.project_name.replace("-", "_") }} name: '{{ cookiecutter.project_name }}'
description: {{ cookiecutter.project_description }} description: '{{ cookiecutter.project_description }}'
publish_to: 'none' publish_to: 'none'
version: 1.0.0+1 version: 1.0.0+1
@ -11,30 +11,47 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
serious_python: ^0.7.0 serious_python: 0.9.0
# serious_python:
# git: path: ^1.9.0
# url: https://github.com/flet-dev/serious-python url_strategy: ^0.2.0
# path: src/serious_python cupertino_icons: ^1.0.6
# ref: 'd059aef' path_provider: ^2.1.4
package_info_plus: ^8.0.2
window_manager: ^0.4.3
dependency_overrides:
flet: 0.27.1
flet: ^0.19.0
# flet: # flet:
# git: # git:
# path: packages/flet
# ref: main
# url: https://github.com/flet-dev/flet.git # url: https://github.com/flet-dev/flet.git
# path: package
# ref: '37b9581'
path: ^1.8.3 # serious_python:
url_strategy: ^0.2.0 # git:
cupertino_icons: ^1.0.2 # url: https://github.com/flet-dev/serious-python.git
# ref: main
# path: src/serious_python
wakelock_plus: ^1.2.10
web: ^1.0.0
window_manager: ^0.4.3
webview_flutter_android: ^4.0.0
# {% if 'flet_audio_recorder' in cookiecutter.flutter.dependencies %}
record: ^5.1.1
# {% endif %}
# {% if 'flet_geolocator' in cookiecutter.flutter.dependencies %}
# geolocator: ^12.0.0
# geolocator_android: ^4.6.0
# {% endif %}
dev_dependencies: dev_dependencies:
flutter_test: flutter_launcher_icons: ^0.14.1
sdk: flutter flutter_native_splash: ^2.4.1
flutter_launcher_icons: "^0.13.1"
flutter_native_splash: ^2.3.6
flutter_lints: ^2.0.0 flutter_lints: ^2.0.0
flutter: flutter:
@ -51,6 +68,8 @@ flutter_launcher_icons:
android: true android: true
image_path_android: "images/icon.png" image_path_android: "images/icon.png"
adaptive_icon_background: '#ffffff'
adaptive_icon_foreground: images/icon.png
ios: true ios: true
image_path_ios: "images/icon.png" image_path_ios: "images/icon.png"

View File

@ -0,0 +1,12 @@
{{ '{{flutter_js}}' }}
{{ '{{flutter_build_config}}' }}
_flutter.loader.load({
serviceWorkerSettings: {
serviceWorkerVersion: {{ '{{flutter_service_worker_version}}' }},
},
onEntrypointLoaded: async function (engineInitializer) {
const appRunner = await engineInitializer.initializeEngine({useColorEmoji: useColorEmoji});
await appRunner.runApp();
}
});

View File

@ -2,27 +2,13 @@
<html> <html>
<head> <head>
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
For more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
This is a placeholder for base href that will be replaced by the value of
the `--base-href` argument provided to `flutter build`.
-->
<base href="{{ cookiecutter.base_url }}"> <base href="{{ cookiecutter.base_url }}">
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="{{ cookiecutter.project_description }}"> <meta name="description" content="{{ cookiecutter.project_description }}">
<!-- iOS meta tags & icons --> <!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="{{ cookiecutter.product_name }}"> <meta name="apple-mobile-web-app-title" content="{{ cookiecutter.product_name }}">
<link rel="apple-touch-icon" href="icons/Icon-192.png"> <link rel="apple-touch-icon" href="icons/Icon-192.png">
@ -44,34 +30,10 @@
</script> </script>
<script src="python.js"></script> <script src="python.js"></script>
<script>
// The value below is injected by flutter build, do not touch.
const serviceWorkerVersion = null;
</script>
<!-- This script adds the flutter initialization JS code -->
<script src="flutter.js" defer></script>
</head> </head>
<body> <body>
<script> <script src="flutter_bootstrap.js" async></script>
window.addEventListener('load', function (ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
},
onEntrypointLoaded: function (engineInitializer) {
engineInitializer.initializeEngine({
renderer: webRenderer,
useColorEmoji: useColorEmoji,
}).then(function (appRunner) {
appRunner.runApp();
});
}
});
});
</script>
</body> </body>
</html> </html>

View File

@ -3,8 +3,8 @@
"short_name": "{{ cookiecutter.project_name }}", "short_name": "{{ cookiecutter.project_name }}",
"start_url": ".", "start_url": ".",
"display": "standalone", "display": "standalone",
"background_color": "#0175C2", "background_color": "{{ cookiecutter.pwa_background_color }}",
"theme_color": "#0175C2", "theme_color": "{{ cookiecutter.pwa_theme_color }}",
"description": "{{ cookiecutter.project_description }}", "description": "{{ cookiecutter.project_description }}",
"orientation": "portrait-primary", "orientation": "portrait-primary",
"prefer_related_applications": false, "prefer_related_applications": false,

View File

@ -1,4 +1,4 @@
importScripts("https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js"); importScripts("https://cdn.jsdelivr.net/pyodide/v0.27.2/full/pyodide.js");
self.pythonModuleName = null; self.pythonModuleName = null;
self.initialized = false; self.initialized = false;

View File

@ -6,18 +6,18 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <audioplayers_windows/audioplayers_windows_plugin.h> #include <record_windows/record_windows_plugin_c_api.h>
#include <screen_retriever/screen_retriever_plugin.h> #include <screen_retriever_windows/screen_retriever_windows_plugin_c_api.h>
#include <serious_python_windows/serious_python_windows_plugin_c_api.h> #include <serious_python_windows/serious_python_windows_plugin_c_api.h>
#include <url_launcher_windows/url_launcher_windows.h> #include <url_launcher_windows/url_launcher_windows.h>
#include <window_manager/window_manager_plugin.h> #include <window_manager/window_manager_plugin.h>
#include <window_to_front/window_to_front_plugin.h> #include <window_to_front/window_to_front_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
AudioplayersWindowsPluginRegisterWithRegistrar( RecordWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin")); registry->GetRegistrarForPlugin("RecordWindowsPluginCApi"));
ScreenRetrieverPluginRegisterWithRegistrar( ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin")); registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi"));
SeriousPythonWindowsPluginCApiRegisterWithRegistrar( SeriousPythonWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SeriousPythonWindowsPluginCApi")); registry->GetRegistrarForPlugin("SeriousPythonWindowsPluginCApi"));
UrlLauncherWindowsRegisterWithRegistrar( UrlLauncherWindowsRegisterWithRegistrar(

View File

@ -3,8 +3,8 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
audioplayers_windows record_windows
screen_retriever screen_retriever_windows
serious_python_windows serious_python_windows
url_launcher_windows url_launcher_windows
window_manager window_manager