From 24201253f70a5836962f3de8fe95392df45d075b Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 12:38:34 -0800 Subject: [PATCH 01/14] feat(core): Add secure storage module Adds a secure storage interface which uses FFI bindings to the platform-specific Keychain implementation. --- .github/workflows/celest_core.yaml | 50 +- .vscode/settings.json | 6 + packages/celest_core/CHANGELOG.md | 4 + packages/celest_core/android/.gitignore | 8 + packages/celest_core/android/build.gradle | 62 + .../celest_core/android/consumer-rules.pro | 1 + packages/celest_core/android/settings.gradle | 6 + .../android/src/main/AndroidManifest.xml | 3 + .../celest/celest_core/CelestSecureStorage.kt | 59 + packages/celest_core/example/.gitignore | 43 + packages/celest_core/example/.metadata | 45 + packages/celest_core/example/README.md | 3 + .../celest_core/example/analysis_options.yaml | 1 + .../celest_core/example/android/.gitignore | 13 + .../example/android/app/build.gradle | 66 + .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 44 + .../celest_core_example/MainActivity.kt | 5 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 + .../app/src/main/res/values/styles.xml | 18 + .../app/src/profile/AndroidManifest.xml | 7 + .../celest_core/example/android/build.gradle | 18 + .../example/android/gradle.properties | 3 + .../gradle/wrapper/gradle-wrapper.properties | 5 + .../example/android/settings.gradle | 26 + .../secure_storage_shared.dart | 82 + .../integration_test/secure_storage_test.dart | 8 + packages/celest_core/example/ios/.gitignore | 34 + .../ios/Flutter/AppFrameworkInfo.plist | 26 + .../example/ios/Flutter/Debug.xcconfig | 2 + .../example/ios/Flutter/Release.xcconfig | 2 + packages/celest_core/example/ios/Podfile | 44 + packages/celest_core/example/ios/Podfile.lock | 22 + .../ios/Runner.xcodeproj/project.pbxproj | 731 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 98 + .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../example/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 + .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 295 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 450 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 282 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 462 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 704 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 586 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 1674 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 762 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 1226 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 1418 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + .../celest_core/example/ios/Runner/Info.plist | 49 + .../ios/Runner/Runner-Bridging-Header.h | 1 + .../example/ios/RunnerTests/RunnerTests.swift | 12 + packages/celest_core/example/lib/main.dart | 20 + packages/celest_core/example/linux/.gitignore | 1 + .../celest_core/example/linux/CMakeLists.txt | 145 + .../example/linux/flutter/CMakeLists.txt | 88 + .../flutter/generated_plugin_registrant.cc | 11 + .../flutter/generated_plugin_registrant.h | 15 + .../linux/flutter/generated_plugins.cmake | 24 + packages/celest_core/example/linux/main.cc | 6 + .../example/linux/my_application.cc | 124 + .../example/linux/my_application.h | 18 + packages/celest_core/example/macos/.gitignore | 7 + .../macos/Flutter/Flutter-Debug.xcconfig | 2 + .../macos/Flutter/Flutter-Release.xcconfig | 2 + .../Flutter/GeneratedPluginRegistrant.swift | 10 + packages/celest_core/example/macos/Podfile | 43 + .../celest_core/example/macos/Podfile.lock | 16 + .../macos/Runner.xcodeproj/project.pbxproj | 783 ++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 98 + .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../example/macos/Runner/AppDelegate.swift | 9 + .../AppIcon.appiconset/Contents.json | 68 + .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 102994 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 5680 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 520 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 14142 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 1066 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 36406 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 2218 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 343 ++ .../macos/Runner/Configs/AppInfo.xcconfig | 14 + .../macos/Runner/Configs/Debug.xcconfig | 2 + .../macos/Runner/Configs/Release.xcconfig | 2 + .../macos/Runner/Configs/Warnings.xcconfig | 13 + .../macos/Runner/DebugProfile.entitlements | 12 + .../example/macos/Runner/Info.plist | 32 + .../macos/Runner/MainFlutterWindow.swift | 15 + .../example/macos/Runner/Release.entitlements | 8 + .../macos/RunnerTests/RunnerTests.swift | 12 + packages/celest_core/example/main.dart | 31 - packages/celest_core/example/pubspec.yaml | 24 + .../example/test_driver/integration_test.dart | 5 + packages/celest_core/example/web/favicon.png | Bin 0 -> 917 bytes .../example/web/icons/Icon-192.png | Bin 0 -> 5292 bytes .../example/web/icons/Icon-512.png | Bin 0 -> 8252 bytes .../example/web/icons/Icon-maskable-192.png | Bin 0 -> 5594 bytes .../example/web/icons/Icon-maskable-512.png | Bin 0 -> 20998 bytes packages/celest_core/example/web/index.html | 59 + .../celest_core/example/web/manifest.json | 35 + .../celest_core/example/windows/.gitignore | 17 + .../example/windows/CMakeLists.txt | 108 + .../example/windows/flutter/CMakeLists.txt | 109 + .../flutter/generated_plugin_registrant.cc | 11 + .../flutter/generated_plugin_registrant.h | 15 + .../windows/flutter/generated_plugins.cmake | 24 + .../example/windows/runner/CMakeLists.txt | 40 + .../example/windows/runner/Runner.rc | 121 + .../example/windows/runner/flutter_window.cpp | 71 + .../example/windows/runner/flutter_window.h | 33 + .../example/windows/runner/main.cpp | 43 + .../example/windows/runner/resource.h | 16 + .../windows/runner/resources/app_icon.ico | Bin 0 -> 33772 bytes .../windows/runner/runner.exe.manifest | 20 + .../example/windows/runner/utils.cpp | 65 + .../example/windows/runner/utils.h | 19 + .../example/windows/runner/win32_window.cpp | 288 ++ .../example/windows/runner/win32_window.h | 102 + .../celest_core/ffigen.core_foundation.yaml | 53 + packages/celest_core/ffigen.security.yaml | 88 + packages/celest_core/jnigen.yaml | 20 + .../src/native/android/jni_bindings.ffi.dart | 4048 +++++++++++++++++ .../native/darwin/core_foundation.ffi.dart | 1950 ++++++++ .../src/native/darwin/darwin_ffi_helpers.dart | 133 + .../lib/src/native/darwin/security.ffi.dart | 2758 +++++++++++ .../secure_storage.android.dart | 39 + .../src/secure_storage/secure_storage.dart | 12 + .../secure_storage/secure_storage.darwin.dart | 189 + .../secure_storage/secure_storage.stub.dart | 24 + .../secure_storage_exception.dart | 69 + .../secure_storage_platform.vm.dart | 28 + .../secure_storage_platform.web.dart | 18 + packages/celest_core/pubspec.yaml | 16 + .../secure_storage_darwin_test.dart | 72 + .../secure_storage/secure_storage_test.dart | 5 + .../{ => serialization}/json_value_test.dart | 0 packages/celest_core/tool/ffigen.sh | 16 + 162 files changed, 14653 insertions(+), 41 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 packages/celest_core/android/.gitignore create mode 100644 packages/celest_core/android/build.gradle create mode 100644 packages/celest_core/android/consumer-rules.pro create mode 100644 packages/celest_core/android/settings.gradle create mode 100644 packages/celest_core/android/src/main/AndroidManifest.xml create mode 100644 packages/celest_core/android/src/main/kotlin/dev/celest/celest_core/CelestSecureStorage.kt create mode 100644 packages/celest_core/example/.gitignore create mode 100644 packages/celest_core/example/.metadata create mode 100644 packages/celest_core/example/README.md create mode 100644 packages/celest_core/example/analysis_options.yaml create mode 100644 packages/celest_core/example/android/.gitignore create mode 100644 packages/celest_core/example/android/app/build.gradle create mode 100644 packages/celest_core/example/android/app/src/debug/AndroidManifest.xml create mode 100644 packages/celest_core/example/android/app/src/main/AndroidManifest.xml create mode 100644 packages/celest_core/example/android/app/src/main/kotlin/dev/celest/celest_core_example/MainActivity.kt create mode 100644 packages/celest_core/example/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 packages/celest_core/example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 packages/celest_core/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 packages/celest_core/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 packages/celest_core/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 packages/celest_core/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 packages/celest_core/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 packages/celest_core/example/android/app/src/main/res/values-night/styles.xml create mode 100644 packages/celest_core/example/android/app/src/main/res/values/styles.xml create mode 100644 packages/celest_core/example/android/app/src/profile/AndroidManifest.xml create mode 100644 packages/celest_core/example/android/build.gradle create mode 100644 packages/celest_core/example/android/gradle.properties create mode 100644 packages/celest_core/example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 packages/celest_core/example/android/settings.gradle create mode 100644 packages/celest_core/example/integration_test/secure_storage_shared.dart create mode 100644 packages/celest_core/example/integration_test/secure_storage_test.dart create mode 100644 packages/celest_core/example/ios/.gitignore create mode 100644 packages/celest_core/example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 packages/celest_core/example/ios/Flutter/Debug.xcconfig create mode 100644 packages/celest_core/example/ios/Flutter/Release.xcconfig create mode 100644 packages/celest_core/example/ios/Podfile create mode 100644 packages/celest_core/example/ios/Podfile.lock create mode 100644 packages/celest_core/example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 packages/celest_core/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/celest_core/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/celest_core/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/celest_core/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/celest_core/example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/celest_core/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/celest_core/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/celest_core/example/ios/Runner/AppDelegate.swift create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 packages/celest_core/example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 packages/celest_core/example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 packages/celest_core/example/ios/Runner/Info.plist create mode 100644 packages/celest_core/example/ios/Runner/Runner-Bridging-Header.h create mode 100644 packages/celest_core/example/ios/RunnerTests/RunnerTests.swift create mode 100644 packages/celest_core/example/lib/main.dart create mode 100644 packages/celest_core/example/linux/.gitignore create mode 100644 packages/celest_core/example/linux/CMakeLists.txt create mode 100644 packages/celest_core/example/linux/flutter/CMakeLists.txt create mode 100644 packages/celest_core/example/linux/flutter/generated_plugin_registrant.cc create mode 100644 packages/celest_core/example/linux/flutter/generated_plugin_registrant.h create mode 100644 packages/celest_core/example/linux/flutter/generated_plugins.cmake create mode 100644 packages/celest_core/example/linux/main.cc create mode 100644 packages/celest_core/example/linux/my_application.cc create mode 100644 packages/celest_core/example/linux/my_application.h create mode 100644 packages/celest_core/example/macos/.gitignore create mode 100644 packages/celest_core/example/macos/Flutter/Flutter-Debug.xcconfig create mode 100644 packages/celest_core/example/macos/Flutter/Flutter-Release.xcconfig create mode 100644 packages/celest_core/example/macos/Flutter/GeneratedPluginRegistrant.swift create mode 100644 packages/celest_core/example/macos/Podfile create mode 100644 packages/celest_core/example/macos/Podfile.lock create mode 100644 packages/celest_core/example/macos/Runner.xcodeproj/project.pbxproj create mode 100644 packages/celest_core/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/celest_core/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/celest_core/example/macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/celest_core/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/celest_core/example/macos/Runner/AppDelegate.swift create mode 100644 packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 packages/celest_core/example/macos/Runner/Base.lproj/MainMenu.xib create mode 100644 packages/celest_core/example/macos/Runner/Configs/AppInfo.xcconfig create mode 100644 packages/celest_core/example/macos/Runner/Configs/Debug.xcconfig create mode 100644 packages/celest_core/example/macos/Runner/Configs/Release.xcconfig create mode 100644 packages/celest_core/example/macos/Runner/Configs/Warnings.xcconfig create mode 100644 packages/celest_core/example/macos/Runner/DebugProfile.entitlements create mode 100644 packages/celest_core/example/macos/Runner/Info.plist create mode 100644 packages/celest_core/example/macos/Runner/MainFlutterWindow.swift create mode 100644 packages/celest_core/example/macos/Runner/Release.entitlements create mode 100644 packages/celest_core/example/macos/RunnerTests/RunnerTests.swift delete mode 100644 packages/celest_core/example/main.dart create mode 100644 packages/celest_core/example/pubspec.yaml create mode 100644 packages/celest_core/example/test_driver/integration_test.dart create mode 100644 packages/celest_core/example/web/favicon.png create mode 100644 packages/celest_core/example/web/icons/Icon-192.png create mode 100644 packages/celest_core/example/web/icons/Icon-512.png create mode 100644 packages/celest_core/example/web/icons/Icon-maskable-192.png create mode 100644 packages/celest_core/example/web/icons/Icon-maskable-512.png create mode 100644 packages/celest_core/example/web/index.html create mode 100644 packages/celest_core/example/web/manifest.json create mode 100644 packages/celest_core/example/windows/.gitignore create mode 100644 packages/celest_core/example/windows/CMakeLists.txt create mode 100644 packages/celest_core/example/windows/flutter/CMakeLists.txt create mode 100644 packages/celest_core/example/windows/flutter/generated_plugin_registrant.cc create mode 100644 packages/celest_core/example/windows/flutter/generated_plugin_registrant.h create mode 100644 packages/celest_core/example/windows/flutter/generated_plugins.cmake create mode 100644 packages/celest_core/example/windows/runner/CMakeLists.txt create mode 100644 packages/celest_core/example/windows/runner/Runner.rc create mode 100644 packages/celest_core/example/windows/runner/flutter_window.cpp create mode 100644 packages/celest_core/example/windows/runner/flutter_window.h create mode 100644 packages/celest_core/example/windows/runner/main.cpp create mode 100644 packages/celest_core/example/windows/runner/resource.h create mode 100644 packages/celest_core/example/windows/runner/resources/app_icon.ico create mode 100644 packages/celest_core/example/windows/runner/runner.exe.manifest create mode 100644 packages/celest_core/example/windows/runner/utils.cpp create mode 100644 packages/celest_core/example/windows/runner/utils.h create mode 100644 packages/celest_core/example/windows/runner/win32_window.cpp create mode 100644 packages/celest_core/example/windows/runner/win32_window.h create mode 100644 packages/celest_core/ffigen.core_foundation.yaml create mode 100644 packages/celest_core/ffigen.security.yaml create mode 100644 packages/celest_core/jnigen.yaml create mode 100644 packages/celest_core/lib/src/native/android/jni_bindings.ffi.dart create mode 100644 packages/celest_core/lib/src/native/darwin/core_foundation.ffi.dart create mode 100644 packages/celest_core/lib/src/native/darwin/darwin_ffi_helpers.dart create mode 100644 packages/celest_core/lib/src/native/darwin/security.ffi.dart create mode 100644 packages/celest_core/lib/src/secure_storage/secure_storage.android.dart create mode 100644 packages/celest_core/lib/src/secure_storage/secure_storage.dart create mode 100644 packages/celest_core/lib/src/secure_storage/secure_storage.darwin.dart create mode 100644 packages/celest_core/lib/src/secure_storage/secure_storage.stub.dart create mode 100644 packages/celest_core/lib/src/secure_storage/secure_storage_exception.dart create mode 100644 packages/celest_core/lib/src/secure_storage/secure_storage_platform.vm.dart create mode 100644 packages/celest_core/lib/src/secure_storage/secure_storage_platform.web.dart create mode 100644 packages/celest_core/test/secure_storage/secure_storage_darwin_test.dart create mode 100644 packages/celest_core/test/secure_storage/secure_storage_test.dart rename packages/celest_core/test/{ => serialization}/json_value_test.dart (100%) create mode 100755 packages/celest_core/tool/ffigen.sh diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index e1f4eb5c..3f800c88 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -12,20 +12,50 @@ concurrency: cancel-in-progress: true jobs: - analyze_and_format: - runs-on: ubuntu-latest - timeout-minutes: 10 + # analyze_and_format: + # runs-on: ubuntu-latest + # timeout-minutes: 10 + # steps: + # - name: Git Checkout + # uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # 4.1.1 + # - name: Setup Dart + # uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # 1.6.2 + # - name: Get Packages + # working-directory: packages/celest_core + # run: dart pub get + # - name: Analyze + # working-directory: packages/celest_core + # run: dart analyze --fatal-infos --fatal-warnings + # - name: Format + # working-directory: packages/celest_core + # run: dart format --set-exit-if-changed . + test: + # needs: analyze_and_format + runs-on: macos-xl + timeout-minutes: 15 steps: - name: Git Checkout uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # 4.1.1 - - name: Setup Dart - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # 1.6.2 + - name: Setup Flutter + uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # 2.13.0 + with: + cache: true + - name: Setup Android + uses: ReactiveCircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 # 2.30.1 + with: + api-level: 34 - name: Get Packages working-directory: packages/celest_core run: dart pub get - - name: Analyze + - name: Test working-directory: packages/celest_core - run: dart analyze --fatal-infos --fatal-warnings - - name: Format - working-directory: packages/celest_core - run: dart format --set-exit-if-changed . + run: dart test + - name: Get Packages (Example) + working-directory: packages/celest_core/example + run: flutter pub get + - name: Test (Example) + working-directory: packages/celest_core/example + run: | + for OS in "sdk iPhone macos"; do + flutter test -d $OS integration_test/secure_storage_test.dart + done diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..290fa83f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.associations": { + "__locale": "cpp", + "locale": "cpp" + } +} \ No newline at end of file diff --git a/packages/celest_core/CHANGELOG.md b/packages/celest_core/CHANGELOG.md index 077668af..f1399e1f 100644 --- a/packages/celest_core/CHANGELOG.md +++ b/packages/celest_core/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.2-wip + +- Adds `Keychain` interface for secure storage of sensitive data. + ## 0.2.1 - Overrides `toString` for `CloudException` types. diff --git a/packages/celest_core/android/.gitignore b/packages/celest_core/android/.gitignore new file mode 100644 index 00000000..167e46c9 --- /dev/null +++ b/packages/celest_core/android/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +local.properties +.idea/ +.DS_Store +build +captures +.cxx \ No newline at end of file diff --git a/packages/celest_core/android/build.gradle b/packages/celest_core/android/build.gradle new file mode 100644 index 00000000..d259ba69 --- /dev/null +++ b/packages/celest_core/android/build.gradle @@ -0,0 +1,62 @@ +group 'dev.celest.celest_core' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.7.21' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.4.2' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + // Conditional for compatibility with AGP <4.2. + if (project.android.hasProperty("namespace")) { + namespace 'dev.celest.celest_core' + } + + compileSdk 31 + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + minSdkVersion 21 + consumerProguardFiles 'consumer-rules.pro' + } + + buildTypes { + release { + minifyEnabled false + } + } +} + +dependencies { + implementation 'androidx.security:security-crypto:[1.1.0-alpha04,)' +} diff --git a/packages/celest_core/android/consumer-rules.pro b/packages/celest_core/android/consumer-rules.pro new file mode 100644 index 00000000..b1869a38 --- /dev/null +++ b/packages/celest_core/android/consumer-rules.pro @@ -0,0 +1 @@ +-keep class dev.celest.celest_core.** { *; } \ No newline at end of file diff --git a/packages/celest_core/android/settings.gradle b/packages/celest_core/android/settings.gradle new file mode 100644 index 00000000..5c967786 --- /dev/null +++ b/packages/celest_core/android/settings.gradle @@ -0,0 +1,6 @@ +rootProject.name = 'celest_core' +dependencyResolutionManagement { + repositories { + google() + } +} diff --git a/packages/celest_core/android/src/main/AndroidManifest.xml b/packages/celest_core/android/src/main/AndroidManifest.xml new file mode 100644 index 00000000..73a53d2f --- /dev/null +++ b/packages/celest_core/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + \ No newline at end of file diff --git a/packages/celest_core/android/src/main/kotlin/dev/celest/celest_core/CelestSecureStorage.kt b/packages/celest_core/android/src/main/kotlin/dev/celest/celest_core/CelestSecureStorage.kt new file mode 100644 index 00000000..1aa4a3f4 --- /dev/null +++ b/packages/celest_core/android/src/main/kotlin/dev/celest/celest_core/CelestSecureStorage.kt @@ -0,0 +1,59 @@ +package dev.celest.celest_core + +import android.annotation.SuppressLint +import android.app.Activity +import android.content.SharedPreferences +import androidx.annotation.Keep +import androidx.annotation.Nullable +import androidx.security.crypto.EncryptedSharedPreferences +import androidx.security.crypto.MasterKey + +// TODO(dnys1): Exclude from backup: +// - https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences +// - https://developer.android.com/guide/topics/data/autobackup#IncludingFiles +@Keep +class CelestSecureStorage(private val mainActivity: Activity, private val scope: String) { + + private val sharedPreferences: SharedPreferences by lazy { + val masterKey = MasterKey.Builder(mainActivity) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build() + val sharedPreferences = EncryptedSharedPreferences.create( + mainActivity, + scope, + masterKey, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM, + ) + sharedPreferences + } + + private val editor: SharedPreferences.Editor + get() = sharedPreferences.edit() + + fun write(dataKey: String, value: String?) { + with(editor) { + putString(dataKey, value) + apply() + } + } + + fun read(dataKey: String): String? = sharedPreferences.getString(dataKey, null) + + fun delete(dataKey: String): String? { + val current = read(dataKey) + with(editor) { + remove(dataKey) + apply() + } + return current + } + + fun clear() { + with(editor) { + clear() + apply() + } + } + +} \ No newline at end of file diff --git a/packages/celest_core/example/.gitignore b/packages/celest_core/example/.gitignore new file mode 100644 index 00000000..29a3a501 --- /dev/null +++ b/packages/celest_core/example/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/packages/celest_core/example/.metadata b/packages/celest_core/example/.metadata new file mode 100644 index 00000000..bae49f35 --- /dev/null +++ b/packages/celest_core/example/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "7482962148e8d758338d8a28f589f317e1e42ba4" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + - platform: android + create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + - platform: ios + create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + - platform: linux + create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + - platform: macos + create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + - platform: web + create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + - platform: windows + create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/celest_core/example/README.md b/packages/celest_core/example/README.md new file mode 100644 index 00000000..a86e4bb2 --- /dev/null +++ b/packages/celest_core/example/README.md @@ -0,0 +1,3 @@ +# celest_core_example + +A new Flutter project. diff --git a/packages/celest_core/example/analysis_options.yaml b/packages/celest_core/example/analysis_options.yaml new file mode 100644 index 00000000..f9b30346 --- /dev/null +++ b/packages/celest_core/example/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flutter_lints/flutter.yaml diff --git a/packages/celest_core/example/android/.gitignore b/packages/celest_core/example/android/.gitignore new file mode 100644 index 00000000..6f568019 --- /dev/null +++ b/packages/celest_core/example/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/packages/celest_core/example/android/app/build.gradle b/packages/celest_core/example/android/app/build.gradle new file mode 100644 index 00000000..b82b7db2 --- /dev/null +++ b/packages/celest_core/example/android/app/build.gradle @@ -0,0 +1,66 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + namespace "dev.celest.celest_core_example" + compileSdk flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + applicationId "dev.celest.celest_core_example" + minSdkVersion 21 + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + // These dependencies are only present so that `jnigen` will work. + // Applications should not include these. + implementation 'androidx.security:security-crypto:[1.1.0-alpha04,)' +} diff --git a/packages/celest_core/example/android/app/src/debug/AndroidManifest.xml b/packages/celest_core/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..399f6981 --- /dev/null +++ b/packages/celest_core/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/packages/celest_core/example/android/app/src/main/AndroidManifest.xml b/packages/celest_core/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..3aa8d8b3 --- /dev/null +++ b/packages/celest_core/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/celest_core/example/android/app/src/main/kotlin/dev/celest/celest_core_example/MainActivity.kt b/packages/celest_core/example/android/app/src/main/kotlin/dev/celest/celest_core_example/MainActivity.kt new file mode 100644 index 00000000..3f6455e9 --- /dev/null +++ b/packages/celest_core/example/android/app/src/main/kotlin/dev/celest/celest_core_example/MainActivity.kt @@ -0,0 +1,5 @@ +package dev.celest.celest_core_example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() diff --git a/packages/celest_core/example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/celest_core/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 00000000..f74085f3 --- /dev/null +++ b/packages/celest_core/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/celest_core/example/android/app/src/main/res/drawable/launch_background.xml b/packages/celest_core/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 00000000..304732f8 --- /dev/null +++ b/packages/celest_core/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/celest_core/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/celest_core/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/celest_core/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/celest_core/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/celest_core/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/android/app/src/main/res/values-night/styles.xml b/packages/celest_core/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 00000000..06952be7 --- /dev/null +++ b/packages/celest_core/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/celest_core/example/android/app/src/main/res/values/styles.xml b/packages/celest_core/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..cb1ef880 --- /dev/null +++ b/packages/celest_core/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/celest_core/example/android/app/src/profile/AndroidManifest.xml b/packages/celest_core/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..399f6981 --- /dev/null +++ b/packages/celest_core/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/packages/celest_core/example/android/build.gradle b/packages/celest_core/example/android/build.gradle new file mode 100644 index 00000000..bc157bd1 --- /dev/null +++ b/packages/celest_core/example/android/build.gradle @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/packages/celest_core/example/android/gradle.properties b/packages/celest_core/example/android/gradle.properties new file mode 100644 index 00000000..598d13fe --- /dev/null +++ b/packages/celest_core/example/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx4G +android.useAndroidX=true +android.enableJetifier=true diff --git a/packages/celest_core/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/celest_core/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..e1ca574e --- /dev/null +++ b/packages/celest_core/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip diff --git a/packages/celest_core/example/android/settings.gradle b/packages/celest_core/example/android/settings.gradle new file mode 100644 index 00000000..1d6d19b7 --- /dev/null +++ b/packages/celest_core/example/android/settings.gradle @@ -0,0 +1,26 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + } + settings.ext.flutterSdkPath = flutterSdkPath() + + includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.3.0" apply false + id "org.jetbrains.kotlin.android" version "1.7.10" apply false +} + +include ":app" diff --git a/packages/celest_core/example/integration_test/secure_storage_shared.dart b/packages/celest_core/example/integration_test/secure_storage_shared.dart new file mode 100644 index 00000000..fe7e8a49 --- /dev/null +++ b/packages/celest_core/example/integration_test/secure_storage_shared.dart @@ -0,0 +1,82 @@ +import 'dart:math'; + +import 'package:celest_core/src/secure_storage/secure_storage.dart'; +import 'package:test/test.dart'; + +void sharedTests() { + group('SecureStorage', () { + late String key; + final storage = SecureStorage(scope: 'test'); + + setUp(() { + storage.clear(); + // Add some randomness to prevent overlap between concurrent tests. + key = String.fromCharCodes( + List.generate(10, (_) => _random.nextInt(255) + 1), + ); + }); + + tearDownAll(() { + storage.clear(); + }); + + group('write', () { + test('writes a new key-value pair to storage', () { + storage.write(key, 'value'); + expect(storage.read(key), 'value'); + }); + + test('updates the value for an existing key', () { + storage.write(key, 'write'); + expect(storage.read(key), 'write', reason: 'Value was written'); + + storage.write(key, 'update'); + expect(storage.read(key), 'update', reason: 'Value was updated'); + }); + }); + + group('read', () { + test('can read a non-existent key', () { + expect(storage.read(key), isNull); + }); + }); + + group('delete', () { + test('removes the key if it exists', () { + storage.write(key, 'delete'); + expect(storage.read(key), 'delete', reason: 'Value was written'); + + storage.delete(key); + expect(storage.read(key), isNull, reason: 'Value was deleted'); + }); + + test('can delete a non-existent key', () { + expect(() => storage.delete(key), returnsNormally); + expect(() => storage.delete(key), returnsNormally); + expect(() => storage.delete(key), returnsNormally); + }); + }); + + group('read/write/delete can handle key value pairs of varying length', () { + for (final (length, s) in largeKeyValuePairs) { + test('can store key/value with length $length', () { + storage.write(s, s); + expect(storage.read(s), s, reason: 'Value was written'); + + storage.delete(s); + expect(storage.read(s), isNull, reason: 'Value was deleted'); + }); + } + }); + }); +} + +final _random = Random(); +Iterable<(int, String)> get largeKeyValuePairs sync* { + for (final length in const [100, 1000, 10000]) { + final string = String.fromCharCodes( + List.generate(length, (_) => _random.nextInt(255) + 1), + ); + yield (length, string); + } +} diff --git a/packages/celest_core/example/integration_test/secure_storage_test.dart b/packages/celest_core/example/integration_test/secure_storage_test.dart new file mode 100644 index 00000000..5e4eff5e --- /dev/null +++ b/packages/celest_core/example/integration_test/secure_storage_test.dart @@ -0,0 +1,8 @@ +import 'package:integration_test/integration_test.dart'; + +import 'secure_storage_shared.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + sharedTests(); +} diff --git a/packages/celest_core/example/ios/.gitignore b/packages/celest_core/example/ios/.gitignore new file mode 100644 index 00000000..7a7f9873 --- /dev/null +++ b/packages/celest_core/example/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/packages/celest_core/example/ios/Flutter/AppFrameworkInfo.plist b/packages/celest_core/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..7c569640 --- /dev/null +++ b/packages/celest_core/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/packages/celest_core/example/ios/Flutter/Debug.xcconfig b/packages/celest_core/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..ec97fc6f --- /dev/null +++ b/packages/celest_core/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/celest_core/example/ios/Flutter/Release.xcconfig b/packages/celest_core/example/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..c4855bfe --- /dev/null +++ b/packages/celest_core/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/celest_core/example/ios/Podfile b/packages/celest_core/example/ios/Podfile new file mode 100644 index 00000000..d97f17e2 --- /dev/null +++ b/packages/celest_core/example/ios/Podfile @@ -0,0 +1,44 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '12.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/celest_core/example/ios/Podfile.lock b/packages/celest_core/example/ios/Podfile.lock new file mode 100644 index 00000000..84bbe8b8 --- /dev/null +++ b/packages/celest_core/example/ios/Podfile.lock @@ -0,0 +1,22 @@ +PODS: + - Flutter (1.0.0) + - integration_test (0.0.1): + - Flutter + +DEPENDENCIES: + - Flutter (from `Flutter`) + - integration_test (from `.symlinks/plugins/integration_test/ios`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + integration_test: + :path: ".symlinks/plugins/integration_test/ios" + +SPEC CHECKSUMS: + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + integration_test: 13825b8a9334a850581300559b8839134b124670 + +PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 + +COCOAPODS: 1.15.0 diff --git a/packages/celest_core/example/ios/Runner.xcodeproj/project.pbxproj b/packages/celest_core/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..2f0e2be1 --- /dev/null +++ b/packages/celest_core/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,731 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 7617BF077D3512DCAA0DB2A8 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C97E0BC7AE8D9D9901E731A /* Pods_RunnerTests.framework */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + AF353EBE084243CFF3F1D321 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E283F6BF96857279274270FE /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0719E5A2F3687A63996F85BE /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 1E57296042765F5C62B7DF05 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 22A54C2967A19B1CB6642C91 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 2C97E0BC7AE8D9D9901E731A /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 64ABE791AF4EAAA6FBBFCFD9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E283F6BF96857279274270FE /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E2B6A9055C887BFE95006F5E /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + E454D2E5416E20F155389E3E /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AF353EBE084243CFF3F1D321 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B269C471107164EE54717C58 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7617BF077D3512DCAA0DB2A8 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 31E7259D84779F5BB392A60A /* Pods */ = { + isa = PBXGroup; + children = ( + 22A54C2967A19B1CB6642C91 /* Pods-Runner.debug.xcconfig */, + E454D2E5416E20F155389E3E /* Pods-Runner.release.xcconfig */, + 64ABE791AF4EAAA6FBBFCFD9 /* Pods-Runner.profile.xcconfig */, + 0719E5A2F3687A63996F85BE /* Pods-RunnerTests.debug.xcconfig */, + E2B6A9055C887BFE95006F5E /* Pods-RunnerTests.release.xcconfig */, + 1E57296042765F5C62B7DF05 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + 31E7259D84779F5BB392A60A /* Pods */, + ABA9456D007CA1E3CF5BA6AB /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + ABA9456D007CA1E3CF5BA6AB /* Frameworks */ = { + isa = PBXGroup; + children = ( + E283F6BF96857279274270FE /* Pods_Runner.framework */, + 2C97E0BC7AE8D9D9901E731A /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 41512757A1592A2E9E885BFB /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + B269C471107164EE54717C58 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + F5CD319CA982986026BDAB9B /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 35B9DCD971FDF65F80D75C50 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 35B9DCD971FDF65F80D75C50 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 41512757A1592A2E9E885BFB /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + F5CD319CA982986026BDAB9B /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 3N6FCLHNUW; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.celest.celestCoreExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0719E5A2F3687A63996F85BE /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.celest.celestCoreExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E2B6A9055C887BFE95006F5E /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.celest.celestCoreExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1E57296042765F5C62B7DF05 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.celest.celestCoreExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 3N6FCLHNUW; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.celest.celestCoreExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 3N6FCLHNUW; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.celest.celestCoreExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/packages/celest_core/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/celest_core/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/packages/celest_core/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/celest_core/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/celest_core/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/packages/celest_core/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/celest_core/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/celest_core/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/packages/celest_core/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/celest_core/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/celest_core/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..8e3ca5df --- /dev/null +++ b/packages/celest_core/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/celest_core/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/celest_core/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/packages/celest_core/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/packages/celest_core/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/celest_core/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/packages/celest_core/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/celest_core/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/celest_core/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/packages/celest_core/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/celest_core/example/ios/Runner/AppDelegate.swift b/packages/celest_core/example/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..70693e4a --- /dev/null +++ b/packages/celest_core/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d36b1fab --- /dev/null +++ b/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..797d452e458972bab9d994556c8305db4c827017 GIT binary patch literal 406 zcmV;H0crk;P))>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2d933e1120817fe9182483a228007b18ab6ae GIT binary patch literal 450 zcmV;z0X_bSP)iGWQ_5NJQ_~rNh*z)}eT%KUb z`7gNk0#AwF^#0T0?hIa^`~Ck;!}#m+_uT050aTR(J!bU#|IzRL%^UsMS#KsYnTF*!YeDOytlP4VhV?b} z%rz_<=#CPc)tU1MZTq~*2=8~iZ!lSa<{9b@2Jl;?IEV8)=fG217*|@)CCYgFze-x? zIFODUIA>nWKpE+bn~n7;-89sa>#DR>TSlqWk*!2hSN6D~Qb#VqbP~4Fk&m`@1$JGr zXPIdeRE&b2Thd#{MtDK$px*d3-Wx``>!oimf%|A-&-q*6KAH)e$3|6JV%HX{Hig)k suLT-RhftRq8b9;(V=235Wa|I=027H2wCDra;{X5v07*qoM6N<$f;9x^2LJ#7 literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..4cd7b0099ca80c806f8fe495613e8d6c69460d76 GIT binary patch literal 282 zcmV+#0p(^bcu7P-R4C8Q z&e;xxFbF_Vrezo%_kH*OKhshZ6BFpG-Y1e10`QXJKbND7AMQ&cMj60B5TNObaZxYybcN07*qoM6N<$g3m;S%K!iX literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe730945a01f64a61e2235dbe3f45b08f7729182 GIT binary patch literal 462 zcmV;<0WtoGP)-}iV`2<;=$?g5M=KQbZ{F&YRNy7Nn@%_*5{gvDM0aKI4?ESmw z{NnZg)A0R`+4?NF_RZexyVB&^^ZvN!{I28tr{Vje;QNTz`dG&Jz0~Ek&f2;*Z7>B|cg}xYpxEFY+0YrKLF;^Q+-HreN0P{&i zK~zY`?b7ECf-n?@;d<&orQ*Q7KoR%4|C>{W^h6@&01>0SKS`dn{Q}GT%Qj_{PLZ_& zs`MFI#j-(>?bvdZ!8^xTwlY{qA)T4QLbY@j(!YJ7aXJervHy6HaG_2SB`6CC{He}f zHVw(fJWApwPq!6VY7r1w-Fs)@ox~N+q|w~e;JI~C4Vf^@d>Wvj=fl`^u9x9wd9 zR%3*Q+)t%S!MU_`id^@&Y{y7-r98lZX0?YrHlfmwb?#}^1b{8g&KzmkE(L>Z&)179 zp<)v6Y}pRl100G2FL_t(o!|l{-Q-VMg#&MKg7c{O0 z2wJImOS3Gy*Z2Qifdv~JYOp;v+U)a|nLoc7hNH;I$;lzDt$}rkaFw1mYK5_0Q(Sut zvbEloxON7$+HSOgC9Z8ltuC&0OSF!-mXv5caV>#bc3@hBPX@I$58-z}(ZZE!t-aOG zpjNkbau@>yEzH(5Yj4kZiMH32XI!4~gVXNnjAvRx;Sdg^`>2DpUEwoMhTs_st8pKG z(%SHyHdU&v%f36~uERh!bd`!T2dw;z6PrOTQ7Vt*#9F2uHlUVnb#ev_o^fh}Dzmq} zWtlk35}k=?xj28uO|5>>$yXadTUE@@IPpgH`gJ~Ro4>jd1IF|(+IX>8M4Ps{PNvmI zNj4D+XgN83gPt_Gm}`Ybv{;+&yu-C(Grdiahmo~BjG-l&mWM+{e5M1sm&=xduwgM9 z`8OEh`=F3r`^E{n_;%9weN{cf2%7=VzC@cYj+lg>+3|D|_1C@{hcU(DyQG_BvBWe? zvTv``=%b1zrol#=R`JB)>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..502f463a9bc882b461c96aadf492d1729e49e725 GIT binary patch literal 586 zcmV-Q0=4~#P)+}#`wDE{8-2Mebf5<{{PqV{TgVcv*r8?UZ3{-|G?_}T*&y;@cqf{ z{Q*~+qr%%p!1pS*_Uicl#q9lc(D`!D`LN62sNwq{oYw(Wmhk)k<@f$!$@ng~_5)Ru z0Z)trIA5^j{DIW^c+vT2%lW+2<(RtE2wR;4O@)Tm`Xr*?A(qYoM}7i5Yxw>D(&6ou zxz!_Xr~yNF+waPe00049Nkl*;a!v6h%{rlvIH#gW3s8p;bFr=l}mRqpW2h zw=OA%hdyL~z+UHOzl0eKhEr$YYOL-c-%Y<)=j?(bzDweB7{b+%_ypvm_cG{SvM=DK zhv{K@m>#Bw>2W$eUI#iU)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G! zhkE!s;%oku3;IwG3U^2kw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn`0X*2 zy3(k600_CSZj?O$Qu%&$;|TGUJrptR(HzyIx>5E(2r{eA(<6t3e3I0B)7d6s7?Z5J zZ!rtKvA{MiEBm&KFtoifx>5P^Z=vl)95XJn()aS5%ad(s?4-=Tkis9IGu{`Fy8r+H07*qoM6N<$f20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec303439225b78712f49115768196d8d76f6790 GIT binary patch literal 862 zcmV-k1EKthP)20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f5fea27c705180eb716271f41b582e76dcbd90 GIT binary patch literal 1674 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 literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/celest_core/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0467bf12aa4d28f374bb26596605a46dcbb3e7c8 GIT binary patch literal 1418 zcmV;51$Fv~P)q zKfU)WzW*n(@|xWGCA9ScMt*e9`2kdxPQ&&>|-UCa7_51w+ zLUsW@ZzZSW0y$)Hp~e9%PvP|a03ks1`~K?q{u;6NC8*{AOqIUq{CL&;p56Lf$oQGq z^={4hPQv)y=I|4n+?>7Fim=dxt1 z2H+Dm+1+fh+IF>G0SjJMkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJT zkdTm&kdTm&kdTm&kdP`esgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>Tmf` zm1{eLgw!b{bXkjWbF%dTkTZEJWyWOb##Lfw4EK2}<0d6%>AGS{po>WCOy&f$Tay_> z?NBlkpo@s-O;0V%Y_Xa-G#_O08q5LR*~F%&)}{}r&L%Sbs8AS4t7Y0NEx*{soY=0MZExqA5XHQkqi#4gW3 zqODM^iyZl;dvf)-bOXtOru(s)Uc7~BFx{w-FK;2{`VA?(g&@3z&bfLFyctOH!cVsF z7IL=fo-qBndRUm;kAdXR4e6>k-z|21AaN%ubeVrHl*<|s&Ax@W-t?LR(P-24A5=>a z*R9#QvjzF8n%@1Nw@?CG@6(%>+-0ASK~jEmCV|&a*7-GKT72W<(TbSjf)&Eme6nGE z>Gkj4Sq&2e+-G%|+NM8OOm5zVl9{Z8Dd8A5z3y8mZ=4Bv4%>as_{9cN#bm~;h>62( zdqY93Zy}v&c4n($Vv!UybR8ocs7#zbfX1IY-*w~)p}XyZ-SFC~4w>BvMVr`dFbelV{lLL0bx7@*ZZdebr3`sP;? zVImji)kG)(6Juv0lz@q`F!k1FE;CQ(D0iG$wchPbKZQELlsZ#~rt8#90Y_Xh&3U-< z{s<&cCV_1`^TD^ia9!*mQDq& zn2{r`j};V|uV%_wsP!zB?m%;FeaRe+X47K0e+KE!8C{gAWF8)lCd1u1%~|M!XNRvw zvtqy3iz0WSpWdhn6$hP8PaRBmp)q`#PCA`Vd#Tc$@f1tAcM>f_I@bC)hkI9|o(Iqv zo}Piadq!j76}004RBio<`)70k^`K1NK)q>w?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF z34$0Z;QO!JOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUC YUoZo%k(ykuW&i*H07*qoM6N<$f+CH{y8r+H literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 00000000..0bedcf2f --- /dev/null +++ b/packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/packages/celest_core/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/celest_core/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/celest_core/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/packages/celest_core/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/celest_core/example/ios/Runner/Base.lproj/Main.storyboard b/packages/celest_core/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/packages/celest_core/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/celest_core/example/ios/Runner/Info.plist b/packages/celest_core/example/ios/Runner/Info.plist new file mode 100644 index 00000000..924652c6 --- /dev/null +++ b/packages/celest_core/example/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Celest Core Example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + celest_core_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/packages/celest_core/example/ios/Runner/Runner-Bridging-Header.h b/packages/celest_core/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..308a2a56 --- /dev/null +++ b/packages/celest_core/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/packages/celest_core/example/ios/RunnerTests/RunnerTests.swift b/packages/celest_core/example/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 00000000..86a7c3b1 --- /dev/null +++ b/packages/celest_core/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/packages/celest_core/example/lib/main.dart b/packages/celest_core/example/lib/main.dart new file mode 100644 index 00000000..a7256585 --- /dev/null +++ b/packages/celest_core/example/lib/main.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; + +void main() { + runApp(const MainApp()); +} + +class MainApp extends StatelessWidget { + const MainApp({super.key}); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + home: Scaffold( + body: Center( + child: Text('Hello World!'), + ), + ), + ); + } +} diff --git a/packages/celest_core/example/linux/.gitignore b/packages/celest_core/example/linux/.gitignore new file mode 100644 index 00000000..d3896c98 --- /dev/null +++ b/packages/celest_core/example/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/packages/celest_core/example/linux/CMakeLists.txt b/packages/celest_core/example/linux/CMakeLists.txt new file mode 100644 index 00000000..1597108e --- /dev/null +++ b/packages/celest_core/example/linux/CMakeLists.txt @@ -0,0 +1,145 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "celest_core_example") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "dev.celest.celest_core_example") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# not the value here, or `flutter run` will no longer work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# 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 +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/packages/celest_core/example/linux/flutter/CMakeLists.txt b/packages/celest_core/example/linux/flutter/CMakeLists.txt new file mode 100644 index 00000000..d5bd0164 --- /dev/null +++ b/packages/celest_core/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/packages/celest_core/example/linux/flutter/generated_plugin_registrant.cc b/packages/celest_core/example/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 00000000..e71a16d2 --- /dev/null +++ b/packages/celest_core/example/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/packages/celest_core/example/linux/flutter/generated_plugin_registrant.h b/packages/celest_core/example/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 00000000..e0f0a47b --- /dev/null +++ b/packages/celest_core/example/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/packages/celest_core/example/linux/flutter/generated_plugins.cmake b/packages/celest_core/example/linux/flutter/generated_plugins.cmake new file mode 100644 index 00000000..be1ee3e5 --- /dev/null +++ b/packages/celest_core/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/packages/celest_core/example/linux/main.cc b/packages/celest_core/example/linux/main.cc new file mode 100644 index 00000000..e7c5c543 --- /dev/null +++ b/packages/celest_core/example/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/packages/celest_core/example/linux/my_application.cc b/packages/celest_core/example/linux/my_application.cc new file mode 100644 index 00000000..d5238c09 --- /dev/null +++ b/packages/celest_core/example/linux/my_application.cc @@ -0,0 +1,124 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "celest_core_example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "celest_core_example"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + 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. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + 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; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/packages/celest_core/example/linux/my_application.h b/packages/celest_core/example/linux/my_application.h new file mode 100644 index 00000000..72271d5e --- /dev/null +++ b/packages/celest_core/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/packages/celest_core/example/macos/.gitignore b/packages/celest_core/example/macos/.gitignore new file mode 100644 index 00000000..746adbb6 --- /dev/null +++ b/packages/celest_core/example/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/packages/celest_core/example/macos/Flutter/Flutter-Debug.xcconfig b/packages/celest_core/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 00000000..4b81f9b2 --- /dev/null +++ b/packages/celest_core/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/celest_core/example/macos/Flutter/Flutter-Release.xcconfig b/packages/celest_core/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 00000000..5caa9d15 --- /dev/null +++ b/packages/celest_core/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/celest_core/example/macos/Flutter/GeneratedPluginRegistrant.swift b/packages/celest_core/example/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 00000000..cccf817a --- /dev/null +++ b/packages/celest_core/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,10 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { +} diff --git a/packages/celest_core/example/macos/Podfile b/packages/celest_core/example/macos/Podfile new file mode 100644 index 00000000..c795730d --- /dev/null +++ b/packages/celest_core/example/macos/Podfile @@ -0,0 +1,43 @@ +platform :osx, '10.14' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/packages/celest_core/example/macos/Podfile.lock b/packages/celest_core/example/macos/Podfile.lock new file mode 100644 index 00000000..58a75c4d --- /dev/null +++ b/packages/celest_core/example/macos/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - FlutterMacOS (1.0.0) + +DEPENDENCIES: + - FlutterMacOS (from `Flutter/ephemeral`) + +EXTERNAL SOURCES: + FlutterMacOS: + :path: Flutter/ephemeral + +SPEC CHECKSUMS: + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + +PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367 + +COCOAPODS: 1.15.0 diff --git a/packages/celest_core/example/macos/Runner.xcodeproj/project.pbxproj b/packages/celest_core/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..2cae1a19 --- /dev/null +++ b/packages/celest_core/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,783 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 4E2E5D240AE18EC4DF61BFA6 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D96E1C1ADB2C4A653235BD3 /* Pods_RunnerTests.framework */; }; + B6DCD5610A3AEF0C8D949E0F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9FB2887E9559348149CFB42 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0692A6874684F4F70639D3EB /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 10B41FD89784B932573AFCB3 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* celest_core_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = celest_core_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 4942F17F9317CC1C9B5DB021 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 6D96E1C1ADB2C4A653235BD3 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + B9FB2887E9559348149CFB42 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E92E4A9C614F0DAF7E299012 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + F3D3016D855EB7DE8BA118A2 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + FC6485A5079A058D1918C05B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4E2E5D240AE18EC4DF61BFA6 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B6DCD5610A3AEF0C8D949E0F /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + 5475FABF5DB9CBE0F25B4757 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* celest_core_example.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + 5475FABF5DB9CBE0F25B4757 /* Pods */ = { + isa = PBXGroup; + children = ( + F3D3016D855EB7DE8BA118A2 /* Pods-Runner.debug.xcconfig */, + 0692A6874684F4F70639D3EB /* Pods-Runner.release.xcconfig */, + FC6485A5079A058D1918C05B /* Pods-Runner.profile.xcconfig */, + E92E4A9C614F0DAF7E299012 /* Pods-RunnerTests.debug.xcconfig */, + 10B41FD89784B932573AFCB3 /* Pods-RunnerTests.release.xcconfig */, + 4942F17F9317CC1C9B5DB021 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + B9FB2887E9559348149CFB42 /* Pods_Runner.framework */, + 6D96E1C1ADB2C4A653235BD3 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + A3F76E354E626BF81CC15A32 /* [CP] Check Pods Manifest.lock */, + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 0E925AB782D37372BFD00672 /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* celest_core_example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 0E925AB782D37372BFD00672 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + A3F76E354E626BF81CC15A32 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E92E4A9C614F0DAF7E299012 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.celest.celestCoreExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/celest_core_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/celest_core_example"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 10B41FD89784B932573AFCB3 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.celest.celestCoreExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/celest_core_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/celest_core_example"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4942F17F9317CC1C9B5DB021 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.celest.celestCoreExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/celest_core_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/celest_core_example"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/packages/celest_core/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/celest_core/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/packages/celest_core/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/celest_core/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/celest_core/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..e2aa1d9c --- /dev/null +++ b/packages/celest_core/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/celest_core/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/packages/celest_core/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/packages/celest_core/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/packages/celest_core/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/celest_core/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/packages/celest_core/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/celest_core/example/macos/Runner/AppDelegate.swift b/packages/celest_core/example/macos/Runner/AppDelegate.swift new file mode 100644 index 00000000..d53ef643 --- /dev/null +++ b/packages/celest_core/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..a2ec33f1 --- /dev/null +++ b/packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..82b6f9d9a33e198f5747104729e1fcef999772a5 GIT binary patch literal 102994 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ⅅ8MglG&ER{i5lN315cO?EdHNLrg? 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 z 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 Pe7HEdAEg|=c=LY&YVNkY literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..13b35eba55c6dabc3aac36f33d859266c18fa0d0 GIT binary patch literal 5680 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 literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000000000000000000000000000000000000..0a3f5fa40fb3d1e0710331a48de5d256da3f275d GIT binary patch literal 520 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 literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/packages/celest_core/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000000000000000000000000000000000000..2f1632cfddf3d9dade342351e627a0a75609fb46 GIT binary patch literal 2218 zcmV;b2vzrqP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91K%fHv1ONa40RR91KmY&$07g+lumAuE6iGxuRCodHTWf3-RTMruyW6Fu zQYeUM04eX6D5c0FCjKKPrco1(K`<0SL=crI{PC3-^hZU0kQie$gh-5!7z6SH6Q0J% zqot*`H1q{R5fHFYS}dje@;kG=v$L0(yY0?wY2%*c?A&{2?!D*x?m71{of2gv!$5|C z3>qG_BW}7K_yUcT3A5C6QD<+{aq?x;MAUyAiJn#Jv8_zZtQ{P zTRzbL3U9!qVuZzS$xKU10KiW~Bgdcv1-!uAhQxf3a7q+dU6lj?yoO4Lq4TUN4}h{N z*fIM=SS8|C2$(T>w$`t@3Tka!(r!7W`x z-isCVgQD^mG-MJ;XtJuK3V{Vy72GQ83KRWsHU?e*wrhKk=ApIYeDqLi;JI1e zuvv}5^Dc=k7F7?nm3nIw$NVmU-+R>> zyqOR$-2SDpJ}Pt;^RkJytDVXNTsu|mI1`~G7yw`EJR?VkGfNdqK9^^8P`JdtTV&tX4CNcV4 z&N06nZa??Fw1AgQOUSE2AmPE@WO(Fvo`%m`cDgiv(fAeRA%3AGXUbsGw{7Q`cY;1BI#ac3iN$$Hw z0LT0;xc%=q)me?Y*$xI@GRAw?+}>=9D+KTk??-HJ4=A>`V&vKFS75@MKdSF1JTq{S zc1!^8?YA|t+uKigaq!sT;Z!&0F2=k7F0PIU;F$leJLaw2UI6FL^w}OG&!;+b%ya1c z1n+6-inU<0VM-Y_s5iTElq)ThyF?StVcebpGI znw#+zLx2@ah{$_2jn+@}(zJZ{+}_N9BM;z)0yr|gF-4=Iyu@hI*Lk=-A8f#bAzc9f z`Kd6K--x@t04swJVC3JK1cHY-Hq+=|PN-VO;?^_C#;coU6TDP7Bt`;{JTG;!+jj(` zw5cLQ-(Cz-Tlb`A^w7|R56Ce;Wmr0)$KWOUZ6ai0PhzPeHwdl0H(etP zUV`va_i0s-4#DkNM8lUlqI7>YQLf)(lz9Q3Uw`)nc(z3{m5ZE77Ul$V%m)E}3&8L0 z-XaU|eB~Is08eORPk;=<>!1w)Kf}FOVS2l&9~A+@R#koFJ$Czd%Y(ENTV&A~U(IPI z;UY+gf+&6ioZ=roly<0Yst8ck>(M=S?B-ys3mLdM&)ex!hbt+ol|T6CTS+Sc0jv(& z7ijdvFwBq;0a{%3GGwkDKTeG`b+lyj0jjS1OMkYnepCdoosNY`*zmBIo*981BU%%U z@~$z0V`OVtIbEx5pa|Tct|Lg#ZQf5OYMUMRD>Wdxm5SAqV2}3!ceE-M2 z@O~lQ0OiKQp}o9I;?uxCgYVV?FH|?Riri*U$Zi_`V2eiA>l zdSm6;SEm6#T+SpcE8Ro_f2AwxzI z44hfe^WE3!h@W3RDyA_H440cpmYkv*)6m1XazTqw%=E5Xv7^@^^T7Q2wxr+Z2kVYr + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/celest_core/example/macos/Runner/Configs/AppInfo.xcconfig b/packages/celest_core/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 00000000..2cca0fe2 --- /dev/null +++ b/packages/celest_core/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = celest_core_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = dev.celest.celestCoreExample + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2024 dev.celest. All rights reserved. diff --git a/packages/celest_core/example/macos/Runner/Configs/Debug.xcconfig b/packages/celest_core/example/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 00000000..36b0fd94 --- /dev/null +++ b/packages/celest_core/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/packages/celest_core/example/macos/Runner/Configs/Release.xcconfig b/packages/celest_core/example/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 00000000..dff4f495 --- /dev/null +++ b/packages/celest_core/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/packages/celest_core/example/macos/Runner/Configs/Warnings.xcconfig b/packages/celest_core/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 00000000..42bcbf47 --- /dev/null +++ b/packages/celest_core/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/packages/celest_core/example/macos/Runner/DebugProfile.entitlements b/packages/celest_core/example/macos/Runner/DebugProfile.entitlements new file mode 100644 index 00000000..dddb8a30 --- /dev/null +++ b/packages/celest_core/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/packages/celest_core/example/macos/Runner/Info.plist b/packages/celest_core/example/macos/Runner/Info.plist new file mode 100644 index 00000000..4789daa6 --- /dev/null +++ b/packages/celest_core/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/packages/celest_core/example/macos/Runner/MainFlutterWindow.swift b/packages/celest_core/example/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 00000000..3cc05eb2 --- /dev/null +++ b/packages/celest_core/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/packages/celest_core/example/macos/Runner/Release.entitlements b/packages/celest_core/example/macos/Runner/Release.entitlements new file mode 100644 index 00000000..852fa1a4 --- /dev/null +++ b/packages/celest_core/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/packages/celest_core/example/macos/RunnerTests/RunnerTests.swift b/packages/celest_core/example/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 00000000..5418c9f5 --- /dev/null +++ b/packages/celest_core/example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/packages/celest_core/example/main.dart b/packages/celest_core/example/main.dart deleted file mode 100644 index a73180d8..00000000 --- a/packages/celest_core/example/main.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:celest_core/celest_core.dart'; - -void main() { - Serializers.instance.put(const MyClassSerializer()); - final serialized = Serializers.instance.serialize(MyClass('Celest')); - print('Serialized: $serialized'); - final deserialized = Serializers.instance.deserialize(serialized); - print('Deserialized: $deserialized'); -} - -final class MyClass { - const MyClass(this.name); - - final String name; - - @override - String toString() => 'MyClass(name: $name)'; -} - -final class MyClassSerializer extends Serializer { - const MyClassSerializer(); - - @override - MyClass deserialize(Object? value) { - final map = assertWireType>(value); - return MyClass(map['name'] as String); - } - - @override - Object? serialize(MyClass value) => {'name': value.name}; -} diff --git a/packages/celest_core/example/pubspec.yaml b/packages/celest_core/example/pubspec.yaml new file mode 100644 index 00000000..68821f89 --- /dev/null +++ b/packages/celest_core/example/pubspec.yaml @@ -0,0 +1,24 @@ +name: celest_core_example +description: "A new Flutter project." +publish_to: 'none' +version: 0.1.0 + +environment: + sdk: '>=3.3.0 <4.0.0' + +dependencies: + celest_core: + path: ../ + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^3.0.0 + integration_test: + sdk: flutter + test: ^1.24.9 + +flutter: + uses-material-design: true diff --git a/packages/celest_core/example/test_driver/integration_test.dart b/packages/celest_core/example/test_driver/integration_test.dart new file mode 100644 index 00000000..01a82181 --- /dev/null +++ b/packages/celest_core/example/test_driver/integration_test.dart @@ -0,0 +1,5 @@ +import 'package:integration_test/integration_test_driver.dart'; + +// Required for running integration tests in the browser +// https://docs.flutter.dev/cookbook/testing/integration/introduction#5b-web +Future main() => integrationDriver(); diff --git a/packages/celest_core/example/web/favicon.png b/packages/celest_core/example/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/web/icons/Icon-192.png b/packages/celest_core/example/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/web/icons/Icon-512.png b/packages/celest_core/example/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/web/icons/Icon-maskable-192.png b/packages/celest_core/example/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9b4d76e525556d5d89141648c724331630325d GIT binary patch literal 5594 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 X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/web/icons/Icon-maskable-512.png b/packages/celest_core/example/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..d69c56691fbdb0b7efa65097c7cc1edac12a6d3e GIT binary patch literal 20998 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 MPgg&ebxsLQ025IeI{*Lx literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/web/index.html b/packages/celest_core/example/web/index.html new file mode 100644 index 00000000..3b2eec85 --- /dev/null +++ b/packages/celest_core/example/web/index.html @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + celest_core_example + + + + + + + + + + diff --git a/packages/celest_core/example/web/manifest.json b/packages/celest_core/example/web/manifest.json new file mode 100644 index 00000000..3521aad0 --- /dev/null +++ b/packages/celest_core/example/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "celest_core_example", + "short_name": "celest_core_example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/packages/celest_core/example/windows/.gitignore b/packages/celest_core/example/windows/.gitignore new file mode 100644 index 00000000..d492d0d9 --- /dev/null +++ b/packages/celest_core/example/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/packages/celest_core/example/windows/CMakeLists.txt b/packages/celest_core/example/windows/CMakeLists.txt new file mode 100644 index 00000000..ae39ba61 --- /dev/null +++ b/packages/celest_core/example/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(celest_core_example LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "celest_core_example") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +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 +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/packages/celest_core/example/windows/flutter/CMakeLists.txt b/packages/celest_core/example/windows/flutter/CMakeLists.txt new file mode 100644 index 00000000..903f4899 --- /dev/null +++ b/packages/celest_core/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/packages/celest_core/example/windows/flutter/generated_plugin_registrant.cc b/packages/celest_core/example/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 00000000..8b6d4680 --- /dev/null +++ b/packages/celest_core/example/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void RegisterPlugins(flutter::PluginRegistry* registry) { +} diff --git a/packages/celest_core/example/windows/flutter/generated_plugin_registrant.h b/packages/celest_core/example/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 00000000..dc139d85 --- /dev/null +++ b/packages/celest_core/example/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/packages/celest_core/example/windows/flutter/generated_plugins.cmake b/packages/celest_core/example/windows/flutter/generated_plugins.cmake new file mode 100644 index 00000000..3ad69c61 --- /dev/null +++ b/packages/celest_core/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/packages/celest_core/example/windows/runner/CMakeLists.txt b/packages/celest_core/example/windows/runner/CMakeLists.txt new file mode 100644 index 00000000..394917c0 --- /dev/null +++ b/packages/celest_core/example/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/packages/celest_core/example/windows/runner/Runner.rc b/packages/celest_core/example/windows/runner/Runner.rc new file mode 100644 index 00000000..3099af81 --- /dev/null +++ b/packages/celest_core/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "dev.celest" "\0" + VALUE "FileDescription", "celest_core_example" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "celest_core_example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2024 dev.celest. All rights reserved." "\0" + VALUE "OriginalFilename", "celest_core_example.exe" "\0" + VALUE "ProductName", "celest_core_example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/packages/celest_core/example/windows/runner/flutter_window.cpp b/packages/celest_core/example/windows/runner/flutter_window.cpp new file mode 100644 index 00000000..955ee303 --- /dev/null +++ b/packages/celest_core/example/windows/runner/flutter_window.cpp @@ -0,0 +1,71 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/packages/celest_core/example/windows/runner/flutter_window.h b/packages/celest_core/example/windows/runner/flutter_window.h new file mode 100644 index 00000000..6da0652f --- /dev/null +++ b/packages/celest_core/example/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/packages/celest_core/example/windows/runner/main.cpp b/packages/celest_core/example/windows/runner/main.cpp new file mode 100644 index 00000000..6e88cb85 --- /dev/null +++ b/packages/celest_core/example/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"celest_core_example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/packages/celest_core/example/windows/runner/resource.h b/packages/celest_core/example/windows/runner/resource.h new file mode 100644 index 00000000..66a65d1e --- /dev/null +++ b/packages/celest_core/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/packages/celest_core/example/windows/runner/resources/app_icon.ico b/packages/celest_core/example/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04e20caf6370ebb9253ad831cc31de4a9c965f6 GIT binary patch literal 33772 zcmeHQc|26z|35SKE&G-*mXah&B~fFkXr)DEO&hIfqby^T&>|8^_Ub8Vp#`BLl3lbZ zvPO!8k!2X>cg~Elr=IVxo~J*a`+9wR=A83c-k-DFd(XM&UI1VKCqM@V;DDtJ09WB} zRaHKiW(GT00brH|0EeTeKVbpbGZg?nK6-j827q-+NFM34gXjqWxJ*a#{b_apGN<-L_m3#8Z26atkEn& ze87Bvv^6vVmM+p+cQ~{u%=NJF>#(d;8{7Q{^rWKWNtf14H}>#&y7$lqmY6xmZryI& z($uy?c5-+cPnt2%)R&(KIWEXww>Cnz{OUpT>W$CbO$h1= z#4BPMkFG1Y)x}Ui+WXr?Z!w!t_hjRq8qTaWpu}FH{MsHlU{>;08goVLm{V<&`itk~ zE_Ys=D(hjiy+5=?=$HGii=Y5)jMe9|wWoD_K07(}edAxh`~LBorOJ!Cf@f{_gNCC| z%{*04ViE!#>@hc1t5bb+NO>ncf@@Dv01K!NxH$3Eg1%)|wLyMDF8^d44lV!_Sr}iEWefOaL z8f?ud3Q%Sen39u|%00W<#!E=-RpGa+H8}{ulxVl4mwpjaU+%2pzmi{3HM)%8vb*~-M9rPUAfGCSos8GUXp02|o~0BTV2l#`>>aFV&_P$ejS;nGwSVP8 zMbOaG7<7eKD>c12VdGH;?2@q7535sa7MN*L@&!m?L`ASG%boY7(&L5imY#EQ$KrBB z4@_tfP5m50(T--qv1BJcD&aiH#b-QC>8#7Fx@3yXlonJI#aEIi=8&ChiVpc#N=5le zM*?rDIdcpawoc5kizv$GEjnveyrp3sY>+5_R5;>`>erS%JolimF=A^EIsAK zsPoVyyUHCgf0aYr&alx`<)eb6Be$m&`JYSuBu=p8j%QlNNp$-5C{b4#RubPb|CAIS zGE=9OFLP7?Hgc{?k45)84biT0k&-C6C%Q}aI~q<(7BL`C#<6HyxaR%!dFx7*o^laG z=!GBF^cwK$IA(sn9y6>60Rw{mYRYkp%$jH z*xQM~+bp)G$_RhtFPYx2HTsWk80+p(uqv9@I9)y{b$7NK53rYL$ezbmRjdXS?V}fj zWxX_feWoLFNm3MG7pMUuFPs$qrQWO9!l2B(SIuy2}S|lHNbHzoE+M2|Zxhjq9+Ws8c{*}x^VAib7SbxJ*Q3EnY5lgI9 z=U^f3IW6T=TWaVj+2N%K3<%Un;CF(wUp`TC&Y|ZjyFu6co^uqDDB#EP?DV5v_dw~E zIRK*BoY9y-G_ToU2V_XCX4nJ32~`czdjT!zwme zGgJ0nOk3U4@IE5JwtM}pwimLjk{ln^*4HMU%Fl4~n(cnsLB}Ja-jUM>xIB%aY;Nq8 z)Fp8dv1tkqKanv<68o@cN|%thj$+f;zGSO7H#b+eMAV8xH$hLggtt?O?;oYEgbq@= zV(u9bbd12^%;?nyk6&$GPI%|+<_mEpJGNfl*`!KV;VfmZWw{n{rnZ51?}FDh8we_L z8OI9nE31skDqJ5Oa_ybn7|5@ui>aC`s34p4ZEu6-s!%{uU45$Zd1=p$^^dZBh zu<*pDDPLW+c>iWO$&Z_*{VSQKg7=YEpS3PssPn1U!lSm6eZIho*{@&20e4Y_lRklKDTUCKI%o4Pc<|G^Xgu$J^Q|B87U;`c1zGwf^-zH*VQ^x+i^OUWE0yd z;{FJq)2w!%`x7yg@>uGFFf-XJl4H`YtUG%0slGKOlXV`q?RP>AEWg#x!b{0RicxGhS!3$p7 zij;{gm!_u@D4$Ox%>>bPtLJ> zwKtYz?T_DR1jN>DkkfGU^<#6sGz|~p*I{y`aZ>^Di#TC|Z!7j_O1=Wo8thuit?WxR zh9_S>kw^{V^|g}HRUF=dcq>?q(pHxw!8rx4dC6vbQVmIhmICF#zU!HkHpQ>9S%Uo( zMw{eC+`&pb=GZRou|3;Po1}m46H6NGd$t<2mQh}kaK-WFfmj_66_17BX0|j-E2fe3Jat}ijpc53 zJV$$;PC<5aW`{*^Z6e5##^`Ed#a0nwJDT#Qq~^e8^JTA=z^Kl>La|(UQ!bI@#ge{Dzz@61p-I)kc2?ZxFt^QQ}f%ldLjO*GPj(5)V9IyuUakJX=~GnTgZ4$5!3E=V#t`yOG4U z(gphZB6u2zsj=qNFLYShhg$}lNpO`P9xOSnO*$@@UdMYES*{jJVj|9z-}F^riksLK zbsU+4-{281P9e2UjY6tse^&a)WM1MFw;p#_dHhWI7p&U*9TR0zKdVuQed%6{otTsq z$f~S!;wg#Bd9kez=Br{m|66Wv z#g1xMup<0)H;c2ZO6su_ii&m8j&+jJz4iKnGZ&wxoQX|5a>v&_e#6WA!MB_4asTxLRGQCC5cI(em z%$ZfeqP>!*q5kU>a+BO&ln=4Jm>Ef(QE8o&RgLkk%2}4Tf}U%IFP&uS7}&|Q-)`5< z+e>;s#4cJ-z%&-^&!xsYx777Wt(wZY9(3(avmr|gRe4cD+a8&!LY`1^T?7x{E<=kdY9NYw>A;FtTvQ=Y&1M%lyZPl$ss1oY^Sl8we}n}Aob#6 zl4jERwnt9BlSoWb@3HxYgga(752Vu6Y)k4yk9u~Kw>cA5&LHcrvn1Y-HoIuFWg~}4 zEw4bR`mXZQIyOAzo)FYqg?$5W<;^+XX%Uz61{-L6@eP|lLH%|w?g=rFc;OvEW;^qh z&iYXGhVt(G-q<+_j}CTbPS_=K>RKN0&;dubh0NxJyDOHFF;<1k!{k#7b{|Qok9hac z;gHz}6>H6C6RnB`Tt#oaSrX0p-j-oRJ;_WvS-qS--P*8}V943RT6kou-G=A+7QPGQ z!ze^UGxtW3FC0$|(lY9^L!Lx^?Q8cny(rR`es5U;-xBhphF%_WNu|aO<+e9%6LuZq zt(0PoagJG<%hyuf;te}n+qIl_Ej;czWdc{LX^pS>77s9t*2b4s5dvP_!L^3cwlc)E!(!kGrg~FescVT zZCLeua3f4;d;Tk4iXzt}g}O@nlK3?_o91_~@UMIl?@77Qc$IAlLE95#Z=TES>2E%z zxUKpK{_HvGF;5%Q7n&vA?`{%8ohlYT_?(3A$cZSi)MvIJygXD}TS-3UwyUxGLGiJP znblO~G|*uA^|ac8E-w#}uBtg|s_~s&t>-g0X%zIZ@;o_wNMr_;{KDg^O=rg`fhDZu zFp(VKd1Edj%F zWHPl+)FGj%J1BO3bOHVfH^3d1F{)*PL&sRX`~(-Zy3&9UQX)Z;c51tvaI2E*E7!)q zcz|{vpK7bjxix(k&6=OEIBJC!9lTkUbgg?4-yE{9+pFS)$Ar@vrIf`D0Bnsed(Cf? zObt2CJ>BKOl>q8PyFO6w)+6Iz`LW%T5^R`U_NIW0r1dWv6OY=TVF?N=EfA(k(~7VBW(S;Tu5m4Lg8emDG-(mOSSs=M9Q&N8jc^Y4&9RqIsk(yO_P(mcCr}rCs%1MW1VBrn=0-oQN(Xj!k%iKV zb%ricBF3G4S1;+8lzg5PbZ|$Se$)I=PwiK=cDpHYdov2QO1_a-*dL4KUi|g&oh>(* zq$<`dQ^fat`+VW?m)?_KLn&mp^-@d=&7yGDt<=XwZZC=1scwxO2^RRI7n@g-1o8ps z)&+et_~)vr8aIF1VY1Qrq~Xe``KJrQSnAZ{CSq3yP;V*JC;mmCT6oRLSs7=GA?@6g zUooM}@tKtx(^|aKK8vbaHlUQqwE0}>j&~YlN3H#vKGm@u)xxS?n9XrOWUfCRa< z`20Fld2f&;gg7zpo{Adh+mqNntMc-D$N^yWZAZRI+u1T1zWHPxk{+?vcS1D>08>@6 zLhE@`gt1Y9mAK6Z4p|u(5I%EkfU7rKFSM=E4?VG9tI;a*@?6!ey{lzN5=Y-!$WFSe z&2dtO>^0@V4WRc#L&P%R(?@KfSblMS+N+?xUN$u3K4Ys%OmEh+tq}fnU}i>6YHM?< zlnL2gl~sF!j!Y4E;j3eIU-lfa`RsOL*Tt<%EFC0gPzoHfNWAfKFIKZN8}w~(Yi~=q z>=VNLO2|CjkxP}RkutxjV#4fWYR1KNrPYq5ha9Wl+u>ipsk*I(HS@iLnmGH9MFlTU zaFZ*KSR0px>o+pL7BbhB2EC1%PJ{67_ z#kY&#O4@P=OV#-79y_W>Gv2dxL*@G7%LksNSqgId9v;2xJ zrh8uR!F-eU$NMx@S*+sk=C~Dxr9Qn7TfWnTupuHKuQ$;gGiBcU>GF5sWx(~4IP3`f zWE;YFO*?jGwYh%C3X<>RKHC-DZ!*r;cIr}GLOno^3U4tFSSoJp%oHPiSa%nh=Zgn% z14+8v@ygy0>UgEN1bczD6wK45%M>psM)y^)IfG*>3ItX|TzV*0i%@>L(VN!zdKb8S?Qf7BhjNpziA zR}?={-eu>9JDcl*R=OP9B8N$IcCETXah9SUDhr{yrld{G;PnCWRsPD7!eOOFBTWUQ=LrA_~)mFf&!zJX!Oc-_=kT<}m|K52 z)M=G#;p;Rdb@~h5D{q^K;^fX-m5V}L%!wVC2iZ1uu401Ll}#rocTeK|7FAeBRhNdQ zCc2d^aQnQp=MpOmak60N$OgS}a;p(l9CL`o4r(e-nN}mQ?M&isv-P&d$!8|1D1I(3-z!wi zTgoo)*Mv`gC?~bm?S|@}I|m-E2yqPEvYybiD5azInexpK8?9q*$9Yy9-t%5jU8~ym zgZDx>!@ujQ=|HJnwp^wv-FdD{RtzO9SnyfB{mH_(c!jHL*$>0o-(h(eqe*ZwF6Lvu z{7rkk%PEqaA>o+f{H02tzZ@TWy&su?VNw43! z-X+rN`6llvpUms3ZiSt)JMeztB~>9{J8SPmYs&qohxdYFi!ra8KR$35Zp9oR)eFC4 zE;P31#3V)n`w$fZ|4X-|%MX`xZDM~gJyl2W;O$H25*=+1S#%|53>|LyH za@yh+;325%Gq3;J&a)?%7X%t@WXcWL*BaaR*7UEZad4I8iDt7^R_Fd`XeUo256;sAo2F!HcIQKk;h})QxEsPE5BcKc7WyerTchgKmrfRX z!x#H_%cL#B9TWAqkA4I$R^8{%do3Y*&(;WFmJ zU7Dih{t1<{($VtJRl9|&EB?|cJ)xse!;}>6mSO$o5XIx@V|AA8ZcoD88ZM?C*;{|f zZVmf94_l1OmaICt`2sTyG!$^UeTHx9YuUP!omj(r|7zpm5475|yXI=rR>>fteLI+| z)MoiGho0oEt=*J(;?VY0QzwCqw@cVm?d7Y!z0A@u#H?sCJ*ecvyhj& z-F77lO;SH^dmf?L>3i>?Z*U}Em4ZYV_CjgfvzYsRZ+1B!Uo6H6mbS<-FFL`ytqvb& zE7+)2ahv-~dz(Hs+f})z{*4|{)b=2!RZK;PWwOnO=hG7xG`JU5>bAvUbdYd_CjvtHBHgtGdlO+s^9ca^Bv3`t@VRX2_AD$Ckg36OcQRF zXD6QtGfHdw*hx~V(MV-;;ZZF#dJ-piEF+s27z4X1qi5$!o~xBnvf=uopcn7ftfsZc zy@(PuOk`4GL_n(H9(E2)VUjqRCk9kR?w)v@xO6Jm_Mx})&WGEl=GS0#)0FAq^J*o! zAClhvoTsNP*-b~rN{8Yym3g{01}Ep^^Omf=SKqvN?{Q*C4HNNAcrowIa^mf+3PRy! z*_G-|3i8a;+q;iP@~Of_$(vtFkB8yOyWt2*K)vAn9El>=D;A$CEx6b*XF@4y_6M+2 zpeW`RHoI_p(B{%(&jTHI->hmNmZjHUj<@;7w0mx3&koy!2$@cfX{sN19Y}euYJFn& z1?)+?HCkD0MRI$~uB2UWri})0bru_B;klFdwsLc!ne4YUE;t41JqfG# zZJq6%vbsdx!wYeE<~?>o4V`A3?lN%MnKQ`z=uUivQN^vzJ|C;sdQ37Qn?;lpzg})y z)_2~rUdH}zNwX;Tp0tJ78+&I=IwOQ-fl30R79O8@?Ub8IIA(6I`yHn%lARVL`%b8+ z4$8D-|MZZWxc_)vu6@VZN!HsI$*2NOV&uMxBNzIbRgy%ob_ zhwEH{J9r$!dEix9XM7n&c{S(h>nGm?el;gaX0@|QnzFD@bne`el^CO$yXC?BDJ|Qg z+y$GRoR`?ST1z^e*>;!IS@5Ovb7*RlN>BV_UC!7E_F;N#ky%1J{+iixp(dUJj93aK zzHNN>R-oN7>kykHClPnoPTIj7zc6KM(Pnlb(|s??)SMb)4!sMHU^-ntJwY5Big7xv zb1Ew`Xj;|D2kzGja*C$eS44(d&RMU~c_Y14V9_TLTz0J#uHlsx`S6{nhsA0dWZ#cG zJ?`fO50E>*X4TQLv#nl%3GOk*UkAgt=IY+u0LNXqeln3Z zv$~&Li`ZJOKkFuS)dJRA>)b_Da%Q~axwA_8zNK{BH{#}#m}zGcuckz}riDE-z_Ms> zR8-EqAMcfyGJCtvTpaUVQtajhUS%c@Yj}&6Zz;-M7MZzqv3kA7{SuW$oW#=0az2wQ zg-WG@Vb4|D`pl~Il54N7Hmsauc_ne-a!o5#j3WaBBh@Wuefb!QJIOn5;d)%A#s+5% zuD$H=VNux9bE-}1&bcYGZ+>1Fo;3Z@e&zX^n!?JK*adSbONm$XW9z;Q^L>9U!}Toj2WdafJ%oL#h|yWWwyAGxzfrAWdDTtaKl zK4`5tDpPg5>z$MNv=X0LZ0d6l%D{(D8oT@+w0?ce$DZ6pv>{1&Ok67Ix1 zH}3=IEhPJEhItCC8E=`T`N5(k?G=B4+xzZ?<4!~ ze~z6Wk9!CHTI(0rLJ4{JU?E-puc;xusR?>G?;4vt;q~iI9=kDL=z0Rr%O$vU`30X$ zDZRFyZ`(omOy@u|i6h;wtJlP;+}$|Ak|k2dea7n?U1*$T!sXqqOjq^NxLPMmk~&qI zYg0W?yK8T(6+Ea+$YyspKK?kP$+B`~t3^Pib_`!6xCs32!i@pqXfFV6PmBIR<-QW= zN8L{pt0Vap0x`Gzn#E@zh@H)0FfVfA_Iu4fjYZ+umO1LXIbVc$pY+E234u)ttcrl$ z>s92z4vT%n6cMb>=XT6;l0+9e(|CZG)$@C7t7Z7Ez@a)h)!hyuV&B5K%%)P5?Lk|C zZZSVzdXp{@OXSP0hoU-gF8s8Um(#xzjP2Vem zec#-^JqTa&Y#QJ>-FBxd7tf`XB6e^JPUgagB8iBSEps;92KG`!#mvVcPQ5yNC-GEG zTiHEDYfH+0O15}r^+ z#jxj=@x8iNHWALe!P3R67TwmhItn**0JwnzSV2O&KE8KcT+0hWH^OPD1pwiuyx=b@ zNf5Jh0{9X)8;~Es)$t@%(3!OnbY+`@?i{mGX7Yy}8T_*0a6g;kaFPq;*=px5EhO{Cp%1kI<0?*|h8v!6WnO3cCJRF2-CRrU3JiLJnj@6;L)!0kWYAc_}F{2P))3HmCrz zQ&N&gE70;`!6*eJ4^1IR{f6j4(-l&X!tjHxkbHA^Zhrnhr9g{exN|xrS`5Pq=#Xf& zG%P=#ra-TyVFfgW%cZo5OSIwFL9WtXAlFOa+ubmI5t*3=g#Y zF%;70p5;{ZeFL}&}yOY1N1*Q;*<(kTB!7vM$QokF)yr2FlIU@$Ph58$Bz z0J?xQG=MlS4L6jA22eS42g|9*9pX@$#*sUeM(z+t?hr@r5J&D1rx}2pW&m*_`VDCW zUYY@v-;bAO0HqoAgbbiGGC<=ryf96}3pouhy3XJrX+!!u*O_>Si38V{uJmQ&USptX zKp#l(?>%^7;2%h(q@YWS#9;a!JhKlkR#Vd)ERILlgu!Hr@jA@V;sk4BJ-H#p*4EqC zDGjC*tl=@3Oi6)Bn^QwFpul18fpkbpg0+peH$xyPBqb%`$OUhPKyWb32o7clB*9Z< zN=i~NLjavrLtwgJ01bufP+>p-jR2I95|TpmKpQL2!oV>g(4RvS2pK4*ou%m(h6r3A zX#s&`9LU1ZG&;{CkOK!4fLDTnBys`M!vuz>Q&9OZ0hGQl!~!jSDg|~s*w52opC{sB ze|Cf2luD(*G13LcOAGA!s2FjSK8&IE5#W%J25w!vM0^VyQM!t)inj&RTiJ!wXzFgz z3^IqzB7I0L$llljsGq})thBy9UOyjtFO_*hYM_sgcMk>44jeH0V1FDyELc{S1F-;A zS;T^k^~4biG&V*Irq}O;e}j$$+E_#G?HKIn05iP3j|87TkGK~SqG!-KBg5+mN(aLm z8ybhIM`%C19UX$H$KY6JgXbY$0AT%rEpHC;u`rQ$Y=rxUdsc5*Kvc8jaYaO$^)cI6){P6K0r)I6DY4Wr4&B zLQUBraey#0HV|&c4v7PVo3n$zHj99(TZO^3?Ly%C4nYvJTL9eLBLHsM3WKKD>5!B` zQ=BsR3aR6PD(Fa>327E2HAu5TM~Wusc!)>~(gM)+3~m;92Jd;FnSib=M5d6;;5{%R zb4V7DEJ0V!CP-F*oU?gkc>ksUtAYP&V4ND5J>J2^jt*vcFflQWCrB&fLdT%O59PVJ zhid#toR=FNgD!q3&r8#wEBr`!wzvQu5zX?Q>nlSJ4i@WC*CN*-xU66F^V5crWevQ9gsq$I@z1o(a=k7LL~ z7m_~`o;_Ozha1$8Q}{WBehvAlO4EL60y5}8GDrZ< zXh&F}71JbW2A~8KfEWj&UWV#4+Z4p`b{uAj4&WC zha`}X@3~+Iz^WRlOHU&KngK>#j}+_o@LdBC1H-`gT+krWX3-;!)6?{FBp~%20a}FL zFP9%Emqcwa#(`=G>BBZ0qZDQhmZKJg_g8<=bBFKWr!dyg(YkpE+|R*SGpDVU!+VlU zFC54^DLv}`qa%49T>nNiA9Q7Ips#!Xx90tCU2gvK`(F+GPcL=J^>No{)~we#o@&mUb6c$ zCc*<|NJBk-#+{j9xkQ&ujB zI~`#kN~7W!f*-}wkG~Ld!JqZ@tK}eeSnsS5J1fMFXm|`LJx&}5`@dK3W^7#Wnm+_P zBZkp&j1fa2Y=eIjJ0}gh85jt43kaIXXv?xmo@eHrka!Z|vQv12HN#+!I5E z`(fbuW>gFiJL|uXJ!vKt#z3e3HlVdboH7;e#i3(2<)Fg-I@BR!qY#eof3MFZ&*Y@l zI|KJf&ge@p2Dq09Vu$$Qxb7!}{m-iRk@!)%KL)txi3;~Z4Pb}u@GsW;ELiWeG9V51 znX#}B&4Y2E7-H=OpNE@q{%hFLxwIpBF2t{vPREa8_{linXT;#1vMRWjOzLOP$-hf( z>=?$0;~~PnkqY;~K{EM6Vo-T(0K{A0}VUGmu*hR z{tw3hvBN%N3G3Yw`X5Te+F{J`(3w1s3-+1EbnFQKcrgrX1Jqvs@ADGe%M0s$EbK$$ zK)=y=upBc6SjGYAACCcI=Y*6Fi8_jgwZlLxD26fnQfJmb8^gHRN5(TemhX@0e=vr> zg`W}6U>x6VhoA3DqsGGD9uL1DhB3!OXO=k}59TqD@(0Nb{)Ut_luTioK_>7wjc!5C zIr@w}b`Fez3)0wQfKl&bae7;PcTA7%?f2xucM0G)wt_KO!Ewx>F~;=BI0j=Fb4>pp zv}0R^xM4eti~+^+gE$6b81p(kwzuDti(-K9bc|?+pJEl@H+jSYuxZQV8rl8 zjp@M{#%qItIUFN~KcO9Hed*`$5A-2~pAo~K&<-Q+`9`$CK>rzqAI4w~$F%vs9s{~x zg4BP%Gy*@m?;D6=SRX?888Q6peF@_4Z->8wAH~Cn!R$|Hhq2cIzFYqT_+cDourHbY z0qroxJnrZ4Gh+Ay+F`_c%+KRT>y3qw{)89?=hJ@=KO=@ep)aBJ$c!JHfBMJpsP*3G za7|)VJJ8B;4?n{~ldJF7%jmb`-ftIvNd~ekoufG(`K(3=LNc;HBY& z(lp#q8XAD#cIf}k49zX_i`*fO+#!zKA&%T3j@%)R+#yag067CU%yUEe47>wzGU8^` z1EXFT^@I!{J!F8!X?S6ph8J=gUi5tl93*W>7}_uR<2N2~e}FaG?}KPyugQ=-OGEZs z!GBoyYY+H*ANn4?Z)X4l+7H%`17i5~zRlRIX?t)6_eu=g2Q`3WBhxSUeea+M-S?RL zX9oBGKn%a!H+*hx4d2(I!gsi+@SQK%<{X22M~2tMulJoa)0*+z9=-YO+;DFEm5eE1U9b^B(Z}2^9!Qk`!A$wUE z7$Ar5?NRg2&G!AZqnmE64eh^Anss3i!{}%6@Et+4rr!=}!SBF8eZ2*J3ujCWbl;3; z48H~goPSv(8X61fKKdpP!Z7$88NL^Z?j`!^*I?-P4X^pMxyWz~@$(UeAcTSDd(`vO z{~rc;9|GfMJcApU3k}22a!&)k4{CU!e_ny^Y3cO;tOvOMKEyWz!vG(Kp*;hB?d|R3`2X~=5a6#^o5@qn?J-bI8Ppip{-yG z!k|VcGsq!jF~}7DMr49Wap-s&>o=U^T0!Lcy}!(bhtYsPQy z4|EJe{12QL#=c(suQ89Mhw9<`bui%nx7Nep`C&*M3~vMEACmcRYYRGtANq$F%zh&V zc)cEVeHz*Z1N)L7k-(k3np#{GcDh2Q@ya0YHl*n7fl*ZPAsbU-a94MYYtA#&!c`xGIaV;yzsmrjfieTEtqB_WgZp2*NplHx=$O{M~2#i_vJ{ps-NgK zQsxKK_CBM2PP_je+Xft`(vYfXXgIUr{=PA=7a8`2EHk)Ym2QKIforz# tySWtj{oF3N9@_;i*Fv5S)9x^z=nlWP>jpp-9)52ZmLVA=i*%6g{{fxOO~wEK literal 0 HcmV?d00001 diff --git a/packages/celest_core/example/windows/runner/runner.exe.manifest b/packages/celest_core/example/windows/runner/runner.exe.manifest new file mode 100644 index 00000000..a42ea768 --- /dev/null +++ b/packages/celest_core/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/packages/celest_core/example/windows/runner/utils.cpp b/packages/celest_core/example/windows/runner/utils.cpp new file mode 100644 index 00000000..b2b08734 --- /dev/null +++ b/packages/celest_core/example/windows/runner/utils.cpp @@ -0,0 +1,65 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length <= 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + input_length, utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/packages/celest_core/example/windows/runner/utils.h b/packages/celest_core/example/windows/runner/utils.h new file mode 100644 index 00000000..3879d547 --- /dev/null +++ b/packages/celest_core/example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/packages/celest_core/example/windows/runner/win32_window.cpp b/packages/celest_core/example/windows/runner/win32_window.cpp new file mode 100644 index 00000000..60608d0f --- /dev/null +++ b/packages/celest_core/example/windows/runner/win32_window.cpp @@ -0,0 +1,288 @@ +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/packages/celest_core/example/windows/runner/win32_window.h b/packages/celest_core/example/windows/runner/win32_window.h new file mode 100644 index 00000000..e901dde6 --- /dev/null +++ b/packages/celest_core/example/windows/runner/win32_window.h @@ -0,0 +1,102 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/packages/celest_core/ffigen.core_foundation.yaml b/packages/celest_core/ffigen.core_foundation.yaml new file mode 100644 index 00000000..2af63fa6 --- /dev/null +++ b/packages/celest_core/ffigen.core_foundation.yaml @@ -0,0 +1,53 @@ +name: CoreFoundation +description: | + Bindings for Core Foundation on iOS/macOS. + + Regenerate bindings with `dart run ffigen --config=ffigen.core_foundation.yaml`. +language: "c" +output: + bindings: "lib/src/native/darwin/core_foundation.ffi.dart" +compiler-opts: + - "-F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks" +headers: + entry-points: + - "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFDictionary.h" + - "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFString.h" + - "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFData.h" +preamble: | + // ignore_for_file: type=lint + // ignore_for_file: return_of_invalid_type + // ignore_for_file: unnecessary_non_null_assertion +comments: + style: any + length: full + +ffi-native: +exclude-all-by-default: true +typedefs: + include: + - CF.* +globals: + include: + - kCF.* +functions: + include: + - CFDictionary.* + - CFArray.* + - CF(.*)GetTypeID + - CFDataCreate + - CFStringGetCStringPtr + - CFStringGetCString + - CFStringGetLength + - CFStringGetMaximumSizeForEncoding + - CFStringCreateWithCString + - CFDataGetBytePtr + - CFRelease +structs: + rename: + "__CFString": CFString + "__CFData": CFData + "__CFDictionary": CFDictionary + "__CFArray": CFArray +unnamed-enums: + include: + - kCF.* diff --git a/packages/celest_core/ffigen.security.yaml b/packages/celest_core/ffigen.security.yaml new file mode 100644 index 00000000..bbe4a82b --- /dev/null +++ b/packages/celest_core/ffigen.security.yaml @@ -0,0 +1,88 @@ +name: SecurityFramework +description: | + Bindings for Security.framework on iOS/macOS. + + Regenerate bindings with `dart run ffigen --config=ffigen.security.yaml`. +language: "c" +output: + bindings: "lib/src/native/darwin/security.ffi.dart" +compiler-opts: + - "-F/System/Volumes/Data/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks" +headers: + entry-points: + - "/System/Volumes/Data/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecItem.h" + - "/System/Volumes/Data/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecBase.h" + - "/System/Volumes/Data/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychainItem.h" +preamble: | + // ignore_for_file: type=lint + // ignore_for_file: return_of_invalid_type + // ignore_for_file: unnecessary_non_null_assertion +comments: + style: any + length: full +library-imports: + cf: "package:celest_core/src/native/darwin/core_foundation.ffi.dart" + +ffi-native: +exclude-all-by-default: true +typedefs: + include: + - Sec.* +functions: + include: + - Sec.* + - SecKeychainItem.* +globals: + include: + - kSec.* + - kCF.* +structs: + include: + - __SecKeychainItem + rename: + "__SecKeychainItem": SecKeychainItem +unnamed-enums: + include: + - errSec.* +type-map: + typedefs: + CFString: + lib: cf + c-type: CFString + dart-type: CFString + CFType: + lib: cf + c-type: CFType + dart-type: CFType + CFArray: + lib: cf + c-type: CFArray + dart-type: CFArray + CFArrayRef: + lib: cf + c-type: CFArrayRef + dart-type: CFArrayRef + CFData: + lib: cf + c-type: CFData + dart-type: CFData + CFDataRef: + lib: cf + c-type: CFDataRef + dart-type: CFDataRef + CFDictionary: + lib: cf + c-type: CFDictionary + dart-type: CFDictionary + CFStringRef: + lib: cf + c-type: CFStringRef + dart-type: CFStringRef + CFTypeRef: + lib: cf + c-type: CFTypeRef + dart-type: CFTypeRef + CFDictionaryRef: + lib: cf + c-type: CFDictionaryRef + dart-type: CFDictionaryRef diff --git a/packages/celest_core/jnigen.yaml b/packages/celest_core/jnigen.yaml new file mode 100644 index 00000000..e690ec73 --- /dev/null +++ b/packages/celest_core/jnigen.yaml @@ -0,0 +1,20 @@ +# Regenerate bindings with `dart run jnigen --config jnigen.yaml`. + +summarizer: + backend: asm + +android_sdk_config: + add_gradle_deps: true + android_example: "example/" + +suspend_fun_to_async: true + +output: + bindings_type: dart_only + dart: + path: "lib/src/native/android/jni_bindings.ffi.dart" + structure: single_file + +classes: + - dev.celest.celest_core.CelestSecureStorage + - android.app.Activity diff --git a/packages/celest_core/lib/src/native/android/jni_bindings.ffi.dart b/packages/celest_core/lib/src/native/android/jni_bindings.ffi.dart new file mode 100644 index 00000000..64cda8fc --- /dev/null +++ b/packages/celest_core/lib/src/native/android/jni_bindings.ffi.dart @@ -0,0 +1,4048 @@ +// Autogenerated by jnigen. DO NOT EDIT! + +// ignore_for_file: annotate_overrides +// ignore_for_file: camel_case_extensions +// ignore_for_file: camel_case_types +// ignore_for_file: constant_identifier_names +// ignore_for_file: file_names +// ignore_for_file: lines_longer_than_80_chars +// ignore_for_file: no_leading_underscores_for_local_identifiers +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: overridden_fields +// ignore_for_file: unnecessary_cast +// ignore_for_file: unused_element +// ignore_for_file: unused_field +// ignore_for_file: unused_import +// ignore_for_file: unused_local_variable +// ignore_for_file: unused_shown_name + +import "dart:isolate" show ReceivePort; +import "dart:ffi" as ffi; +import "package:jni/internal_helpers_for_jnigen.dart"; +import "package:jni/jni.dart" as jni; + +/// from: dev.celest.celest_core.CelestSecureStorage +class CelestSecureStorage extends jni.JObject { + @override + late final jni.JObjType $type = type; + + CelestSecureStorage.fromRef( + jni.JObjectPtr ref, + ) : super.fromRef(ref); + + static final _class = + jni.Jni.findJClass(r"dev/celest/celest_core/CelestSecureStorage"); + + /// The type which includes information such as the signature of this class. + static const type = $CelestSecureStorageType(); + static final _id_new0 = jni.Jni.accessors.getMethodIDOf(_class.reference, + r"", r"(Landroid/app/Activity;Ljava/lang/String;)V"); + + /// from: public void (android.app.Activity activity, java.lang.String string) + /// The returned object must be released after use, by calling the [release] method. + factory CelestSecureStorage( + Activity activity, + jni.JString string, + ) { + return CelestSecureStorage.fromRef(jni.Jni.accessors.newObjectWithArgs( + _class.reference, + _id_new0, + [activity.reference, string.reference]).object); + } + + static final _id_write = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"write", r"(Ljava/lang/String;Ljava/lang/String;)V"); + + /// from: public final void write(java.lang.String string, java.lang.String string1) + void write( + jni.JString string, + jni.JString string1, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_write, + jni.JniCallType.voidType, + [string.reference, string1.reference]).check(); + } + + static final _id_read = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"read", r"(Ljava/lang/String;)Ljava/lang/String;"); + + /// from: public final java.lang.String read(java.lang.String string) + /// The returned object must be released after use, by calling the [release] method. + jni.JString read( + jni.JString string, + ) { + return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_read, + jni.JniCallType.objectType, + [string.reference]).object); + } + + static final _id_delete = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"delete", r"(Ljava/lang/String;)Ljava/lang/String;"); + + /// from: public final java.lang.String delete(java.lang.String string) + /// The returned object must be released after use, by calling the [release] method. + jni.JString delete( + jni.JString string, + ) { + return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_delete, + jni.JniCallType.objectType, + [string.reference]).object); + } + + static final _id_clear = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"clear", r"()V"); + + /// from: public final void clear() + void clear() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_clear, jni.JniCallType.voidType, []).check(); + } +} + +final class $CelestSecureStorageType extends jni.JObjType { + const $CelestSecureStorageType(); + + @override + String get signature => r"Ldev/celest/celest_core/CelestSecureStorage;"; + + @override + CelestSecureStorage fromRef(jni.JObjectPtr ref) => + CelestSecureStorage.fromRef(ref); + + @override + jni.JObjType get superType => const jni.JObjectType(); + + @override + final superCount = 1; + + @override + int get hashCode => ($CelestSecureStorageType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == ($CelestSecureStorageType) && + other is $CelestSecureStorageType; + } +} + +/// from: android.app.Activity$ScreenCaptureCallback +class Activity_ScreenCaptureCallback extends jni.JObject { + @override + late final jni.JObjType $type = type; + + Activity_ScreenCaptureCallback.fromRef( + jni.JObjectPtr ref, + ) : super.fromRef(ref); + + static final _class = + jni.Jni.findJClass(r"android/app/Activity$ScreenCaptureCallback"); + + /// The type which includes information such as the signature of this class. + static const type = $Activity_ScreenCaptureCallbackType(); + static final _id_onScreenCaptured = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onScreenCaptured", r"()V"); + + /// from: public abstract void onScreenCaptured() + void onScreenCaptured() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onScreenCaptured, jni.JniCallType.voidType, []).check(); + } +} + +final class $Activity_ScreenCaptureCallbackType + extends jni.JObjType { + const $Activity_ScreenCaptureCallbackType(); + + @override + String get signature => r"Landroid/app/Activity$ScreenCaptureCallback;"; + + @override + Activity_ScreenCaptureCallback fromRef(jni.JObjectPtr ref) => + Activity_ScreenCaptureCallback.fromRef(ref); + + @override + jni.JObjType get superType => const jni.JObjectType(); + + @override + final superCount = 1; + + @override + int get hashCode => ($Activity_ScreenCaptureCallbackType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == ($Activity_ScreenCaptureCallbackType) && + other is $Activity_ScreenCaptureCallbackType; + } +} + +/// from: android.app.Activity +class Activity extends jni.JObject { + @override + late final jni.JObjType $type = type; + + Activity.fromRef( + jni.JObjectPtr ref, + ) : super.fromRef(ref); + + static final _class = jni.Jni.findJClass(r"android/app/Activity"); + + /// The type which includes information such as the signature of this class. + static const type = $ActivityType(); + + /// from: static public final int DEFAULT_KEYS_DIALER + static const DEFAULT_KEYS_DIALER = 1; + + /// from: static public final int DEFAULT_KEYS_DISABLE + static const DEFAULT_KEYS_DISABLE = 0; + + /// from: static public final int DEFAULT_KEYS_SEARCH_GLOBAL + static const DEFAULT_KEYS_SEARCH_GLOBAL = 4; + + /// from: static public final int DEFAULT_KEYS_SEARCH_LOCAL + static const DEFAULT_KEYS_SEARCH_LOCAL = 3; + + /// from: static public final int DEFAULT_KEYS_SHORTCUT + static const DEFAULT_KEYS_SHORTCUT = 2; + + static final _id_FOCUSED_STATE_SET = jni.Jni.accessors.getStaticFieldIDOf( + _class.reference, + r"FOCUSED_STATE_SET", + r"[I", + ); + + /// from: static protected final int[] FOCUSED_STATE_SET + /// The returned object must be released after use, by calling the [release] method. + static jni.JArray get FOCUSED_STATE_SET => + const jni.JArrayType(jni.jintType()).fromRef(jni.Jni.accessors + .getStaticField(_class.reference, _id_FOCUSED_STATE_SET, + jni.JniCallType.objectType) + .object); + + /// from: static public final int FULLSCREEN_MODE_REQUEST_ENTER + static const FULLSCREEN_MODE_REQUEST_ENTER = 1; + + /// from: static public final int FULLSCREEN_MODE_REQUEST_EXIT + static const FULLSCREEN_MODE_REQUEST_EXIT = 0; + + /// from: static public final int OVERRIDE_TRANSITION_CLOSE + static const OVERRIDE_TRANSITION_CLOSE = 1; + + /// from: static public final int OVERRIDE_TRANSITION_OPEN + static const OVERRIDE_TRANSITION_OPEN = 0; + + /// from: static public final int RESULT_CANCELED + static const RESULT_CANCELED = 0; + + /// from: static public final int RESULT_FIRST_USER + static const RESULT_FIRST_USER = 1; + + /// from: static public final int RESULT_OK + static const RESULT_OK = -1; + + static final _id_new0 = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"", r"()V"); + + /// from: public void () + /// The returned object must be released after use, by calling the [release] method. + factory Activity() { + return Activity.fromRef(jni.Jni.accessors + .newObjectWithArgs(_class.reference, _id_new0, []).object); + } + + static final _id_getIntent = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getIntent", r"()Landroid/content/Intent;"); + + /// from: public android.content.Intent getIntent() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getIntent() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_getIntent, jni.JniCallType.objectType, []).object); + } + + static final _id_setIntent = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"setIntent", r"(Landroid/content/Intent;)V"); + + /// from: public void setIntent(android.content.Intent intent) + void setIntent( + jni.JObject intent, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setIntent, + jni.JniCallType.voidType, [intent.reference]).check(); + } + + static final _id_setLocusContext = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"setLocusContext", + r"(Landroid/content/LocusId;Landroid/os/Bundle;)V"); + + /// from: public void setLocusContext(android.content.LocusId locusId, android.os.Bundle bundle) + void setLocusContext( + jni.JObject locusId, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setLocusContext, + jni.JniCallType.voidType, + [locusId.reference, bundle.reference]).check(); + } + + static final _id_getApplication = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getApplication", r"()Landroid/app/Application;"); + + /// from: public final android.app.Application getApplication() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getApplication() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_getApplication, jni.JniCallType.objectType, []).object); + } + + static final _id_isChild = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"isChild", r"()Z"); + + /// from: public final boolean isChild() + bool isChild() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_isChild, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_getParent = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getParent", r"()Landroid/app/Activity;"); + + /// from: public final android.app.Activity getParent() + /// The returned object must be released after use, by calling the [release] method. + Activity getParent() { + return const $ActivityType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_getParent, jni.JniCallType.objectType, []).object); + } + + static final _id_getWindowManager = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getWindowManager", r"()Landroid/view/WindowManager;"); + + /// from: public android.view.WindowManager getWindowManager() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getWindowManager() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getWindowManager, + jni.JniCallType.objectType, []).object); + } + + static final _id_getWindow = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getWindow", r"()Landroid/view/Window;"); + + /// from: public android.view.Window getWindow() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getWindow() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_getWindow, jni.JniCallType.objectType, []).object); + } + + static final _id_getLoaderManager = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getLoaderManager", r"()Landroid/app/LoaderManager;"); + + /// from: public android.app.LoaderManager getLoaderManager() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getLoaderManager() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getLoaderManager, + jni.JniCallType.objectType, []).object); + } + + static final _id_getCurrentFocus = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getCurrentFocus", r"()Landroid/view/View;"); + + /// from: public android.view.View getCurrentFocus() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getCurrentFocus() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_getCurrentFocus, jni.JniCallType.objectType, []).object); + } + + static final _id_attachBaseContext = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"attachBaseContext", r"(Landroid/content/Context;)V"); + + /// from: protected void attachBaseContext(android.content.Context context) + void attachBaseContext( + jni.JObject context, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_attachBaseContext, + jni.JniCallType.voidType, + [context.reference]).check(); + } + + static final _id_registerActivityLifecycleCallbacks = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"registerActivityLifecycleCallbacks", + r"(Landroid/app/Application$ActivityLifecycleCallbacks;)V"); + + /// from: public void registerActivityLifecycleCallbacks(android.app.Application$ActivityLifecycleCallbacks activityLifecycleCallbacks) + void registerActivityLifecycleCallbacks( + jni.JObject activityLifecycleCallbacks, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_registerActivityLifecycleCallbacks, + jni.JniCallType.voidType, + [activityLifecycleCallbacks.reference]).check(); + } + + static final _id_unregisterActivityLifecycleCallbacks = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"unregisterActivityLifecycleCallbacks", + r"(Landroid/app/Application$ActivityLifecycleCallbacks;)V"); + + /// from: public void unregisterActivityLifecycleCallbacks(android.app.Application$ActivityLifecycleCallbacks activityLifecycleCallbacks) + void unregisterActivityLifecycleCallbacks( + jni.JObject activityLifecycleCallbacks, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_unregisterActivityLifecycleCallbacks, + jni.JniCallType.voidType, + [activityLifecycleCallbacks.reference]).check(); + } + + static final _id_registerComponentCallbacks = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"registerComponentCallbacks", + r"(Landroid/content/ComponentCallbacks;)V"); + + /// from: public void registerComponentCallbacks(android.content.ComponentCallbacks componentCallbacks) + void registerComponentCallbacks( + jni.JObject componentCallbacks, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_registerComponentCallbacks, + jni.JniCallType.voidType, + [componentCallbacks.reference]).check(); + } + + static final _id_unregisterComponentCallbacks = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"unregisterComponentCallbacks", + r"(Landroid/content/ComponentCallbacks;)V"); + + /// from: public void unregisterComponentCallbacks(android.content.ComponentCallbacks componentCallbacks) + void unregisterComponentCallbacks( + jni.JObject componentCallbacks, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_unregisterComponentCallbacks, + jni.JniCallType.voidType, + [componentCallbacks.reference]).check(); + } + + static final _id_onCreate = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onCreate", r"(Landroid/os/Bundle;)V"); + + /// from: protected void onCreate(android.os.Bundle bundle) + void onCreate( + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_onCreate, + jni.JniCallType.voidType, [bundle.reference]).check(); + } + + static final _id_getSplashScreen = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getSplashScreen", r"()Landroid/window/SplashScreen;"); + + /// from: public final android.window.SplashScreen getSplashScreen() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getSplashScreen() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_getSplashScreen, jni.JniCallType.objectType, []).object); + } + + static final _id_onCreate1 = jni.Jni.accessors.getMethodIDOf(_class.reference, + r"onCreate", r"(Landroid/os/Bundle;Landroid/os/PersistableBundle;)V"); + + /// from: public void onCreate(android.os.Bundle bundle, android.os.PersistableBundle persistableBundle) + void onCreate1( + jni.JObject bundle, + jni.JObject persistableBundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onCreate1, + jni.JniCallType.voidType, + [bundle.reference, persistableBundle.reference]).check(); + } + + static final _id_onRestoreInstanceState = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onRestoreInstanceState", r"(Landroid/os/Bundle;)V"); + + /// from: protected void onRestoreInstanceState(android.os.Bundle bundle) + void onRestoreInstanceState( + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onRestoreInstanceState, + jni.JniCallType.voidType, + [bundle.reference]).check(); + } + + static final _id_onRestoreInstanceState1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onRestoreInstanceState", + r"(Landroid/os/Bundle;Landroid/os/PersistableBundle;)V"); + + /// from: public void onRestoreInstanceState(android.os.Bundle bundle, android.os.PersistableBundle persistableBundle) + void onRestoreInstanceState1( + jni.JObject bundle, + jni.JObject persistableBundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onRestoreInstanceState1, + jni.JniCallType.voidType, + [bundle.reference, persistableBundle.reference]).check(); + } + + static final _id_onPostCreate = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onPostCreate", r"(Landroid/os/Bundle;)V"); + + /// from: protected void onPostCreate(android.os.Bundle bundle) + void onPostCreate( + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_onPostCreate, + jni.JniCallType.voidType, [bundle.reference]).check(); + } + + static final _id_onPostCreate1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onPostCreate", + r"(Landroid/os/Bundle;Landroid/os/PersistableBundle;)V"); + + /// from: public void onPostCreate(android.os.Bundle bundle, android.os.PersistableBundle persistableBundle) + void onPostCreate1( + jni.JObject bundle, + jni.JObject persistableBundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onPostCreate1, + jni.JniCallType.voidType, + [bundle.reference, persistableBundle.reference]).check(); + } + + static final _id_onStart = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"onStart", r"()V"); + + /// from: protected void onStart() + void onStart() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onStart, jni.JniCallType.voidType, []).check(); + } + + static final _id_onRestart = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"onRestart", r"()V"); + + /// from: protected void onRestart() + void onRestart() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onRestart, jni.JniCallType.voidType, []).check(); + } + + static final _id_onStateNotSaved = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onStateNotSaved", r"()V"); + + /// from: public void onStateNotSaved() + void onStateNotSaved() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onStateNotSaved, jni.JniCallType.voidType, []).check(); + } + + static final _id_onResume = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"onResume", r"()V"); + + /// from: protected void onResume() + void onResume() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onResume, jni.JniCallType.voidType, []).check(); + } + + static final _id_onPostResume = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onPostResume", r"()V"); + + /// from: protected void onPostResume() + void onPostResume() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onPostResume, jni.JniCallType.voidType, []).check(); + } + + static final _id_onTopResumedActivityChanged = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onTopResumedActivityChanged", r"(Z)V"); + + /// from: public void onTopResumedActivityChanged(boolean z) + void onTopResumedActivityChanged( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onTopResumedActivityChanged, + jni.JniCallType.voidType, + [z ? 1 : 0]).check(); + } + + static final _id_isVoiceInteraction = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"isVoiceInteraction", r"()Z"); + + /// from: public boolean isVoiceInteraction() + bool isVoiceInteraction() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_isVoiceInteraction, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_isVoiceInteractionRoot = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"isVoiceInteractionRoot", r"()Z"); + + /// from: public boolean isVoiceInteractionRoot() + bool isVoiceInteractionRoot() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_isVoiceInteractionRoot, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_getVoiceInteractor = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"getVoiceInteractor", + r"()Landroid/app/VoiceInteractor;"); + + /// from: public android.app.VoiceInteractor getVoiceInteractor() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getVoiceInteractor() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getVoiceInteractor, + jni.JniCallType.objectType, []).object); + } + + static final _id_isLocalVoiceInteractionSupported = jni.Jni.accessors + .getMethodIDOf( + _class.reference, r"isLocalVoiceInteractionSupported", r"()Z"); + + /// from: public boolean isLocalVoiceInteractionSupported() + bool isLocalVoiceInteractionSupported() { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_isLocalVoiceInteractionSupported, + jni.JniCallType.booleanType, []).boolean; + } + + static final _id_startLocalVoiceInteraction = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startLocalVoiceInteraction", + r"(Landroid/os/Bundle;)V"); + + /// from: public void startLocalVoiceInteraction(android.os.Bundle bundle) + void startLocalVoiceInteraction( + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startLocalVoiceInteraction, + jni.JniCallType.voidType, + [bundle.reference]).check(); + } + + static final _id_onLocalVoiceInteractionStarted = jni.Jni.accessors + .getMethodIDOf( + _class.reference, r"onLocalVoiceInteractionStarted", r"()V"); + + /// from: public void onLocalVoiceInteractionStarted() + void onLocalVoiceInteractionStarted() { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onLocalVoiceInteractionStarted, + jni.JniCallType.voidType, []).check(); + } + + static final _id_onLocalVoiceInteractionStopped = jni.Jni.accessors + .getMethodIDOf( + _class.reference, r"onLocalVoiceInteractionStopped", r"()V"); + + /// from: public void onLocalVoiceInteractionStopped() + void onLocalVoiceInteractionStopped() { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onLocalVoiceInteractionStopped, + jni.JniCallType.voidType, []).check(); + } + + static final _id_stopLocalVoiceInteraction = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"stopLocalVoiceInteraction", r"()V"); + + /// from: public void stopLocalVoiceInteraction() + void stopLocalVoiceInteraction() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_stopLocalVoiceInteraction, jni.JniCallType.voidType, []).check(); + } + + static final _id_onNewIntent = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onNewIntent", r"(Landroid/content/Intent;)V"); + + /// from: protected void onNewIntent(android.content.Intent intent) + void onNewIntent( + jni.JObject intent, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_onNewIntent, + jni.JniCallType.voidType, [intent.reference]).check(); + } + + static final _id_onSaveInstanceState = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onSaveInstanceState", r"(Landroid/os/Bundle;)V"); + + /// from: protected void onSaveInstanceState(android.os.Bundle bundle) + void onSaveInstanceState( + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onSaveInstanceState, + jni.JniCallType.voidType, + [bundle.reference]).check(); + } + + static final _id_onSaveInstanceState1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onSaveInstanceState", + r"(Landroid/os/Bundle;Landroid/os/PersistableBundle;)V"); + + /// from: public void onSaveInstanceState(android.os.Bundle bundle, android.os.PersistableBundle persistableBundle) + void onSaveInstanceState1( + jni.JObject bundle, + jni.JObject persistableBundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onSaveInstanceState1, + jni.JniCallType.voidType, + [bundle.reference, persistableBundle.reference]).check(); + } + + static final _id_onPause = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"onPause", r"()V"); + + /// from: protected void onPause() + void onPause() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onPause, jni.JniCallType.voidType, []).check(); + } + + static final _id_onUserLeaveHint = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onUserLeaveHint", r"()V"); + + /// from: protected void onUserLeaveHint() + void onUserLeaveHint() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onUserLeaveHint, jni.JniCallType.voidType, []).check(); + } + + static final _id_onCreateThumbnail = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onCreateThumbnail", + r"(Landroid/graphics/Bitmap;Landroid/graphics/Canvas;)Z"); + + /// from: public boolean onCreateThumbnail(android.graphics.Bitmap bitmap, android.graphics.Canvas canvas) + bool onCreateThumbnail( + jni.JObject bitmap, + jni.JObject canvas, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onCreateThumbnail, + jni.JniCallType.booleanType, + [bitmap.reference, canvas.reference]).boolean; + } + + static final _id_onCreateDescription = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onCreateDescription", r"()Ljava/lang/CharSequence;"); + + /// from: public java.lang.CharSequence onCreateDescription() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject onCreateDescription() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onCreateDescription, + jni.JniCallType.objectType, []).object); + } + + static final _id_onProvideAssistData = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onProvideAssistData", r"(Landroid/os/Bundle;)V"); + + /// from: public void onProvideAssistData(android.os.Bundle bundle) + void onProvideAssistData( + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onProvideAssistData, + jni.JniCallType.voidType, + [bundle.reference]).check(); + } + + static final _id_onProvideAssistContent = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onProvideAssistContent", + r"(Landroid/app/assist/AssistContent;)V"); + + /// from: public void onProvideAssistContent(android.app.assist.AssistContent assistContent) + void onProvideAssistContent( + jni.JObject assistContent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onProvideAssistContent, + jni.JniCallType.voidType, + [assistContent.reference]).check(); + } + + static final _id_onGetDirectActions = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onGetDirectActions", + r"(Landroid/os/CancellationSignal;Ljava/util/function/Consumer;)V"); + + /// from: public void onGetDirectActions(android.os.CancellationSignal cancellationSignal, java.util.function.Consumer consumer) + void onGetDirectActions( + jni.JObject cancellationSignal, + jni.JObject consumer, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onGetDirectActions, + jni.JniCallType.voidType, + [cancellationSignal.reference, consumer.reference]).check(); + } + + static final _id_onPerformDirectAction = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onPerformDirectAction", + r"(Ljava/lang/String;Landroid/os/Bundle;Landroid/os/CancellationSignal;Ljava/util/function/Consumer;)V"); + + /// from: public void onPerformDirectAction(java.lang.String string, android.os.Bundle bundle, android.os.CancellationSignal cancellationSignal, java.util.function.Consumer consumer) + void onPerformDirectAction( + jni.JString string, + jni.JObject bundle, + jni.JObject cancellationSignal, + jni.JObject consumer, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onPerformDirectAction, jni.JniCallType.voidType, [ + string.reference, + bundle.reference, + cancellationSignal.reference, + consumer.reference + ]).check(); + } + + static final _id_requestShowKeyboardShortcuts = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"requestShowKeyboardShortcuts", r"()V"); + + /// from: public final void requestShowKeyboardShortcuts() + void requestShowKeyboardShortcuts() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_requestShowKeyboardShortcuts, jni.JniCallType.voidType, []).check(); + } + + static final _id_dismissKeyboardShortcutsHelper = jni.Jni.accessors + .getMethodIDOf( + _class.reference, r"dismissKeyboardShortcutsHelper", r"()V"); + + /// from: public final void dismissKeyboardShortcutsHelper() + void dismissKeyboardShortcutsHelper() { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_dismissKeyboardShortcutsHelper, + jni.JniCallType.voidType, []).check(); + } + + static final _id_onProvideKeyboardShortcuts = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onProvideKeyboardShortcuts", + r"(Ljava/util/List;Landroid/view/Menu;I)V"); + + /// from: public void onProvideKeyboardShortcuts(java.util.List list, android.view.Menu menu, int i) + void onProvideKeyboardShortcuts( + jni.JList list, + jni.JObject menu, + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onProvideKeyboardShortcuts, + jni.JniCallType.voidType, + [list.reference, menu.reference, jni.JValueInt(i)]).check(); + } + + static final _id_showAssist = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"showAssist", r"(Landroid/os/Bundle;)Z"); + + /// from: public boolean showAssist(android.os.Bundle bundle) + bool showAssist( + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_showAssist, + jni.JniCallType.booleanType, [bundle.reference]).boolean; + } + + static final _id_onStop = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"onStop", r"()V"); + + /// from: protected void onStop() + void onStop() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onStop, jni.JniCallType.voidType, []).check(); + } + + static final _id_onDestroy = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"onDestroy", r"()V"); + + /// from: protected void onDestroy() + void onDestroy() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onDestroy, jni.JniCallType.voidType, []).check(); + } + + static final _id_reportFullyDrawn = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"reportFullyDrawn", r"()V"); + + /// from: public void reportFullyDrawn() + void reportFullyDrawn() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_reportFullyDrawn, jni.JniCallType.voidType, []).check(); + } + + static final _id_onMultiWindowModeChanged = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onMultiWindowModeChanged", + r"(ZLandroid/content/res/Configuration;)V"); + + /// from: public void onMultiWindowModeChanged(boolean z, android.content.res.Configuration configuration) + void onMultiWindowModeChanged( + bool z, + jni.JObject configuration, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onMultiWindowModeChanged, + jni.JniCallType.voidType, + [z ? 1 : 0, configuration.reference]).check(); + } + + static final _id_onMultiWindowModeChanged1 = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onMultiWindowModeChanged", r"(Z)V"); + + /// from: public void onMultiWindowModeChanged(boolean z) + void onMultiWindowModeChanged1( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onMultiWindowModeChanged1, + jni.JniCallType.voidType, + [z ? 1 : 0]).check(); + } + + static final _id_isInMultiWindowMode = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"isInMultiWindowMode", r"()Z"); + + /// from: public boolean isInMultiWindowMode() + bool isInMultiWindowMode() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_isInMultiWindowMode, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_onPictureInPictureModeChanged = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onPictureInPictureModeChanged", + r"(ZLandroid/content/res/Configuration;)V"); + + /// from: public void onPictureInPictureModeChanged(boolean z, android.content.res.Configuration configuration) + void onPictureInPictureModeChanged( + bool z, + jni.JObject configuration, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onPictureInPictureModeChanged, + jni.JniCallType.voidType, + [z ? 1 : 0, configuration.reference]).check(); + } + + static final _id_onPictureInPictureUiStateChanged = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onPictureInPictureUiStateChanged", + r"(Landroid/app/PictureInPictureUiState;)V"); + + /// from: public void onPictureInPictureUiStateChanged(android.app.PictureInPictureUiState pictureInPictureUiState) + void onPictureInPictureUiStateChanged( + jni.JObject pictureInPictureUiState, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onPictureInPictureUiStateChanged, + jni.JniCallType.voidType, + [pictureInPictureUiState.reference]).check(); + } + + static final _id_onPictureInPictureModeChanged1 = jni.Jni.accessors + .getMethodIDOf( + _class.reference, r"onPictureInPictureModeChanged", r"(Z)V"); + + /// from: public void onPictureInPictureModeChanged(boolean z) + void onPictureInPictureModeChanged1( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onPictureInPictureModeChanged1, + jni.JniCallType.voidType, + [z ? 1 : 0]).check(); + } + + static final _id_isInPictureInPictureMode = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"isInPictureInPictureMode", r"()Z"); + + /// from: public boolean isInPictureInPictureMode() + bool isInPictureInPictureMode() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_isInPictureInPictureMode, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_enterPictureInPictureMode = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"enterPictureInPictureMode", r"()V"); + + /// from: public void enterPictureInPictureMode() + void enterPictureInPictureMode() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_enterPictureInPictureMode, jni.JniCallType.voidType, []).check(); + } + + static final _id_enterPictureInPictureMode1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"enterPictureInPictureMode", + r"(Landroid/app/PictureInPictureParams;)Z"); + + /// from: public boolean enterPictureInPictureMode(android.app.PictureInPictureParams pictureInPictureParams) + bool enterPictureInPictureMode1( + jni.JObject pictureInPictureParams, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_enterPictureInPictureMode1, + jni.JniCallType.booleanType, + [pictureInPictureParams.reference]).boolean; + } + + static final _id_setPictureInPictureParams = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"setPictureInPictureParams", + r"(Landroid/app/PictureInPictureParams;)V"); + + /// from: public void setPictureInPictureParams(android.app.PictureInPictureParams pictureInPictureParams) + void setPictureInPictureParams( + jni.JObject pictureInPictureParams, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setPictureInPictureParams, + jni.JniCallType.voidType, + [pictureInPictureParams.reference]).check(); + } + + static final _id_getMaxNumPictureInPictureActions = jni.Jni.accessors + .getMethodIDOf( + _class.reference, r"getMaxNumPictureInPictureActions", r"()I"); + + /// from: public int getMaxNumPictureInPictureActions() + int getMaxNumPictureInPictureActions() { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getMaxNumPictureInPictureActions, + jni.JniCallType.intType, []).integer; + } + + static final _id_onPictureInPictureRequested = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onPictureInPictureRequested", r"()Z"); + + /// from: public boolean onPictureInPictureRequested() + bool onPictureInPictureRequested() { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onPictureInPictureRequested, + jni.JniCallType.booleanType, []).boolean; + } + + static final _id_requestFullscreenMode = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"requestFullscreenMode", + r"(ILandroid/os/OutcomeReceiver;)V"); + + /// from: public void requestFullscreenMode(int i, android.os.OutcomeReceiver outcomeReceiver) + void requestFullscreenMode( + int i, + jni.JObject outcomeReceiver, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_requestFullscreenMode, + jni.JniCallType.voidType, + [jni.JValueInt(i), outcomeReceiver.reference]).check(); + } + + static final _id_setShouldDockBigOverlays = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setShouldDockBigOverlays", r"(Z)V"); + + /// from: public void setShouldDockBigOverlays(boolean z) + void setShouldDockBigOverlays( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setShouldDockBigOverlays, + jni.JniCallType.voidType, + [z ? 1 : 0]).check(); + } + + static final _id_shouldDockBigOverlays = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"shouldDockBigOverlays", r"()Z"); + + /// from: public boolean shouldDockBigOverlays() + bool shouldDockBigOverlays() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_shouldDockBigOverlays, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_onConfigurationChanged = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onConfigurationChanged", + r"(Landroid/content/res/Configuration;)V"); + + /// from: public void onConfigurationChanged(android.content.res.Configuration configuration) + void onConfigurationChanged( + jni.JObject configuration, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onConfigurationChanged, + jni.JniCallType.voidType, + [configuration.reference]).check(); + } + + static final _id_getChangingConfigurations = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"getChangingConfigurations", r"()I"); + + /// from: public int getChangingConfigurations() + int getChangingConfigurations() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_getChangingConfigurations, jni.JniCallType.intType, []).integer; + } + + static final _id_getLastNonConfigurationInstance = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"getLastNonConfigurationInstance", + r"()Ljava/lang/Object;"); + + /// from: public java.lang.Object getLastNonConfigurationInstance() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getLastNonConfigurationInstance() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getLastNonConfigurationInstance, + jni.JniCallType.objectType, []).object); + } + + static final _id_onRetainNonConfigurationInstance = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onRetainNonConfigurationInstance", + r"()Ljava/lang/Object;"); + + /// from: public java.lang.Object onRetainNonConfigurationInstance() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject onRetainNonConfigurationInstance() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onRetainNonConfigurationInstance, + jni.JniCallType.objectType, []).object); + } + + static final _id_onLowMemory = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"onLowMemory", r"()V"); + + /// from: public void onLowMemory() + void onLowMemory() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onLowMemory, jni.JniCallType.voidType, []).check(); + } + + static final _id_onTrimMemory = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onTrimMemory", r"(I)V"); + + /// from: public void onTrimMemory(int i) + void onTrimMemory( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_onTrimMemory, + jni.JniCallType.voidType, [jni.JValueInt(i)]).check(); + } + + static final _id_getFragmentManager = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"getFragmentManager", + r"()Landroid/app/FragmentManager;"); + + /// from: public android.app.FragmentManager getFragmentManager() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getFragmentManager() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getFragmentManager, + jni.JniCallType.objectType, []).object); + } + + static final _id_onAttachFragment = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onAttachFragment", r"(Landroid/app/Fragment;)V"); + + /// from: public void onAttachFragment(android.app.Fragment fragment) + void onAttachFragment( + jni.JObject fragment, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_onAttachFragment, + jni.JniCallType.voidType, [fragment.reference]).check(); + } + + static final _id_managedQuery = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"managedQuery", + r"(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;"); + + /// from: public final android.database.Cursor managedQuery(android.net.Uri uri, java.lang.String[] strings, java.lang.String string, java.lang.String[] strings1, java.lang.String string1) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject managedQuery( + jni.JObject uri, + jni.JArray strings, + jni.JString string, + jni.JArray strings1, + jni.JString string1, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_managedQuery, jni.JniCallType.objectType, [ + uri.reference, + strings.reference, + string.reference, + strings1.reference, + string1.reference + ]).object); + } + + static final _id_startManagingCursor = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startManagingCursor", + r"(Landroid/database/Cursor;)V"); + + /// from: public void startManagingCursor(android.database.Cursor cursor) + void startManagingCursor( + jni.JObject cursor, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startManagingCursor, + jni.JniCallType.voidType, + [cursor.reference]).check(); + } + + static final _id_stopManagingCursor = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"stopManagingCursor", r"(Landroid/database/Cursor;)V"); + + /// from: public void stopManagingCursor(android.database.Cursor cursor) + void stopManagingCursor( + jni.JObject cursor, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_stopManagingCursor, + jni.JniCallType.voidType, + [cursor.reference]).check(); + } + + static final _id_findViewById = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"findViewById", r"(I)Landroid/view/View;"); + + /// from: public T findViewById(int i) + /// The returned object must be released after use, by calling the [release] method. + $T findViewById<$T extends jni.JObject>( + int i, { + required jni.JObjType<$T> T, + }) { + return T.fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_findViewById, + jni.JniCallType.objectType, + [jni.JValueInt(i)]).object); + } + + static final _id_requireViewById = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"requireViewById", r"(I)Landroid/view/View;"); + + /// from: public final T requireViewById(int i) + /// The returned object must be released after use, by calling the [release] method. + $T requireViewById<$T extends jni.JObject>( + int i, { + required jni.JObjType<$T> T, + }) { + return T.fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_requireViewById, + jni.JniCallType.objectType, + [jni.JValueInt(i)]).object); + } + + static final _id_getActionBar = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getActionBar", r"()Landroid/app/ActionBar;"); + + /// from: public android.app.ActionBar getActionBar() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getActionBar() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_getActionBar, jni.JniCallType.objectType, []).object); + } + + static final _id_setActionBar = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"setActionBar", r"(Landroid/widget/Toolbar;)V"); + + /// from: public void setActionBar(android.widget.Toolbar toolbar) + void setActionBar( + jni.JObject toolbar, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setActionBar, + jni.JniCallType.voidType, [toolbar.reference]).check(); + } + + static final _id_setContentView = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setContentView", r"(I)V"); + + /// from: public void setContentView(int i) + void setContentView( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setContentView, + jni.JniCallType.voidType, [jni.JValueInt(i)]).check(); + } + + static final _id_setContentView1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"setContentView", r"(Landroid/view/View;)V"); + + /// from: public void setContentView(android.view.View view) + void setContentView1( + jni.JObject view, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setContentView1, + jni.JniCallType.voidType, [view.reference]).check(); + } + + static final _id_setContentView2 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"setContentView", + r"(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V"); + + /// from: public void setContentView(android.view.View view, android.view.ViewGroup$LayoutParams layoutParams) + void setContentView2( + jni.JObject view, + jni.JObject layoutParams, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setContentView2, + jni.JniCallType.voidType, + [view.reference, layoutParams.reference]).check(); + } + + static final _id_addContentView = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"addContentView", + r"(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V"); + + /// from: public void addContentView(android.view.View view, android.view.ViewGroup$LayoutParams layoutParams) + void addContentView( + jni.JObject view, + jni.JObject layoutParams, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_addContentView, + jni.JniCallType.voidType, + [view.reference, layoutParams.reference]).check(); + } + + static final _id_getContentTransitionManager = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"getContentTransitionManager", + r"()Landroid/transition/TransitionManager;"); + + /// from: public android.transition.TransitionManager getContentTransitionManager() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getContentTransitionManager() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getContentTransitionManager, + jni.JniCallType.objectType, []).object); + } + + static final _id_setContentTransitionManager = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setContentTransitionManager", + r"(Landroid/transition/TransitionManager;)V"); + + /// from: public void setContentTransitionManager(android.transition.TransitionManager transitionManager) + void setContentTransitionManager( + jni.JObject transitionManager, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setContentTransitionManager, + jni.JniCallType.voidType, + [transitionManager.reference]).check(); + } + + static final _id_getContentScene = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getContentScene", r"()Landroid/transition/Scene;"); + + /// from: public android.transition.Scene getContentScene() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getContentScene() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_getContentScene, jni.JniCallType.objectType, []).object); + } + + static final _id_setFinishOnTouchOutside = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setFinishOnTouchOutside", r"(Z)V"); + + /// from: public void setFinishOnTouchOutside(boolean z) + void setFinishOnTouchOutside( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setFinishOnTouchOutside, + jni.JniCallType.voidType, + [z ? 1 : 0]).check(); + } + + static final _id_setDefaultKeyMode = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setDefaultKeyMode", r"(I)V"); + + /// from: public final void setDefaultKeyMode(int i) + void setDefaultKeyMode( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setDefaultKeyMode, + jni.JniCallType.voidType, + [jni.JValueInt(i)]).check(); + } + + static final _id_onKeyDown = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onKeyDown", r"(ILandroid/view/KeyEvent;)Z"); + + /// from: public boolean onKeyDown(int i, android.view.KeyEvent keyEvent) + bool onKeyDown( + int i, + jni.JObject keyEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onKeyDown, + jni.JniCallType.booleanType, + [jni.JValueInt(i), keyEvent.reference]).boolean; + } + + static final _id_onKeyLongPress = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onKeyLongPress", r"(ILandroid/view/KeyEvent;)Z"); + + /// from: public boolean onKeyLongPress(int i, android.view.KeyEvent keyEvent) + bool onKeyLongPress( + int i, + jni.JObject keyEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onKeyLongPress, + jni.JniCallType.booleanType, + [jni.JValueInt(i), keyEvent.reference]).boolean; + } + + static final _id_onKeyUp = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onKeyUp", r"(ILandroid/view/KeyEvent;)Z"); + + /// from: public boolean onKeyUp(int i, android.view.KeyEvent keyEvent) + bool onKeyUp( + int i, + jni.JObject keyEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onKeyUp, + jni.JniCallType.booleanType, + [jni.JValueInt(i), keyEvent.reference]).boolean; + } + + static final _id_onKeyMultiple = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onKeyMultiple", r"(IILandroid/view/KeyEvent;)Z"); + + /// from: public boolean onKeyMultiple(int i, int i1, android.view.KeyEvent keyEvent) + bool onKeyMultiple( + int i, + int i1, + jni.JObject keyEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onKeyMultiple, + jni.JniCallType.booleanType, + [jni.JValueInt(i), jni.JValueInt(i1), keyEvent.reference]).boolean; + } + + static final _id_onBackPressed = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onBackPressed", r"()V"); + + /// from: public void onBackPressed() + void onBackPressed() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onBackPressed, jni.JniCallType.voidType, []).check(); + } + + static final _id_onKeyShortcut = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onKeyShortcut", r"(ILandroid/view/KeyEvent;)Z"); + + /// from: public boolean onKeyShortcut(int i, android.view.KeyEvent keyEvent) + bool onKeyShortcut( + int i, + jni.JObject keyEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onKeyShortcut, + jni.JniCallType.booleanType, + [jni.JValueInt(i), keyEvent.reference]).boolean; + } + + static final _id_onTouchEvent = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onTouchEvent", r"(Landroid/view/MotionEvent;)Z"); + + /// from: public boolean onTouchEvent(android.view.MotionEvent motionEvent) + bool onTouchEvent( + jni.JObject motionEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_onTouchEvent, + jni.JniCallType.booleanType, [motionEvent.reference]).boolean; + } + + static final _id_onTrackballEvent = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onTrackballEvent", r"(Landroid/view/MotionEvent;)Z"); + + /// from: public boolean onTrackballEvent(android.view.MotionEvent motionEvent) + bool onTrackballEvent( + jni.JObject motionEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_onTrackballEvent, + jni.JniCallType.booleanType, [motionEvent.reference]).boolean; + } + + static final _id_onGenericMotionEvent = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onGenericMotionEvent", + r"(Landroid/view/MotionEvent;)Z"); + + /// from: public boolean onGenericMotionEvent(android.view.MotionEvent motionEvent) + bool onGenericMotionEvent( + jni.JObject motionEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onGenericMotionEvent, + jni.JniCallType.booleanType, + [motionEvent.reference]).boolean; + } + + static final _id_onUserInteraction = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onUserInteraction", r"()V"); + + /// from: public void onUserInteraction() + void onUserInteraction() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onUserInteraction, jni.JniCallType.voidType, []).check(); + } + + static final _id_onWindowAttributesChanged = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onWindowAttributesChanged", + r"(Landroid/view/WindowManager$LayoutParams;)V"); + + /// from: public void onWindowAttributesChanged(android.view.WindowManager$LayoutParams layoutParams) + void onWindowAttributesChanged( + jni.JObject layoutParams, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onWindowAttributesChanged, + jni.JniCallType.voidType, + [layoutParams.reference]).check(); + } + + static final _id_onContentChanged = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onContentChanged", r"()V"); + + /// from: public void onContentChanged() + void onContentChanged() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onContentChanged, jni.JniCallType.voidType, []).check(); + } + + static final _id_onWindowFocusChanged = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onWindowFocusChanged", r"(Z)V"); + + /// from: public void onWindowFocusChanged(boolean z) + void onWindowFocusChanged( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onWindowFocusChanged, + jni.JniCallType.voidType, + [z ? 1 : 0]).check(); + } + + static final _id_onAttachedToWindow = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onAttachedToWindow", r"()V"); + + /// from: public void onAttachedToWindow() + void onAttachedToWindow() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_onAttachedToWindow, jni.JniCallType.voidType, []).check(); + } + + static final _id_onDetachedFromWindow = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onDetachedFromWindow", r"()V"); + + /// from: public void onDetachedFromWindow() + void onDetachedFromWindow() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_onDetachedFromWindow, jni.JniCallType.voidType, []).check(); + } + + static final _id_hasWindowFocus = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"hasWindowFocus", r"()Z"); + + /// from: public boolean hasWindowFocus() + bool hasWindowFocus() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_hasWindowFocus, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_dispatchKeyEvent = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"dispatchKeyEvent", r"(Landroid/view/KeyEvent;)Z"); + + /// from: public boolean dispatchKeyEvent(android.view.KeyEvent keyEvent) + bool dispatchKeyEvent( + jni.JObject keyEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_dispatchKeyEvent, + jni.JniCallType.booleanType, [keyEvent.reference]).boolean; + } + + static final _id_dispatchKeyShortcutEvent = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"dispatchKeyShortcutEvent", + r"(Landroid/view/KeyEvent;)Z"); + + /// from: public boolean dispatchKeyShortcutEvent(android.view.KeyEvent keyEvent) + bool dispatchKeyShortcutEvent( + jni.JObject keyEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_dispatchKeyShortcutEvent, + jni.JniCallType.booleanType, + [keyEvent.reference]).boolean; + } + + static final _id_dispatchTouchEvent = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"dispatchTouchEvent", + r"(Landroid/view/MotionEvent;)Z"); + + /// from: public boolean dispatchTouchEvent(android.view.MotionEvent motionEvent) + bool dispatchTouchEvent( + jni.JObject motionEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_dispatchTouchEvent, + jni.JniCallType.booleanType, + [motionEvent.reference]).boolean; + } + + static final _id_dispatchTrackballEvent = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"dispatchTrackballEvent", + r"(Landroid/view/MotionEvent;)Z"); + + /// from: public boolean dispatchTrackballEvent(android.view.MotionEvent motionEvent) + bool dispatchTrackballEvent( + jni.JObject motionEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_dispatchTrackballEvent, + jni.JniCallType.booleanType, + [motionEvent.reference]).boolean; + } + + static final _id_dispatchGenericMotionEvent = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"dispatchGenericMotionEvent", + r"(Landroid/view/MotionEvent;)Z"); + + /// from: public boolean dispatchGenericMotionEvent(android.view.MotionEvent motionEvent) + bool dispatchGenericMotionEvent( + jni.JObject motionEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_dispatchGenericMotionEvent, + jni.JniCallType.booleanType, + [motionEvent.reference]).boolean; + } + + static final _id_dispatchPopulateAccessibilityEvent = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"dispatchPopulateAccessibilityEvent", + r"(Landroid/view/accessibility/AccessibilityEvent;)Z"); + + /// from: public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent accessibilityEvent) + bool dispatchPopulateAccessibilityEvent( + jni.JObject accessibilityEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_dispatchPopulateAccessibilityEvent, + jni.JniCallType.booleanType, + [accessibilityEvent.reference]).boolean; + } + + static final _id_onCreatePanelView = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onCreatePanelView", r"(I)Landroid/view/View;"); + + /// from: public android.view.View onCreatePanelView(int i) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject onCreatePanelView( + int i, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onCreatePanelView, + jni.JniCallType.objectType, + [jni.JValueInt(i)]).object); + } + + static final _id_onCreatePanelMenu = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onCreatePanelMenu", r"(ILandroid/view/Menu;)Z"); + + /// from: public boolean onCreatePanelMenu(int i, android.view.Menu menu) + bool onCreatePanelMenu( + int i, + jni.JObject menu, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onCreatePanelMenu, + jni.JniCallType.booleanType, + [jni.JValueInt(i), menu.reference]).boolean; + } + + static final _id_onPreparePanel = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onPreparePanel", + r"(ILandroid/view/View;Landroid/view/Menu;)Z"); + + /// from: public boolean onPreparePanel(int i, android.view.View view, android.view.Menu menu) + bool onPreparePanel( + int i, + jni.JObject view, + jni.JObject menu, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onPreparePanel, + jni.JniCallType.booleanType, + [jni.JValueInt(i), view.reference, menu.reference]).boolean; + } + + static final _id_onMenuOpened = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onMenuOpened", r"(ILandroid/view/Menu;)Z"); + + /// from: public boolean onMenuOpened(int i, android.view.Menu menu) + bool onMenuOpened( + int i, + jni.JObject menu, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onMenuOpened, + jni.JniCallType.booleanType, + [jni.JValueInt(i), menu.reference]).boolean; + } + + static final _id_onMenuItemSelected = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onMenuItemSelected", r"(ILandroid/view/MenuItem;)Z"); + + /// from: public boolean onMenuItemSelected(int i, android.view.MenuItem menuItem) + bool onMenuItemSelected( + int i, + jni.JObject menuItem, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onMenuItemSelected, + jni.JniCallType.booleanType, + [jni.JValueInt(i), menuItem.reference]).boolean; + } + + static final _id_onPanelClosed = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onPanelClosed", r"(ILandroid/view/Menu;)V"); + + /// from: public void onPanelClosed(int i, android.view.Menu menu) + void onPanelClosed( + int i, + jni.JObject menu, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_onPanelClosed, + jni.JniCallType.voidType, [jni.JValueInt(i), menu.reference]).check(); + } + + static final _id_invalidateOptionsMenu = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"invalidateOptionsMenu", r"()V"); + + /// from: public void invalidateOptionsMenu() + void invalidateOptionsMenu() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_invalidateOptionsMenu, jni.JniCallType.voidType, []).check(); + } + + static final _id_onCreateOptionsMenu = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onCreateOptionsMenu", r"(Landroid/view/Menu;)Z"); + + /// from: public boolean onCreateOptionsMenu(android.view.Menu menu) + bool onCreateOptionsMenu( + jni.JObject menu, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onCreateOptionsMenu, + jni.JniCallType.booleanType, + [menu.reference]).boolean; + } + + static final _id_onPrepareOptionsMenu = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onPrepareOptionsMenu", r"(Landroid/view/Menu;)Z"); + + /// from: public boolean onPrepareOptionsMenu(android.view.Menu menu) + bool onPrepareOptionsMenu( + jni.JObject menu, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onPrepareOptionsMenu, + jni.JniCallType.booleanType, + [menu.reference]).boolean; + } + + static final _id_onOptionsItemSelected = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onOptionsItemSelected", + r"(Landroid/view/MenuItem;)Z"); + + /// from: public boolean onOptionsItemSelected(android.view.MenuItem menuItem) + bool onOptionsItemSelected( + jni.JObject menuItem, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onOptionsItemSelected, + jni.JniCallType.booleanType, + [menuItem.reference]).boolean; + } + + static final _id_onNavigateUp = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onNavigateUp", r"()Z"); + + /// from: public boolean onNavigateUp() + bool onNavigateUp() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onNavigateUp, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_onNavigateUpFromChild = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onNavigateUpFromChild", r"(Landroid/app/Activity;)Z"); + + /// from: public boolean onNavigateUpFromChild(android.app.Activity activity) + bool onNavigateUpFromChild( + Activity activity, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onNavigateUpFromChild, + jni.JniCallType.booleanType, + [activity.reference]).boolean; + } + + static final _id_onCreateNavigateUpTaskStack = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onCreateNavigateUpTaskStack", + r"(Landroid/app/TaskStackBuilder;)V"); + + /// from: public void onCreateNavigateUpTaskStack(android.app.TaskStackBuilder taskStackBuilder) + void onCreateNavigateUpTaskStack( + jni.JObject taskStackBuilder, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onCreateNavigateUpTaskStack, + jni.JniCallType.voidType, + [taskStackBuilder.reference]).check(); + } + + static final _id_onPrepareNavigateUpTaskStack = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onPrepareNavigateUpTaskStack", + r"(Landroid/app/TaskStackBuilder;)V"); + + /// from: public void onPrepareNavigateUpTaskStack(android.app.TaskStackBuilder taskStackBuilder) + void onPrepareNavigateUpTaskStack( + jni.JObject taskStackBuilder, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onPrepareNavigateUpTaskStack, + jni.JniCallType.voidType, + [taskStackBuilder.reference]).check(); + } + + static final _id_onOptionsMenuClosed = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onOptionsMenuClosed", r"(Landroid/view/Menu;)V"); + + /// from: public void onOptionsMenuClosed(android.view.Menu menu) + void onOptionsMenuClosed( + jni.JObject menu, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onOptionsMenuClosed, + jni.JniCallType.voidType, + [menu.reference]).check(); + } + + static final _id_openOptionsMenu = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"openOptionsMenu", r"()V"); + + /// from: public void openOptionsMenu() + void openOptionsMenu() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_openOptionsMenu, jni.JniCallType.voidType, []).check(); + } + + static final _id_closeOptionsMenu = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"closeOptionsMenu", r"()V"); + + /// from: public void closeOptionsMenu() + void closeOptionsMenu() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_closeOptionsMenu, jni.JniCallType.voidType, []).check(); + } + + static final _id_onCreateContextMenu = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onCreateContextMenu", + r"(Landroid/view/ContextMenu;Landroid/view/View;Landroid/view/ContextMenu$ContextMenuInfo;)V"); + + /// from: public void onCreateContextMenu(android.view.ContextMenu contextMenu, android.view.View view, android.view.ContextMenu$ContextMenuInfo contextMenuInfo) + void onCreateContextMenu( + jni.JObject contextMenu, + jni.JObject view, + jni.JObject contextMenuInfo, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_onCreateContextMenu, jni.JniCallType.voidType, [ + contextMenu.reference, + view.reference, + contextMenuInfo.reference + ]).check(); + } + + static final _id_registerForContextMenu = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"registerForContextMenu", r"(Landroid/view/View;)V"); + + /// from: public void registerForContextMenu(android.view.View view) + void registerForContextMenu( + jni.JObject view, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_registerForContextMenu, + jni.JniCallType.voidType, + [view.reference]).check(); + } + + static final _id_unregisterForContextMenu = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"unregisterForContextMenu", r"(Landroid/view/View;)V"); + + /// from: public void unregisterForContextMenu(android.view.View view) + void unregisterForContextMenu( + jni.JObject view, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_unregisterForContextMenu, + jni.JniCallType.voidType, + [view.reference]).check(); + } + + static final _id_openContextMenu = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"openContextMenu", r"(Landroid/view/View;)V"); + + /// from: public void openContextMenu(android.view.View view) + void openContextMenu( + jni.JObject view, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_openContextMenu, + jni.JniCallType.voidType, [view.reference]).check(); + } + + static final _id_closeContextMenu = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"closeContextMenu", r"()V"); + + /// from: public void closeContextMenu() + void closeContextMenu() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_closeContextMenu, jni.JniCallType.voidType, []).check(); + } + + static final _id_onContextItemSelected = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onContextItemSelected", + r"(Landroid/view/MenuItem;)Z"); + + /// from: public boolean onContextItemSelected(android.view.MenuItem menuItem) + bool onContextItemSelected( + jni.JObject menuItem, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onContextItemSelected, + jni.JniCallType.booleanType, + [menuItem.reference]).boolean; + } + + static final _id_onContextMenuClosed = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onContextMenuClosed", r"(Landroid/view/Menu;)V"); + + /// from: public void onContextMenuClosed(android.view.Menu menu) + void onContextMenuClosed( + jni.JObject menu, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onContextMenuClosed, + jni.JniCallType.voidType, + [menu.reference]).check(); + } + + static final _id_onCreateDialog = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onCreateDialog", r"(I)Landroid/app/Dialog;"); + + /// from: protected android.app.Dialog onCreateDialog(int i) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject onCreateDialog( + int i, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onCreateDialog, + jni.JniCallType.objectType, + [jni.JValueInt(i)]).object); + } + + static final _id_onCreateDialog1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onCreateDialog", + r"(ILandroid/os/Bundle;)Landroid/app/Dialog;"); + + /// from: protected android.app.Dialog onCreateDialog(int i, android.os.Bundle bundle) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject onCreateDialog1( + int i, + jni.JObject bundle, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onCreateDialog1, + jni.JniCallType.objectType, + [jni.JValueInt(i), bundle.reference]).object); + } + + static final _id_onPrepareDialog = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onPrepareDialog", r"(ILandroid/app/Dialog;)V"); + + /// from: protected void onPrepareDialog(int i, android.app.Dialog dialog) + void onPrepareDialog( + int i, + jni.JObject dialog, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_onPrepareDialog, + jni.JniCallType.voidType, [jni.JValueInt(i), dialog.reference]).check(); + } + + static final _id_onPrepareDialog1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onPrepareDialog", + r"(ILandroid/app/Dialog;Landroid/os/Bundle;)V"); + + /// from: protected void onPrepareDialog(int i, android.app.Dialog dialog, android.os.Bundle bundle) + void onPrepareDialog1( + int i, + jni.JObject dialog, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onPrepareDialog1, + jni.JniCallType.voidType, + [jni.JValueInt(i), dialog.reference, bundle.reference]).check(); + } + + static final _id_showDialog = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"showDialog", r"(I)V"); + + /// from: public final void showDialog(int i) + void showDialog( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_showDialog, + jni.JniCallType.voidType, [jni.JValueInt(i)]).check(); + } + + static final _id_showDialog1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"showDialog", r"(ILandroid/os/Bundle;)Z"); + + /// from: public final boolean showDialog(int i, android.os.Bundle bundle) + bool showDialog1( + int i, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_showDialog1, + jni.JniCallType.booleanType, + [jni.JValueInt(i), bundle.reference]).boolean; + } + + static final _id_dismissDialog = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"dismissDialog", r"(I)V"); + + /// from: public final void dismissDialog(int i) + void dismissDialog( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_dismissDialog, + jni.JniCallType.voidType, [jni.JValueInt(i)]).check(); + } + + static final _id_removeDialog = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"removeDialog", r"(I)V"); + + /// from: public final void removeDialog(int i) + void removeDialog( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_removeDialog, + jni.JniCallType.voidType, [jni.JValueInt(i)]).check(); + } + + static final _id_onSearchRequested = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onSearchRequested", r"(Landroid/view/SearchEvent;)Z"); + + /// from: public boolean onSearchRequested(android.view.SearchEvent searchEvent) + bool onSearchRequested( + jni.JObject searchEvent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onSearchRequested, + jni.JniCallType.booleanType, + [searchEvent.reference]).boolean; + } + + static final _id_onSearchRequested1 = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onSearchRequested", r"()Z"); + + /// from: public boolean onSearchRequested() + bool onSearchRequested1() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_onSearchRequested1, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_getSearchEvent = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getSearchEvent", r"()Landroid/view/SearchEvent;"); + + /// from: public final android.view.SearchEvent getSearchEvent() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getSearchEvent() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_getSearchEvent, jni.JniCallType.objectType, []).object); + } + + static final _id_startSearch = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startSearch", + r"(Ljava/lang/String;ZLandroid/os/Bundle;Z)V"); + + /// from: public void startSearch(java.lang.String string, boolean z, android.os.Bundle bundle, boolean z1) + void startSearch( + jni.JString string, + bool z, + jni.JObject bundle, + bool z1, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startSearch, + jni.JniCallType.voidType, + [string.reference, z ? 1 : 0, bundle.reference, z1 ? 1 : 0]).check(); + } + + static final _id_triggerSearch = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"triggerSearch", + r"(Ljava/lang/String;Landroid/os/Bundle;)V"); + + /// from: public void triggerSearch(java.lang.String string, android.os.Bundle bundle) + void triggerSearch( + jni.JString string, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_triggerSearch, + jni.JniCallType.voidType, [string.reference, bundle.reference]).check(); + } + + static final _id_takeKeyEvents = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"takeKeyEvents", r"(Z)V"); + + /// from: public void takeKeyEvents(boolean z) + void takeKeyEvents( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_takeKeyEvents, + jni.JniCallType.voidType, [z ? 1 : 0]).check(); + } + + static final _id_requestWindowFeature = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"requestWindowFeature", r"(I)Z"); + + /// from: public final boolean requestWindowFeature(int i) + bool requestWindowFeature( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_requestWindowFeature, + jni.JniCallType.booleanType, + [jni.JValueInt(i)]).boolean; + } + + static final _id_setFeatureDrawableResource = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setFeatureDrawableResource", r"(II)V"); + + /// from: public final void setFeatureDrawableResource(int i, int i1) + void setFeatureDrawableResource( + int i, + int i1, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setFeatureDrawableResource, + jni.JniCallType.voidType, + [jni.JValueInt(i), jni.JValueInt(i1)]).check(); + } + + static final _id_setFeatureDrawableUri = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"setFeatureDrawableUri", r"(ILandroid/net/Uri;)V"); + + /// from: public final void setFeatureDrawableUri(int i, android.net.Uri uri) + void setFeatureDrawableUri( + int i, + jni.JObject uri, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setFeatureDrawableUri, + jni.JniCallType.voidType, + [jni.JValueInt(i), uri.reference]).check(); + } + + static final _id_setFeatureDrawable = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"setFeatureDrawable", + r"(ILandroid/graphics/drawable/Drawable;)V"); + + /// from: public final void setFeatureDrawable(int i, android.graphics.drawable.Drawable drawable) + void setFeatureDrawable( + int i, + jni.JObject drawable, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setFeatureDrawable, + jni.JniCallType.voidType, + [jni.JValueInt(i), drawable.reference]).check(); + } + + static final _id_setFeatureDrawableAlpha = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setFeatureDrawableAlpha", r"(II)V"); + + /// from: public final void setFeatureDrawableAlpha(int i, int i1) + void setFeatureDrawableAlpha( + int i, + int i1, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setFeatureDrawableAlpha, + jni.JniCallType.voidType, + [jni.JValueInt(i), jni.JValueInt(i1)]).check(); + } + + static final _id_getLayoutInflater = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"getLayoutInflater", + r"()Landroid/view/LayoutInflater;"); + + /// from: public android.view.LayoutInflater getLayoutInflater() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getLayoutInflater() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getLayoutInflater, + jni.JniCallType.objectType, []).object); + } + + static final _id_getMenuInflater = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getMenuInflater", r"()Landroid/view/MenuInflater;"); + + /// from: public android.view.MenuInflater getMenuInflater() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getMenuInflater() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_getMenuInflater, jni.JniCallType.objectType, []).object); + } + + static final _id_setTheme = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"setTheme", r"(I)V"); + + /// from: public void setTheme(int i) + void setTheme( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setTheme, + jni.JniCallType.voidType, [jni.JValueInt(i)]).check(); + } + + static final _id_onApplyThemeResource = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onApplyThemeResource", + r"(Landroid/content/res/Resources$Theme;IZ)V"); + + /// from: protected void onApplyThemeResource(android.content.res.Resources$Theme theme, int i, boolean z) + void onApplyThemeResource( + jni.JObject theme, + int i, + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onApplyThemeResource, + jni.JniCallType.voidType, + [theme.reference, jni.JValueInt(i), z ? 1 : 0]).check(); + } + + static final _id_requestPermissions = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"requestPermissions", r"([Ljava/lang/String;I)V"); + + /// from: public final void requestPermissions(java.lang.String[] strings, int i) + void requestPermissions( + jni.JArray strings, + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_requestPermissions, + jni.JniCallType.voidType, + [strings.reference, jni.JValueInt(i)]).check(); + } + + static final _id_onRequestPermissionsResult = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onRequestPermissionsResult", + r"(I[Ljava/lang/String;[I)V"); + + /// from: public void onRequestPermissionsResult(int i, java.lang.String[] strings, int[] is) + void onRequestPermissionsResult( + int i, + jni.JArray strings, + jni.JArray is0, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onRequestPermissionsResult, + jni.JniCallType.voidType, + [jni.JValueInt(i), strings.reference, is0.reference]).check(); + } + + static final _id_shouldShowRequestPermissionRationale = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"shouldShowRequestPermissionRationale", + r"(Ljava/lang/String;)Z"); + + /// from: public boolean shouldShowRequestPermissionRationale(java.lang.String string) + bool shouldShowRequestPermissionRationale( + jni.JString string, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_shouldShowRequestPermissionRationale, + jni.JniCallType.booleanType, + [string.reference]).boolean; + } + + static final _id_startActivityForResult = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startActivityForResult", + r"(Landroid/content/Intent;I)V"); + + /// from: public void startActivityForResult(android.content.Intent intent, int i) + void startActivityForResult( + jni.JObject intent, + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startActivityForResult, + jni.JniCallType.voidType, + [intent.reference, jni.JValueInt(i)]).check(); + } + + static final _id_startActivityForResult1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startActivityForResult", + r"(Landroid/content/Intent;ILandroid/os/Bundle;)V"); + + /// from: public void startActivityForResult(android.content.Intent intent, int i, android.os.Bundle bundle) + void startActivityForResult1( + jni.JObject intent, + int i, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startActivityForResult1, + jni.JniCallType.voidType, + [intent.reference, jni.JValueInt(i), bundle.reference]).check(); + } + + static final _id_isActivityTransitionRunning = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"isActivityTransitionRunning", r"()Z"); + + /// from: public boolean isActivityTransitionRunning() + bool isActivityTransitionRunning() { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_isActivityTransitionRunning, + jni.JniCallType.booleanType, []).boolean; + } + + static final _id_startIntentSenderForResult = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startIntentSenderForResult", + r"(Landroid/content/IntentSender;ILandroid/content/Intent;III)V"); + + /// from: public void startIntentSenderForResult(android.content.IntentSender intentSender, int i, android.content.Intent intent, int i1, int i2, int i3) + void startIntentSenderForResult( + jni.JObject intentSender, + int i, + jni.JObject intent, + int i1, + int i2, + int i3, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_startIntentSenderForResult, jni.JniCallType.voidType, [ + intentSender.reference, + jni.JValueInt(i), + intent.reference, + jni.JValueInt(i1), + jni.JValueInt(i2), + jni.JValueInt(i3) + ]).check(); + } + + static final _id_startIntentSenderForResult1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startIntentSenderForResult", + r"(Landroid/content/IntentSender;ILandroid/content/Intent;IIILandroid/os/Bundle;)V"); + + /// from: public void startIntentSenderForResult(android.content.IntentSender intentSender, int i, android.content.Intent intent, int i1, int i2, int i3, android.os.Bundle bundle) + void startIntentSenderForResult1( + jni.JObject intentSender, + int i, + jni.JObject intent, + int i1, + int i2, + int i3, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_startIntentSenderForResult1, jni.JniCallType.voidType, [ + intentSender.reference, + jni.JValueInt(i), + intent.reference, + jni.JValueInt(i1), + jni.JValueInt(i2), + jni.JValueInt(i3), + bundle.reference + ]).check(); + } + + static final _id_startActivity = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"startActivity", r"(Landroid/content/Intent;)V"); + + /// from: public void startActivity(android.content.Intent intent) + void startActivity( + jni.JObject intent, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_startActivity, + jni.JniCallType.voidType, [intent.reference]).check(); + } + + static final _id_startActivity1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startActivity", + r"(Landroid/content/Intent;Landroid/os/Bundle;)V"); + + /// from: public void startActivity(android.content.Intent intent, android.os.Bundle bundle) + void startActivity1( + jni.JObject intent, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_startActivity1, + jni.JniCallType.voidType, [intent.reference, bundle.reference]).check(); + } + + static final _id_startActivities = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"startActivities", r"([Landroid/content/Intent;)V"); + + /// from: public void startActivities(android.content.Intent[] intents) + void startActivities( + jni.JArray intents, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_startActivities, + jni.JniCallType.voidType, [intents.reference]).check(); + } + + static final _id_startActivities1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startActivities", + r"([Landroid/content/Intent;Landroid/os/Bundle;)V"); + + /// from: public void startActivities(android.content.Intent[] intents, android.os.Bundle bundle) + void startActivities1( + jni.JArray intents, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startActivities1, + jni.JniCallType.voidType, + [intents.reference, bundle.reference]).check(); + } + + static final _id_startIntentSender = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startIntentSender", + r"(Landroid/content/IntentSender;Landroid/content/Intent;III)V"); + + /// from: public void startIntentSender(android.content.IntentSender intentSender, android.content.Intent intent, int i, int i1, int i2) + void startIntentSender( + jni.JObject intentSender, + jni.JObject intent, + int i, + int i1, + int i2, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_startIntentSender, jni.JniCallType.voidType, [ + intentSender.reference, + intent.reference, + jni.JValueInt(i), + jni.JValueInt(i1), + jni.JValueInt(i2) + ]).check(); + } + + static final _id_startIntentSender1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startIntentSender", + r"(Landroid/content/IntentSender;Landroid/content/Intent;IIILandroid/os/Bundle;)V"); + + /// from: public void startIntentSender(android.content.IntentSender intentSender, android.content.Intent intent, int i, int i1, int i2, android.os.Bundle bundle) + void startIntentSender1( + jni.JObject intentSender, + jni.JObject intent, + int i, + int i1, + int i2, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_startIntentSender1, jni.JniCallType.voidType, [ + intentSender.reference, + intent.reference, + jni.JValueInt(i), + jni.JValueInt(i1), + jni.JValueInt(i2), + bundle.reference + ]).check(); + } + + static final _id_startActivityIfNeeded = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startActivityIfNeeded", + r"(Landroid/content/Intent;I)Z"); + + /// from: public boolean startActivityIfNeeded(android.content.Intent intent, int i) + bool startActivityIfNeeded( + jni.JObject intent, + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startActivityIfNeeded, + jni.JniCallType.booleanType, + [intent.reference, jni.JValueInt(i)]).boolean; + } + + static final _id_startActivityIfNeeded1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startActivityIfNeeded", + r"(Landroid/content/Intent;ILandroid/os/Bundle;)Z"); + + /// from: public boolean startActivityIfNeeded(android.content.Intent intent, int i, android.os.Bundle bundle) + bool startActivityIfNeeded1( + jni.JObject intent, + int i, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startActivityIfNeeded1, + jni.JniCallType.booleanType, + [intent.reference, jni.JValueInt(i), bundle.reference]).boolean; + } + + static final _id_startNextMatchingActivity = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startNextMatchingActivity", + r"(Landroid/content/Intent;)Z"); + + /// from: public boolean startNextMatchingActivity(android.content.Intent intent) + bool startNextMatchingActivity( + jni.JObject intent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startNextMatchingActivity, + jni.JniCallType.booleanType, + [intent.reference]).boolean; + } + + static final _id_startNextMatchingActivity1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startNextMatchingActivity", + r"(Landroid/content/Intent;Landroid/os/Bundle;)Z"); + + /// from: public boolean startNextMatchingActivity(android.content.Intent intent, android.os.Bundle bundle) + bool startNextMatchingActivity1( + jni.JObject intent, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startNextMatchingActivity1, + jni.JniCallType.booleanType, + [intent.reference, bundle.reference]).boolean; + } + + static final _id_startActivityFromChild = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startActivityFromChild", + r"(Landroid/app/Activity;Landroid/content/Intent;I)V"); + + /// from: public void startActivityFromChild(android.app.Activity activity, android.content.Intent intent, int i) + void startActivityFromChild( + Activity activity, + jni.JObject intent, + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startActivityFromChild, + jni.JniCallType.voidType, + [activity.reference, intent.reference, jni.JValueInt(i)]).check(); + } + + static final _id_startActivityFromChild1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startActivityFromChild", + r"(Landroid/app/Activity;Landroid/content/Intent;ILandroid/os/Bundle;)V"); + + /// from: public void startActivityFromChild(android.app.Activity activity, android.content.Intent intent, int i, android.os.Bundle bundle) + void startActivityFromChild1( + Activity activity, + jni.JObject intent, + int i, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_startActivityFromChild1, jni.JniCallType.voidType, [ + activity.reference, + intent.reference, + jni.JValueInt(i), + bundle.reference + ]).check(); + } + + static final _id_startActivityFromFragment = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startActivityFromFragment", + r"(Landroid/app/Fragment;Landroid/content/Intent;I)V"); + + /// from: public void startActivityFromFragment(android.app.Fragment fragment, android.content.Intent intent, int i) + void startActivityFromFragment( + jni.JObject fragment, + jni.JObject intent, + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startActivityFromFragment, + jni.JniCallType.voidType, + [fragment.reference, intent.reference, jni.JValueInt(i)]).check(); + } + + static final _id_startActivityFromFragment1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startActivityFromFragment", + r"(Landroid/app/Fragment;Landroid/content/Intent;ILandroid/os/Bundle;)V"); + + /// from: public void startActivityFromFragment(android.app.Fragment fragment, android.content.Intent intent, int i, android.os.Bundle bundle) + void startActivityFromFragment1( + jni.JObject fragment, + jni.JObject intent, + int i, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_startActivityFromFragment1, jni.JniCallType.voidType, [ + fragment.reference, + intent.reference, + jni.JValueInt(i), + bundle.reference + ]).check(); + } + + static final _id_startIntentSenderFromChild = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startIntentSenderFromChild", + r"(Landroid/app/Activity;Landroid/content/IntentSender;ILandroid/content/Intent;III)V"); + + /// from: public void startIntentSenderFromChild(android.app.Activity activity, android.content.IntentSender intentSender, int i, android.content.Intent intent, int i1, int i2, int i3) + void startIntentSenderFromChild( + Activity activity, + jni.JObject intentSender, + int i, + jni.JObject intent, + int i1, + int i2, + int i3, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_startIntentSenderFromChild, jni.JniCallType.voidType, [ + activity.reference, + intentSender.reference, + jni.JValueInt(i), + intent.reference, + jni.JValueInt(i1), + jni.JValueInt(i2), + jni.JValueInt(i3) + ]).check(); + } + + static final _id_startIntentSenderFromChild1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startIntentSenderFromChild", + r"(Landroid/app/Activity;Landroid/content/IntentSender;ILandroid/content/Intent;IIILandroid/os/Bundle;)V"); + + /// from: public void startIntentSenderFromChild(android.app.Activity activity, android.content.IntentSender intentSender, int i, android.content.Intent intent, int i1, int i2, int i3, android.os.Bundle bundle) + void startIntentSenderFromChild1( + Activity activity, + jni.JObject intentSender, + int i, + jni.JObject intent, + int i1, + int i2, + int i3, + jni.JObject bundle, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_startIntentSenderFromChild1, jni.JniCallType.voidType, [ + activity.reference, + intentSender.reference, + jni.JValueInt(i), + intent.reference, + jni.JValueInt(i1), + jni.JValueInt(i2), + jni.JValueInt(i3), + bundle.reference + ]).check(); + } + + static final _id_overrideActivityTransition = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"overrideActivityTransition", r"(III)V"); + + /// from: public void overrideActivityTransition(int i, int i1, int i2) + void overrideActivityTransition( + int i, + int i1, + int i2, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_overrideActivityTransition, + jni.JniCallType.voidType, + [jni.JValueInt(i), jni.JValueInt(i1), jni.JValueInt(i2)]).check(); + } + + static final _id_overrideActivityTransition1 = jni.Jni.accessors + .getMethodIDOf( + _class.reference, r"overrideActivityTransition", r"(IIII)V"); + + /// from: public void overrideActivityTransition(int i, int i1, int i2, int i3) + void overrideActivityTransition1( + int i, + int i1, + int i2, + int i3, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_overrideActivityTransition1, jni.JniCallType.voidType, [ + jni.JValueInt(i), + jni.JValueInt(i1), + jni.JValueInt(i2), + jni.JValueInt(i3) + ]).check(); + } + + static final _id_clearOverrideActivityTransition = jni.Jni.accessors + .getMethodIDOf( + _class.reference, r"clearOverrideActivityTransition", r"(I)V"); + + /// from: public void clearOverrideActivityTransition(int i) + void clearOverrideActivityTransition( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_clearOverrideActivityTransition, + jni.JniCallType.voidType, + [jni.JValueInt(i)]).check(); + } + + static final _id_overridePendingTransition = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"overridePendingTransition", r"(II)V"); + + /// from: public void overridePendingTransition(int i, int i1) + void overridePendingTransition( + int i, + int i1, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_overridePendingTransition, + jni.JniCallType.voidType, + [jni.JValueInt(i), jni.JValueInt(i1)]).check(); + } + + static final _id_overridePendingTransition1 = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"overridePendingTransition", r"(III)V"); + + /// from: public void overridePendingTransition(int i, int i1, int i2) + void overridePendingTransition1( + int i, + int i1, + int i2, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_overridePendingTransition1, + jni.JniCallType.voidType, + [jni.JValueInt(i), jni.JValueInt(i1), jni.JValueInt(i2)]).check(); + } + + static final _id_setResult = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"setResult", r"(I)V"); + + /// from: public final void setResult(int i) + void setResult( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setResult, + jni.JniCallType.voidType, [jni.JValueInt(i)]).check(); + } + + static final _id_setResult1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"setResult", r"(ILandroid/content/Intent;)V"); + + /// from: public final void setResult(int i, android.content.Intent intent) + void setResult1( + int i, + jni.JObject intent, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setResult1, + jni.JniCallType.voidType, [jni.JValueInt(i), intent.reference]).check(); + } + + static final _id_getReferrer = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"getReferrer", r"()Landroid/net/Uri;"); + + /// from: public android.net.Uri getReferrer() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getReferrer() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_getReferrer, jni.JniCallType.objectType, []).object); + } + + static final _id_onProvideReferrer = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onProvideReferrer", r"()Landroid/net/Uri;"); + + /// from: public android.net.Uri onProvideReferrer() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject onProvideReferrer() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onProvideReferrer, + jni.JniCallType.objectType, []).object); + } + + static final _id_getCallingPackage = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getCallingPackage", r"()Ljava/lang/String;"); + + /// from: public java.lang.String getCallingPackage() + /// The returned object must be released after use, by calling the [release] method. + jni.JString getCallingPackage() { + return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getCallingPackage, + jni.JniCallType.objectType, []).object); + } + + static final _id_getCallingActivity = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"getCallingActivity", + r"()Landroid/content/ComponentName;"); + + /// from: public android.content.ComponentName getCallingActivity() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getCallingActivity() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getCallingActivity, + jni.JniCallType.objectType, []).object); + } + + static final _id_getLaunchedFromUid = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"getLaunchedFromUid", r"()I"); + + /// from: public int getLaunchedFromUid() + int getLaunchedFromUid() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_getLaunchedFromUid, jni.JniCallType.intType, []).integer; + } + + static final _id_getLaunchedFromPackage = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getLaunchedFromPackage", r"()Ljava/lang/String;"); + + /// from: public java.lang.String getLaunchedFromPackage() + /// The returned object must be released after use, by calling the [release] method. + jni.JString getLaunchedFromPackage() { + return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getLaunchedFromPackage, + jni.JniCallType.objectType, []).object); + } + + static final _id_setVisible = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"setVisible", r"(Z)V"); + + /// from: public void setVisible(boolean z) + void setVisible( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setVisible, + jni.JniCallType.voidType, [z ? 1 : 0]).check(); + } + + static final _id_isFinishing = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"isFinishing", r"()Z"); + + /// from: public boolean isFinishing() + bool isFinishing() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_isFinishing, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_isDestroyed = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"isDestroyed", r"()Z"); + + /// from: public boolean isDestroyed() + bool isDestroyed() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_isDestroyed, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_isChangingConfigurations = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"isChangingConfigurations", r"()Z"); + + /// from: public boolean isChangingConfigurations() + bool isChangingConfigurations() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_isChangingConfigurations, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_recreate = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"recreate", r"()V"); + + /// from: public void recreate() + void recreate() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_recreate, jni.JniCallType.voidType, []).check(); + } + + static final _id_finish = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"finish", r"()V"); + + /// from: public void finish() + void finish() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_finish, jni.JniCallType.voidType, []).check(); + } + + static final _id_finishAffinity = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"finishAffinity", r"()V"); + + /// from: public void finishAffinity() + void finishAffinity() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_finishAffinity, jni.JniCallType.voidType, []).check(); + } + + static final _id_finishFromChild = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"finishFromChild", r"(Landroid/app/Activity;)V"); + + /// from: public void finishFromChild(android.app.Activity activity) + void finishFromChild( + Activity activity, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_finishFromChild, + jni.JniCallType.voidType, [activity.reference]).check(); + } + + static final _id_finishAfterTransition = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"finishAfterTransition", r"()V"); + + /// from: public void finishAfterTransition() + void finishAfterTransition() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_finishAfterTransition, jni.JniCallType.voidType, []).check(); + } + + static final _id_finishActivity = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"finishActivity", r"(I)V"); + + /// from: public void finishActivity(int i) + void finishActivity( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_finishActivity, + jni.JniCallType.voidType, [jni.JValueInt(i)]).check(); + } + + static final _id_finishActivityFromChild = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"finishActivityFromChild", + r"(Landroid/app/Activity;I)V"); + + /// from: public void finishActivityFromChild(android.app.Activity activity, int i) + void finishActivityFromChild( + Activity activity, + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_finishActivityFromChild, + jni.JniCallType.voidType, + [activity.reference, jni.JValueInt(i)]).check(); + } + + static final _id_finishAndRemoveTask = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"finishAndRemoveTask", r"()V"); + + /// from: public void finishAndRemoveTask() + void finishAndRemoveTask() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_finishAndRemoveTask, jni.JniCallType.voidType, []).check(); + } + + static final _id_releaseInstance = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"releaseInstance", r"()Z"); + + /// from: public boolean releaseInstance() + bool releaseInstance() { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_releaseInstance, + jni.JniCallType.booleanType, []).boolean; + } + + static final _id_onActivityResult = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onActivityResult", r"(IILandroid/content/Intent;)V"); + + /// from: protected void onActivityResult(int i, int i1, android.content.Intent intent) + void onActivityResult( + int i, + int i1, + jni.JObject intent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onActivityResult, + jni.JniCallType.voidType, + [jni.JValueInt(i), jni.JValueInt(i1), intent.reference]).check(); + } + + static final _id_onActivityReenter = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onActivityReenter", r"(ILandroid/content/Intent;)V"); + + /// from: public void onActivityReenter(int i, android.content.Intent intent) + void onActivityReenter( + int i, + jni.JObject intent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onActivityReenter, + jni.JniCallType.voidType, + [jni.JValueInt(i), intent.reference]).check(); + } + + static final _id_createPendingResult = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"createPendingResult", + r"(ILandroid/content/Intent;I)Landroid/app/PendingIntent;"); + + /// from: public android.app.PendingIntent createPendingResult(int i, android.content.Intent intent, int i1) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject createPendingResult( + int i, + jni.JObject intent, + int i1, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_createPendingResult, + jni.JniCallType.objectType, + [jni.JValueInt(i), intent.reference, jni.JValueInt(i1)]).object); + } + + static final _id_setRequestedOrientation = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setRequestedOrientation", r"(I)V"); + + /// from: public void setRequestedOrientation(int i) + void setRequestedOrientation( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setRequestedOrientation, + jni.JniCallType.voidType, + [jni.JValueInt(i)]).check(); + } + + static final _id_getRequestedOrientation = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"getRequestedOrientation", r"()I"); + + /// from: public int getRequestedOrientation() + int getRequestedOrientation() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_getRequestedOrientation, jni.JniCallType.intType, []).integer; + } + + static final _id_getTaskId = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"getTaskId", r"()I"); + + /// from: public int getTaskId() + int getTaskId() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_getTaskId, jni.JniCallType.intType, []).integer; + } + + static final _id_isTaskRoot = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"isTaskRoot", r"()Z"); + + /// from: public boolean isTaskRoot() + bool isTaskRoot() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_isTaskRoot, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_moveTaskToBack = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"moveTaskToBack", r"(Z)Z"); + + /// from: public boolean moveTaskToBack(boolean z) + bool moveTaskToBack( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_moveTaskToBack, + jni.JniCallType.booleanType, [z ? 1 : 0]).boolean; + } + + static final _id_getLocalClassName = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getLocalClassName", r"()Ljava/lang/String;"); + + /// from: public java.lang.String getLocalClassName() + /// The returned object must be released after use, by calling the [release] method. + jni.JString getLocalClassName() { + return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getLocalClassName, + jni.JniCallType.objectType, []).object); + } + + static final _id_getComponentName = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"getComponentName", + r"()Landroid/content/ComponentName;"); + + /// from: public android.content.ComponentName getComponentName() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getComponentName() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getComponentName, + jni.JniCallType.objectType, []).object); + } + + static final _id_getPreferences = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"getPreferences", + r"(I)Landroid/content/SharedPreferences;"); + + /// from: public android.content.SharedPreferences getPreferences(int i) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getPreferences( + int i, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getPreferences, + jni.JniCallType.objectType, + [jni.JValueInt(i)]).object); + } + + static final _id_isLaunchedFromBubble = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"isLaunchedFromBubble", r"()Z"); + + /// from: public boolean isLaunchedFromBubble() + bool isLaunchedFromBubble() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_isLaunchedFromBubble, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_getSystemService = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"getSystemService", + r"(Ljava/lang/String;)Ljava/lang/Object;"); + + /// from: public java.lang.Object getSystemService(java.lang.String string) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getSystemService( + jni.JString string, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getSystemService, + jni.JniCallType.objectType, + [string.reference]).object); + } + + static final _id_setTitle = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"setTitle", r"(Ljava/lang/CharSequence;)V"); + + /// from: public void setTitle(java.lang.CharSequence charSequence) + void setTitle( + jni.JObject charSequence, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setTitle, + jni.JniCallType.voidType, [charSequence.reference]).check(); + } + + static final _id_setTitle1 = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"setTitle", r"(I)V"); + + /// from: public void setTitle(int i) + void setTitle1( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setTitle1, + jni.JniCallType.voidType, [jni.JValueInt(i)]).check(); + } + + static final _id_setTitleColor = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setTitleColor", r"(I)V"); + + /// from: public void setTitleColor(int i) + void setTitleColor( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setTitleColor, + jni.JniCallType.voidType, [jni.JValueInt(i)]).check(); + } + + static final _id_getTitle = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"getTitle", r"()Ljava/lang/CharSequence;"); + + /// from: public final java.lang.CharSequence getTitle() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getTitle() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_getTitle, jni.JniCallType.objectType, []).object); + } + + static final _id_getTitleColor = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"getTitleColor", r"()I"); + + /// from: public final int getTitleColor() + int getTitleColor() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_getTitleColor, jni.JniCallType.intType, []).integer; + } + + static final _id_onTitleChanged = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"onTitleChanged", r"(Ljava/lang/CharSequence;I)V"); + + /// from: protected void onTitleChanged(java.lang.CharSequence charSequence, int i) + void onTitleChanged( + jni.JObject charSequence, + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onTitleChanged, + jni.JniCallType.voidType, + [charSequence.reference, jni.JValueInt(i)]).check(); + } + + static final _id_onChildTitleChanged = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onChildTitleChanged", + r"(Landroid/app/Activity;Ljava/lang/CharSequence;)V"); + + /// from: protected void onChildTitleChanged(android.app.Activity activity, java.lang.CharSequence charSequence) + void onChildTitleChanged( + Activity activity, + jni.JObject charSequence, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onChildTitleChanged, + jni.JniCallType.voidType, + [activity.reference, charSequence.reference]).check(); + } + + static final _id_setTaskDescription = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"setTaskDescription", + r"(Landroid/app/ActivityManager$TaskDescription;)V"); + + /// from: public void setTaskDescription(android.app.ActivityManager$TaskDescription taskDescription) + void setTaskDescription( + jni.JObject taskDescription, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setTaskDescription, + jni.JniCallType.voidType, + [taskDescription.reference]).check(); + } + + static final _id_setProgressBarVisibility = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setProgressBarVisibility", r"(Z)V"); + + /// from: public final void setProgressBarVisibility(boolean z) + void setProgressBarVisibility( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setProgressBarVisibility, + jni.JniCallType.voidType, + [z ? 1 : 0]).check(); + } + + static final _id_setProgressBarIndeterminateVisibility = jni.Jni.accessors + .getMethodIDOf( + _class.reference, r"setProgressBarIndeterminateVisibility", r"(Z)V"); + + /// from: public final void setProgressBarIndeterminateVisibility(boolean z) + void setProgressBarIndeterminateVisibility( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setProgressBarIndeterminateVisibility, + jni.JniCallType.voidType, + [z ? 1 : 0]).check(); + } + + static final _id_setProgressBarIndeterminate = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setProgressBarIndeterminate", r"(Z)V"); + + /// from: public final void setProgressBarIndeterminate(boolean z) + void setProgressBarIndeterminate( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setProgressBarIndeterminate, + jni.JniCallType.voidType, + [z ? 1 : 0]).check(); + } + + static final _id_setProgress = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setProgress", r"(I)V"); + + /// from: public final void setProgress(int i) + void setProgress( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setProgress, + jni.JniCallType.voidType, [jni.JValueInt(i)]).check(); + } + + static final _id_setSecondaryProgress = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setSecondaryProgress", r"(I)V"); + + /// from: public final void setSecondaryProgress(int i) + void setSecondaryProgress( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setSecondaryProgress, + jni.JniCallType.voidType, + [jni.JValueInt(i)]).check(); + } + + static final _id_setVolumeControlStream = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setVolumeControlStream", r"(I)V"); + + /// from: public final void setVolumeControlStream(int i) + void setVolumeControlStream( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setVolumeControlStream, + jni.JniCallType.voidType, + [jni.JValueInt(i)]).check(); + } + + static final _id_getVolumeControlStream = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"getVolumeControlStream", r"()I"); + + /// from: public final int getVolumeControlStream() + int getVolumeControlStream() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_getVolumeControlStream, jni.JniCallType.intType, []).integer; + } + + static final _id_setMediaController = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"setMediaController", + r"(Landroid/media/session/MediaController;)V"); + + /// from: public final void setMediaController(android.media.session.MediaController mediaController) + void setMediaController( + jni.JObject mediaController, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setMediaController, + jni.JniCallType.voidType, + [mediaController.reference]).check(); + } + + static final _id_getMediaController = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"getMediaController", + r"()Landroid/media/session/MediaController;"); + + /// from: public final android.media.session.MediaController getMediaController() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getMediaController() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getMediaController, + jni.JniCallType.objectType, []).object); + } + + static final _id_runOnUiThread = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"runOnUiThread", r"(Ljava/lang/Runnable;)V"); + + /// from: public final void runOnUiThread(java.lang.Runnable runnable) + void runOnUiThread( + jni.JObject runnable, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_runOnUiThread, + jni.JniCallType.voidType, [runnable.reference]).check(); + } + + static final _id_onCreateView = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onCreateView", + r"(Ljava/lang/String;Landroid/content/Context;Landroid/util/AttributeSet;)Landroid/view/View;"); + + /// from: public android.view.View onCreateView(java.lang.String string, android.content.Context context, android.util.AttributeSet attributeSet) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject onCreateView( + jni.JString string, + jni.JObject context, + jni.JObject attributeSet, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onCreateView, + jni.JniCallType.objectType, + [string.reference, context.reference, attributeSet.reference]).object); + } + + static final _id_onCreateView1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onCreateView", + r"(Landroid/view/View;Ljava/lang/String;Landroid/content/Context;Landroid/util/AttributeSet;)Landroid/view/View;"); + + /// from: public android.view.View onCreateView(android.view.View view, java.lang.String string, android.content.Context context, android.util.AttributeSet attributeSet) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject onCreateView1( + jni.JObject view, + jni.JString string, + jni.JObject context, + jni.JObject attributeSet, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, _id_onCreateView1, jni.JniCallType.objectType, [ + view.reference, + string.reference, + context.reference, + attributeSet.reference + ]).object); + } + + static final _id_dump = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"dump", + r"(Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/PrintWriter;[Ljava/lang/String;)V"); + + /// from: public void dump(java.lang.String string, java.io.FileDescriptor fileDescriptor, java.io.PrintWriter printWriter, java.lang.String[] strings) + void dump( + jni.JString string, + jni.JObject fileDescriptor, + jni.JObject printWriter, + jni.JArray strings, + ) { + return jni.Jni.accessors + .callMethodWithArgs(reference, _id_dump, jni.JniCallType.voidType, [ + string.reference, + fileDescriptor.reference, + printWriter.reference, + strings.reference + ]).check(); + } + + static final _id_isImmersive = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"isImmersive", r"()Z"); + + /// from: public boolean isImmersive() + bool isImmersive() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_isImmersive, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_setTranslucent = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setTranslucent", r"(Z)Z"); + + /// from: public boolean setTranslucent(boolean z) + bool setTranslucent( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setTranslucent, + jni.JniCallType.booleanType, [z ? 1 : 0]).boolean; + } + + static final _id_requestVisibleBehind = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"requestVisibleBehind", r"(Z)Z"); + + /// from: public boolean requestVisibleBehind(boolean z) + bool requestVisibleBehind( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_requestVisibleBehind, + jni.JniCallType.booleanType, + [z ? 1 : 0]).boolean; + } + + static final _id_onVisibleBehindCanceled = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onVisibleBehindCanceled", r"()V"); + + /// from: public void onVisibleBehindCanceled() + void onVisibleBehindCanceled() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_onVisibleBehindCanceled, jni.JniCallType.voidType, []).check(); + } + + static final _id_onEnterAnimationComplete = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onEnterAnimationComplete", r"()V"); + + /// from: public void onEnterAnimationComplete() + void onEnterAnimationComplete() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_onEnterAnimationComplete, jni.JniCallType.voidType, []).check(); + } + + static final _id_setImmersive = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setImmersive", r"(Z)V"); + + /// from: public void setImmersive(boolean z) + void setImmersive( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setImmersive, + jni.JniCallType.voidType, [z ? 1 : 0]).check(); + } + + static final _id_setVrModeEnabled = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"setVrModeEnabled", + r"(ZLandroid/content/ComponentName;)V"); + + /// from: public void setVrModeEnabled(boolean z, android.content.ComponentName componentName) + void setVrModeEnabled( + bool z, + jni.JObject componentName, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setVrModeEnabled, + jni.JniCallType.voidType, [z ? 1 : 0, componentName.reference]).check(); + } + + static final _id_startActionMode = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startActionMode", + r"(Landroid/view/ActionMode$Callback;)Landroid/view/ActionMode;"); + + /// from: public android.view.ActionMode startActionMode(android.view.ActionMode$Callback callback) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject startActionMode( + jni.JObject callback, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startActionMode, + jni.JniCallType.objectType, + [callback.reference]).object); + } + + static final _id_startActionMode1 = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"startActionMode", + r"(Landroid/view/ActionMode$Callback;I)Landroid/view/ActionMode;"); + + /// from: public android.view.ActionMode startActionMode(android.view.ActionMode$Callback callback, int i) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject startActionMode1( + jni.JObject callback, + int i, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startActionMode1, + jni.JniCallType.objectType, + [callback.reference, jni.JValueInt(i)]).object); + } + + static final _id_onWindowStartingActionMode = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onWindowStartingActionMode", + r"(Landroid/view/ActionMode$Callback;)Landroid/view/ActionMode;"); + + /// from: public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode$Callback callback) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject onWindowStartingActionMode( + jni.JObject callback, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onWindowStartingActionMode, + jni.JniCallType.objectType, + [callback.reference]).object); + } + + static final _id_onWindowStartingActionMode1 = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"onWindowStartingActionMode", + r"(Landroid/view/ActionMode$Callback;I)Landroid/view/ActionMode;"); + + /// from: public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode$Callback callback, int i) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject onWindowStartingActionMode1( + jni.JObject callback, + int i, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onWindowStartingActionMode1, + jni.JniCallType.objectType, + [callback.reference, jni.JValueInt(i)]).object); + } + + static final _id_onActionModeStarted = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onActionModeStarted", + r"(Landroid/view/ActionMode;)V"); + + /// from: public void onActionModeStarted(android.view.ActionMode actionMode) + void onActionModeStarted( + jni.JObject actionMode, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onActionModeStarted, + jni.JniCallType.voidType, + [actionMode.reference]).check(); + } + + static final _id_onActionModeFinished = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"onActionModeFinished", + r"(Landroid/view/ActionMode;)V"); + + /// from: public void onActionModeFinished(android.view.ActionMode actionMode) + void onActionModeFinished( + jni.JObject actionMode, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_onActionModeFinished, + jni.JniCallType.voidType, + [actionMode.reference]).check(); + } + + static final _id_shouldUpRecreateTask = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"shouldUpRecreateTask", + r"(Landroid/content/Intent;)Z"); + + /// from: public boolean shouldUpRecreateTask(android.content.Intent intent) + bool shouldUpRecreateTask( + jni.JObject intent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_shouldUpRecreateTask, + jni.JniCallType.booleanType, + [intent.reference]).boolean; + } + + static final _id_navigateUpTo = jni.Jni.accessors.getMethodIDOf( + _class.reference, r"navigateUpTo", r"(Landroid/content/Intent;)Z"); + + /// from: public boolean navigateUpTo(android.content.Intent intent) + bool navigateUpTo( + jni.JObject intent, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_navigateUpTo, + jni.JniCallType.booleanType, [intent.reference]).boolean; + } + + static final _id_navigateUpToFromChild = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"navigateUpToFromChild", + r"(Landroid/app/Activity;Landroid/content/Intent;)Z"); + + /// from: public boolean navigateUpToFromChild(android.app.Activity activity, android.content.Intent intent) + bool navigateUpToFromChild( + Activity activity, + jni.JObject intent, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_navigateUpToFromChild, + jni.JniCallType.booleanType, + [activity.reference, intent.reference]).boolean; + } + + static final _id_getParentActivityIntent = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"getParentActivityIntent", + r"()Landroid/content/Intent;"); + + /// from: public android.content.Intent getParentActivityIntent() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getParentActivityIntent() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getParentActivityIntent, + jni.JniCallType.objectType, []).object); + } + + static final _id_setEnterSharedElementCallback = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setEnterSharedElementCallback", + r"(Landroid/app/SharedElementCallback;)V"); + + /// from: public void setEnterSharedElementCallback(android.app.SharedElementCallback sharedElementCallback) + void setEnterSharedElementCallback( + jni.JObject sharedElementCallback, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setEnterSharedElementCallback, + jni.JniCallType.voidType, + [sharedElementCallback.reference]).check(); + } + + static final _id_setExitSharedElementCallback = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setExitSharedElementCallback", + r"(Landroid/app/SharedElementCallback;)V"); + + /// from: public void setExitSharedElementCallback(android.app.SharedElementCallback sharedElementCallback) + void setExitSharedElementCallback( + jni.JObject sharedElementCallback, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setExitSharedElementCallback, + jni.JniCallType.voidType, + [sharedElementCallback.reference]).check(); + } + + static final _id_postponeEnterTransition = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"postponeEnterTransition", r"()V"); + + /// from: public void postponeEnterTransition() + void postponeEnterTransition() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_postponeEnterTransition, jni.JniCallType.voidType, []).check(); + } + + static final _id_startPostponedEnterTransition = jni.Jni.accessors + .getMethodIDOf( + _class.reference, r"startPostponedEnterTransition", r"()V"); + + /// from: public void startPostponedEnterTransition() + void startPostponedEnterTransition() { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_startPostponedEnterTransition, + jni.JniCallType.voidType, []).check(); + } + + static final _id_requestDragAndDropPermissions = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"requestDragAndDropPermissions", + r"(Landroid/view/DragEvent;)Landroid/view/DragAndDropPermissions;"); + + /// from: public android.view.DragAndDropPermissions requestDragAndDropPermissions(android.view.DragEvent dragEvent) + /// The returned object must be released after use, by calling the [release] method. + jni.JObject requestDragAndDropPermissions( + jni.JObject dragEvent, + ) { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_requestDragAndDropPermissions, + jni.JniCallType.objectType, + [dragEvent.reference]).object); + } + + static final _id_startLockTask = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"startLockTask", r"()V"); + + /// from: public void startLockTask() + void startLockTask() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_startLockTask, jni.JniCallType.voidType, []).check(); + } + + static final _id_stopLockTask = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"stopLockTask", r"()V"); + + /// from: public void stopLockTask() + void stopLockTask() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_stopLockTask, jni.JniCallType.voidType, []).check(); + } + + static final _id_showLockTaskEscapeMessage = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"showLockTaskEscapeMessage", r"()V"); + + /// from: public void showLockTaskEscapeMessage() + void showLockTaskEscapeMessage() { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_showLockTaskEscapeMessage, jni.JniCallType.voidType, []).check(); + } + + static final _id_setRecentsScreenshotEnabled = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setRecentsScreenshotEnabled", r"(Z)V"); + + /// from: public void setRecentsScreenshotEnabled(boolean z) + void setRecentsScreenshotEnabled( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setRecentsScreenshotEnabled, + jni.JniCallType.voidType, + [z ? 1 : 0]).check(); + } + + static final _id_setShowWhenLocked = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setShowWhenLocked", r"(Z)V"); + + /// from: public void setShowWhenLocked(boolean z) + void setShowWhenLocked( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, + _id_setShowWhenLocked, jni.JniCallType.voidType, [z ? 1 : 0]).check(); + } + + static final _id_setInheritShowWhenLocked = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setInheritShowWhenLocked", r"(Z)V"); + + /// from: public void setInheritShowWhenLocked(boolean z) + void setInheritShowWhenLocked( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_setInheritShowWhenLocked, + jni.JniCallType.voidType, + [z ? 1 : 0]).check(); + } + + static final _id_setTurnScreenOn = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"setTurnScreenOn", r"(Z)V"); + + /// from: public void setTurnScreenOn(boolean z) + void setTurnScreenOn( + bool z, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_setTurnScreenOn, + jni.JniCallType.voidType, [z ? 1 : 0]).check(); + } + + static final _id_getOnBackInvokedDispatcher = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"getOnBackInvokedDispatcher", + r"()Landroid/window/OnBackInvokedDispatcher;"); + + /// from: public android.window.OnBackInvokedDispatcher getOnBackInvokedDispatcher() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getOnBackInvokedDispatcher() { + return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs( + reference, + _id_getOnBackInvokedDispatcher, + jni.JniCallType.objectType, []).object); + } + + static final _id_registerScreenCaptureCallback = jni.Jni.accessors.getMethodIDOf( + _class.reference, + r"registerScreenCaptureCallback", + r"(Ljava/util/concurrent/Executor;Landroid/app/Activity$ScreenCaptureCallback;)V"); + + /// from: public void registerScreenCaptureCallback(java.util.concurrent.Executor executor, android.app.Activity$ScreenCaptureCallback screenCaptureCallback) + void registerScreenCaptureCallback( + jni.JObject executor, + Activity_ScreenCaptureCallback screenCaptureCallback, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_registerScreenCaptureCallback, + jni.JniCallType.voidType, + [executor.reference, screenCaptureCallback.reference]).check(); + } + + static final _id_unregisterScreenCaptureCallback = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"unregisterScreenCaptureCallback", + r"(Landroid/app/Activity$ScreenCaptureCallback;)V"); + + /// from: public void unregisterScreenCaptureCallback(android.app.Activity$ScreenCaptureCallback screenCaptureCallback) + void unregisterScreenCaptureCallback( + Activity_ScreenCaptureCallback screenCaptureCallback, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_unregisterScreenCaptureCallback, + jni.JniCallType.voidType, + [screenCaptureCallback.reference]).check(); + } +} + +final class $ActivityType extends jni.JObjType { + const $ActivityType(); + + @override + String get signature => r"Landroid/app/Activity;"; + + @override + Activity fromRef(jni.JObjectPtr ref) => Activity.fromRef(ref); + + @override + jni.JObjType get superType => const jni.JObjectType(); + + @override + final superCount = 1; + + @override + int get hashCode => ($ActivityType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == ($ActivityType) && other is $ActivityType; + } +} diff --git a/packages/celest_core/lib/src/native/darwin/core_foundation.ffi.dart b/packages/celest_core/lib/src/native/darwin/core_foundation.ffi.dart new file mode 100644 index 00000000..baf28626 --- /dev/null +++ b/packages/celest_core/lib/src/native/darwin/core_foundation.ffi.dart @@ -0,0 +1,1950 @@ +// ignore_for_file: type=lint +// ignore_for_file: return_of_invalid_type +// ignore_for_file: unnecessary_non_null_assertion + +// AUTO GENERATED FILE, DO NOT EDIT. +// +// Generated by `package:ffigen`. +import 'dart:ffi' as ffi; + +@ffi.Native() +external double kCFCoreFoundationVersionNumber; + +/// Constant used by some functions to indicate failed searches. +@ffi.Native() +external final int kCFNotFound; + +@ffi.Native() +external int CFNullGetTypeID(); + +/// the singleton null instance +@ffi.Native() +external final CFNullRef kCFNull; + +/// This is a synonym for NULL, if you'd rather use a named constant. +@ffi.Native() +external final CFAllocatorRef kCFAllocatorDefault; + +/// Default system allocator; you rarely need to use this. +@ffi.Native() +external final CFAllocatorRef kCFAllocatorSystemDefault; + +/// This allocator uses malloc(), realloc(), and free(). This should not be +/// generally used; stick to kCFAllocatorDefault whenever possible. This +/// allocator is useful as the "bytesDeallocator" in CFData or +/// "contentsDeallocator" in CFString where the memory was obtained as a +/// result of malloc() type functions. +@ffi.Native() +external final CFAllocatorRef kCFAllocatorMalloc; + +/// This allocator explicitly uses the default malloc zone, returned by +/// malloc_default_zone(). It should only be used when an object is +/// safe to be allocated in non-scanned memory. +@ffi.Native() +external final CFAllocatorRef kCFAllocatorMallocZone; + +/// Null allocator which does nothing and allocates no memory. This allocator +/// is useful as the "bytesDeallocator" in CFData or "contentsDeallocator" +/// in CFString where the memory should not be freed. +@ffi.Native() +external final CFAllocatorRef kCFAllocatorNull; + +/// Special allocator argument to CFAllocatorCreate() which means +/// "use the functions given in the context to allocate the allocator +/// itself as well". +@ffi.Native() +external final CFAllocatorRef kCFAllocatorUseContext; + +@ffi.Native() +external int CFAllocatorGetTypeID(); + +/// Polymorphic CF functions +@ffi.Native() +external int CFGetTypeID( + CFTypeRef cf, +); + +@ffi.Native() +external void CFRelease( + CFTypeRef cf, +); + +/// ! +/// @constant kCFTypeDictionaryKeyCallBacks +/// Predefined CFDictionaryKeyCallBacks structure containing a +/// set of callbacks appropriate for use when the keys of a +/// CFDictionary are all CFTypes. +@ffi.Native() +external final CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks; + +/// ! +/// @constant kCFCopyStringDictionaryKeyCallBacks +/// Predefined CFDictionaryKeyCallBacks structure containing a +/// set of callbacks appropriate for use when the keys of a +/// CFDictionary are all CFStrings, which may be mutable and +/// need to be copied in order to serve as constant keys for +/// the values in the dictionary. +@ffi.Native() +external final CFDictionaryKeyCallBacks kCFCopyStringDictionaryKeyCallBacks; + +/// ! +/// @constant kCFTypeDictionaryValueCallBacks +/// Predefined CFDictionaryValueCallBacks structure containing a set +/// of callbacks appropriate for use when the values in a CFDictionary +/// are all CFTypes. +@ffi.Native() +external final CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks; + +/// ! +/// @function CFDictionaryGetTypeID +/// Returns the type identifier of all CFDictionary instances. +@ffi.Native() +external int CFDictionaryGetTypeID(); + +/// ! +/// @function CFDictionaryCreate +/// Creates a new immutable dictionary with the given values. +/// @param allocator The CFAllocator which should be used to allocate +/// memory for the dictionary and its storage for values. This +/// parameter may be NULL in which case the current default +/// CFAllocator is used. If this reference is not a valid +/// CFAllocator, the behavior is undefined. +/// @param keys A C array of the pointer-sized keys to be used for +/// the parallel C array of values to be put into the dictionary. +/// This parameter may be NULL if the numValues parameter is 0. +/// This C array is not changed or freed by this function. If +/// this parameter is not a valid pointer to a C array of at +/// least numValues pointers, the behavior is undefined. +/// @param values A C array of the pointer-sized values to be in the +/// dictionary. This parameter may be NULL if the numValues +/// parameter is 0. This C array is not changed or freed by +/// this function. If this parameter is not a valid pointer to +/// a C array of at least numValues pointers, the behavior is +/// undefined. +/// @param numValues The number of values to copy from the keys and +/// values C arrays into the CFDictionary. This number will be +/// the count of the dictionary. If this parameter is +/// negative, or greater than the number of values actually +/// in the keys or values C arrays, the behavior is undefined. +/// @param keyCallBacks A pointer to a CFDictionaryKeyCallBacks structure +/// initialized with the callbacks for the dictionary to use on +/// each key in the dictionary. The retain callback will be used +/// within this function, for example, to retain all of the new +/// keys from the keys C array. A copy of the contents of the +/// callbacks structure is made, so that a pointer to a structure +/// on the stack can be passed in, or can be reused for multiple +/// dictionary creations. If the version field of this +/// callbacks structure is not one of the defined ones for +/// CFDictionary, the behavior is undefined. The retain field may +/// be NULL, in which case the CFDictionary will do nothing to add +/// a retain to the keys of the contained values. The release field +/// may be NULL, in which case the CFDictionary will do nothing +/// to remove the dictionary's retain (if any) on the keys when the +/// dictionary is destroyed or a key-value pair is removed. If the +/// copyDescription field is NULL, the dictionary will create a +/// simple description for a key. If the equal field is NULL, the +/// dictionary will use pointer equality to test for equality of +/// keys. If the hash field is NULL, a key will be converted from +/// a pointer to an integer to compute the hash code. This callbacks +/// parameter itself may be NULL, which is treated as if a valid +/// structure of version 0 with all fields NULL had been passed in. +/// Otherwise, if any of the fields are not valid pointers to +/// functions of the correct type, or this parameter is not a +/// valid pointer to a CFDictionaryKeyCallBacks callbacks structure, +/// the behavior is undefined. If any of the keys put into the +/// dictionary is not one understood by one of the callback functions +/// the behavior when that callback function is used is undefined. +/// @param valueCallBacks A pointer to a CFDictionaryValueCallBacks structure +/// initialized with the callbacks for the dictionary to use on +/// each value in the dictionary. The retain callback will be used +/// within this function, for example, to retain all of the new +/// values from the values C array. A copy of the contents of the +/// callbacks structure is made, so that a pointer to a structure +/// on the stack can be passed in, or can be reused for multiple +/// dictionary creations. If the version field of this callbacks +/// structure is not one of the defined ones for CFDictionary, the +/// behavior is undefined. The retain field may be NULL, in which +/// case the CFDictionary will do nothing to add a retain to values +/// as they are put into the dictionary. The release field may be +/// NULL, in which case the CFDictionary will do nothing to remove +/// the dictionary's retain (if any) on the values when the +/// dictionary is destroyed or a key-value pair is removed. If the +/// copyDescription field is NULL, the dictionary will create a +/// simple description for a value. If the equal field is NULL, the +/// dictionary will use pointer equality to test for equality of +/// values. This callbacks parameter itself may be NULL, which is +/// treated as if a valid structure of version 0 with all fields +/// NULL had been passed in. Otherwise, +/// if any of the fields are not valid pointers to functions +/// of the correct type, or this parameter is not a valid +/// pointer to a CFDictionaryValueCallBacks callbacks structure, +/// the behavior is undefined. If any of the values put into the +/// dictionary is not one understood by one of the callback functions +/// the behavior when that callback function is used is undefined. +/// @result A reference to the new immutable CFDictionary. +@ffi.Native< + CFDictionaryRef Function( + CFAllocatorRef, + ffi.Pointer>, + ffi.Pointer>, + CFIndex, + ffi.Pointer, + ffi.Pointer)>() +external CFDictionaryRef CFDictionaryCreate( + CFAllocatorRef allocator, + ffi.Pointer> keys, + ffi.Pointer> values, + int numValues, + ffi.Pointer keyCallBacks, + ffi.Pointer valueCallBacks, +); + +/// ! +/// @function CFDictionaryCreateCopy +/// Creates a new immutable dictionary with the key-value pairs from +/// the given dictionary. +/// @param allocator The CFAllocator which should be used to allocate +/// memory for the dictionary and its storage for values. This +/// parameter may be NULL in which case the current default +/// CFAllocator is used. If this reference is not a valid +/// CFAllocator, the behavior is undefined. +/// @param theDict The dictionary which is to be copied. The keys and values +/// from the dictionary are copied as pointers into the new +/// dictionary (that is, the values themselves are copied, not +/// that which the values point to, if anything). However, the +/// keys and values are also retained by the new dictionary using +/// the retain function of the original dictionary. +/// The count of the new dictionary will be the same as the +/// given dictionary. The new dictionary uses the same callbacks +/// as the dictionary to be copied. If this parameter is +/// not a valid CFDictionary, the behavior is undefined. +/// @result A reference to the new immutable CFDictionary. +@ffi.Native() +external CFDictionaryRef CFDictionaryCreateCopy( + CFAllocatorRef allocator, + CFDictionaryRef theDict, +); + +/// ! +/// @function CFDictionaryCreateMutable +/// Creates a new mutable dictionary. +/// @param allocator The CFAllocator which should be used to allocate +/// memory for the dictionary and its storage for values. This +/// parameter may be NULL in which case the current default +/// CFAllocator is used. If this reference is not a valid +/// CFAllocator, the behavior is undefined. +/// @param capacity A hint about the number of values that will be held +/// by the CFDictionary. Pass 0 for no hint. The implementation may +/// ignore this hint, or may use it to optimize various +/// operations. A dictionary's actual capacity is only limited by +/// address space and available memory constraints). If this +/// parameter is negative, the behavior is undefined. +/// @param keyCallBacks A pointer to a CFDictionaryKeyCallBacks structure +/// initialized with the callbacks for the dictionary to use on +/// each key in the dictionary. A copy of the contents of the +/// callbacks structure is made, so that a pointer to a structure +/// on the stack can be passed in, or can be reused for multiple +/// dictionary creations. If the version field of this +/// callbacks structure is not one of the defined ones for +/// CFDictionary, the behavior is undefined. The retain field may +/// be NULL, in which case the CFDictionary will do nothing to add +/// a retain to the keys of the contained values. The release field +/// may be NULL, in which case the CFDictionary will do nothing +/// to remove the dictionary's retain (if any) on the keys when the +/// dictionary is destroyed or a key-value pair is removed. If the +/// copyDescription field is NULL, the dictionary will create a +/// simple description for a key. If the equal field is NULL, the +/// dictionary will use pointer equality to test for equality of +/// keys. If the hash field is NULL, a key will be converted from +/// a pointer to an integer to compute the hash code. This callbacks +/// parameter itself may be NULL, which is treated as if a valid +/// structure of version 0 with all fields NULL had been passed in. +/// Otherwise, if any of the fields are not valid pointers to +/// functions of the correct type, or this parameter is not a +/// valid pointer to a CFDictionaryKeyCallBacks callbacks structure, +/// the behavior is undefined. If any of the keys put into the +/// dictionary is not one understood by one of the callback functions +/// the behavior when that callback function is used is undefined. +/// @param valueCallBacks A pointer to a CFDictionaryValueCallBacks structure +/// initialized with the callbacks for the dictionary to use on +/// each value in the dictionary. The retain callback will be used +/// within this function, for example, to retain all of the new +/// values from the values C array. A copy of the contents of the +/// callbacks structure is made, so that a pointer to a structure +/// on the stack can be passed in, or can be reused for multiple +/// dictionary creations. If the version field of this callbacks +/// structure is not one of the defined ones for CFDictionary, the +/// behavior is undefined. The retain field may be NULL, in which +/// case the CFDictionary will do nothing to add a retain to values +/// as they are put into the dictionary. The release field may be +/// NULL, in which case the CFDictionary will do nothing to remove +/// the dictionary's retain (if any) on the values when the +/// dictionary is destroyed or a key-value pair is removed. If the +/// copyDescription field is NULL, the dictionary will create a +/// simple description for a value. If the equal field is NULL, the +/// dictionary will use pointer equality to test for equality of +/// values. This callbacks parameter itself may be NULL, which is +/// treated as if a valid structure of version 0 with all fields +/// NULL had been passed in. Otherwise, +/// if any of the fields are not valid pointers to functions +/// of the correct type, or this parameter is not a valid +/// pointer to a CFDictionaryValueCallBacks callbacks structure, +/// the behavior is undefined. If any of the values put into the +/// dictionary is not one understood by one of the callback functions +/// the behavior when that callback function is used is undefined. +/// @result A reference to the new mutable CFDictionary. +@ffi.Native< + CFMutableDictionaryRef Function( + CFAllocatorRef, + CFIndex, + ffi.Pointer, + ffi.Pointer)>() +external CFMutableDictionaryRef CFDictionaryCreateMutable( + CFAllocatorRef allocator, + int capacity, + ffi.Pointer keyCallBacks, + ffi.Pointer valueCallBacks, +); + +/// ! +/// @function CFDictionaryCreateMutableCopy +/// Creates a new mutable dictionary with the key-value pairs from +/// the given dictionary. +/// @param allocator The CFAllocator which should be used to allocate +/// memory for the dictionary and its storage for values. This +/// parameter may be NULL in which case the current default +/// CFAllocator is used. If this reference is not a valid +/// CFAllocator, the behavior is undefined. +/// @param capacity A hint about the number of values that will be held +/// by the CFDictionary. Pass 0 for no hint. The implementation may +/// ignore this hint, or may use it to optimize various +/// operations. A dictionary's actual capacity is only limited by +/// address space and available memory constraints). +/// This parameter must be greater than or equal +/// to the count of the dictionary which is to be copied, or the +/// behavior is undefined. If this parameter is negative, the +/// behavior is undefined. +/// @param theDict The dictionary which is to be copied. The keys and values +/// from the dictionary are copied as pointers into the new +/// dictionary (that is, the values themselves are copied, not +/// that which the values point to, if anything). However, the +/// keys and values are also retained by the new dictionary using +/// the retain function of the original dictionary. +/// The count of the new dictionary will be the same as the +/// given dictionary. The new dictionary uses the same callbacks +/// as the dictionary to be copied. If this parameter is +/// not a valid CFDictionary, the behavior is undefined. +/// @result A reference to the new mutable CFDictionary. +@ffi.Native< + CFMutableDictionaryRef Function(CFAllocatorRef, CFIndex, CFDictionaryRef)>() +external CFMutableDictionaryRef CFDictionaryCreateMutableCopy( + CFAllocatorRef allocator, + int capacity, + CFDictionaryRef theDict, +); + +/// ! +/// @function CFDictionaryGetCount +/// Returns the number of values currently in the dictionary. +/// @param theDict The dictionary to be queried. If this parameter is +/// not a valid CFDictionary, the behavior is undefined. +/// @result The number of values in the dictionary. +@ffi.Native() +external int CFDictionaryGetCount( + CFDictionaryRef theDict, +); + +/// ! +/// @function CFDictionaryGetCountOfKey +/// Counts the number of times the given key occurs in the dictionary. +/// @param theDict The dictionary to be searched. If this parameter is +/// not a valid CFDictionary, the behavior is undefined. +/// @param key The key for which to find matches in the dictionary. The +/// hash() and equal() key callbacks provided when the dictionary +/// was created are used to compare. If the hash() key callback +/// was NULL, the key is treated as a pointer and converted to +/// an integer. If the equal() key callback was NULL, pointer +/// equality (in C, ==) is used. If key, or any of the keys in +/// the dictionary, are not understood by the equal() callback, +/// the behavior is undefined. +/// @result Returns 1 if a matching key is used by the dictionary, +/// 0 otherwise. +@ffi.Native)>() +external int CFDictionaryGetCountOfKey( + CFDictionaryRef theDict, + ffi.Pointer key, +); + +/// ! +/// @function CFDictionaryGetCountOfValue +/// Counts the number of times the given value occurs in the dictionary. +/// @param theDict The dictionary to be searched. If this parameter is +/// not a valid CFDictionary, the behavior is undefined. +/// @param value The value for which to find matches in the dictionary. The +/// equal() callback provided when the dictionary was created is +/// used to compare. If the equal() value callback was NULL, pointer +/// equality (in C, ==) is used. If value, or any of the values in +/// the dictionary, are not understood by the equal() callback, +/// the behavior is undefined. +/// @result The number of times the given value occurs in the dictionary. +@ffi.Native)>() +external int CFDictionaryGetCountOfValue( + CFDictionaryRef theDict, + ffi.Pointer value, +); + +/// ! +/// @function CFDictionaryContainsKey +/// Reports whether or not the key is in the dictionary. +/// @param theDict The dictionary to be searched. If this parameter is +/// not a valid CFDictionary, the behavior is undefined. +/// @param key The key for which to find matches in the dictionary. The +/// hash() and equal() key callbacks provided when the dictionary +/// was created are used to compare. If the hash() key callback +/// was NULL, the key is treated as a pointer and converted to +/// an integer. If the equal() key callback was NULL, pointer +/// equality (in C, ==) is used. If key, or any of the keys in +/// the dictionary, are not understood by the equal() callback, +/// the behavior is undefined. +/// @result true, if the key is in the dictionary, otherwise false. +@ffi.Native)>() +external int CFDictionaryContainsKey( + CFDictionaryRef theDict, + ffi.Pointer key, +); + +/// ! +/// @function CFDictionaryContainsValue +/// Reports whether or not the value is in the dictionary. +/// @param theDict The dictionary to be searched. If this parameter is +/// not a valid CFDictionary, the behavior is undefined. +/// @param value The value for which to find matches in the dictionary. The +/// equal() callback provided when the dictionary was created is +/// used to compare. If the equal() callback was NULL, pointer +/// equality (in C, ==) is used. If value, or any of the values +/// in the dictionary, are not understood by the equal() callback, +/// the behavior is undefined. +/// @result true, if the value is in the dictionary, otherwise false. +@ffi.Native)>() +external int CFDictionaryContainsValue( + CFDictionaryRef theDict, + ffi.Pointer value, +); + +/// ! +/// @function CFDictionaryGetValue +/// Retrieves the value associated with the given key. +/// @param theDict The dictionary to be queried. If this parameter is +/// not a valid CFDictionary, the behavior is undefined. +/// @param key The key for which to find a match in the dictionary. The +/// hash() and equal() key callbacks provided when the dictionary +/// was created are used to compare. If the hash() key callback +/// was NULL, the key is treated as a pointer and converted to +/// an integer. If the equal() key callback was NULL, pointer +/// equality (in C, ==) is used. If key, or any of the keys in +/// the dictionary, are not understood by the equal() callback, +/// the behavior is undefined. +/// @result The value with the given key in the dictionary, or NULL if +/// no key-value pair with a matching key exists. Since NULL +/// can be a valid value in some dictionaries, the function +/// CFDictionaryGetValueIfPresent() must be used to distinguish +/// NULL-no-found from NULL-is-the-value. +@ffi.Native< + ffi.Pointer Function(CFDictionaryRef, ffi.Pointer)>() +external ffi.Pointer CFDictionaryGetValue( + CFDictionaryRef theDict, + ffi.Pointer key, +); + +/// ! +/// @function CFDictionaryGetValueIfPresent +/// Retrieves the value associated with the given key. +/// @param theDict The dictionary to be queried. If this parameter is +/// not a valid CFDictionary, the behavior is undefined. +/// @param key The key for which to find a match in the dictionary. The +/// hash() and equal() key callbacks provided when the dictionary +/// was created are used to compare. If the hash() key callback +/// was NULL, the key is treated as a pointer and converted to +/// an integer. If the equal() key callback was NULL, pointer +/// equality (in C, ==) is used. If key, or any of the keys in +/// the dictionary, are not understood by the equal() callback, +/// the behavior is undefined. +/// @param value A pointer to memory which should be filled with the +/// pointer-sized value if a matching key is found. If no key +/// match is found, the contents of the storage pointed to by +/// this parameter are undefined. This parameter may be NULL, +/// in which case the value from the dictionary is not returned +/// (but the return value of this function still indicates +/// whether or not the key-value pair was present). +/// @result true, if a matching key was found, false otherwise. +@ffi.Native< + ffi.UnsignedChar Function(CFDictionaryRef, ffi.Pointer, + ffi.Pointer>)>() +external int CFDictionaryGetValueIfPresent( + CFDictionaryRef theDict, + ffi.Pointer key, + ffi.Pointer> value, +); + +/// ! +/// @function CFDictionaryGetKeysAndValues +/// Fills the two buffers with the keys and values from the dictionary. +/// @param theDict The dictionary to be queried. If this parameter is +/// not a valid CFDictionary, the behavior is undefined. +/// @param keys A C array of pointer-sized values to be filled with keys +/// from the dictionary. The keys and values C arrays are parallel +/// to each other (that is, the items at the same indices form a +/// key-value pair from the dictionary). This parameter may be NULL +/// if the keys are not desired. If this parameter is not a valid +/// pointer to a C array of at least CFDictionaryGetCount() pointers, +/// or NULL, the behavior is undefined. +/// @param values A C array of pointer-sized values to be filled with values +/// from the dictionary. The keys and values C arrays are parallel +/// to each other (that is, the items at the same indices form a +/// key-value pair from the dictionary). This parameter may be NULL +/// if the values are not desired. If this parameter is not a valid +/// pointer to a C array of at least CFDictionaryGetCount() pointers, +/// or NULL, the behavior is undefined. +@ffi.Native< + ffi.Void Function(CFDictionaryRef, ffi.Pointer>, + ffi.Pointer>)>() +external void CFDictionaryGetKeysAndValues( + CFDictionaryRef theDict, + ffi.Pointer> keys, + ffi.Pointer> values, +); + +/// ! +/// @function CFDictionaryApplyFunction +/// Calls a function once for each value in the dictionary. +/// @param theDict The dictionary to be queried. If this parameter is +/// not a valid CFDictionary, the behavior is undefined. +/// @param applier The callback function to call once for each value in +/// the dictionary. If this parameter is not a +/// pointer to a function of the correct prototype, the behavior +/// is undefined. If there are keys or values which the +/// applier function does not expect or cannot properly apply +/// to, the behavior is undefined. +/// @param context A pointer-sized user-defined value, which is passed +/// as the third parameter to the applier function, but is +/// otherwise unused by this function. If the context is not +/// what is expected by the applier function, the behavior is +/// undefined. +@ffi.Native< + ffi.Void Function( + CFDictionaryRef, CFDictionaryApplierFunction, ffi.Pointer)>() +external void CFDictionaryApplyFunction( + CFDictionaryRef theDict, + CFDictionaryApplierFunction applier, + ffi.Pointer context, +); + +/// ! +/// @function CFDictionaryAddValue +/// Adds the key-value pair to the dictionary if no such key already exists. +/// @param theDict The dictionary to which the value is to be added. If this +/// parameter is not a valid mutable CFDictionary, the behavior is +/// undefined. +/// @param key The key of the value to add to the dictionary. The key is +/// retained by the dictionary using the retain callback provided +/// when the dictionary was created. If the key is not of the sort +/// expected by the retain callback, the behavior is undefined. If +/// a key which matches this key is already present in the dictionary, +/// this function does nothing ("add if absent"). +/// @param value The value to add to the dictionary. The value is retained +/// by the dictionary using the retain callback provided when the +/// dictionary was created. If the value is not of the sort expected +/// by the retain callback, the behavior is undefined. +@ffi.Native< + ffi.Void Function( + CFMutableDictionaryRef, ffi.Pointer, ffi.Pointer)>() +external void CFDictionaryAddValue( + CFMutableDictionaryRef theDict, + ffi.Pointer key, + ffi.Pointer value, +); + +/// ! +/// @function CFDictionarySetValue +/// Sets the value of the key in the dictionary. +/// @param theDict The dictionary to which the value is to be set. If this +/// parameter is not a valid mutable CFDictionary, the behavior is +/// undefined. +/// @param key The key of the value to set into the dictionary. If a key +/// which matches this key is already present in the dictionary, only +/// the value is changed ("add if absent, replace if present"). If +/// no key matches the given key, the key-value pair is added to the +/// dictionary. If added, the key is retained by the dictionary, +/// using the retain callback provided +/// when the dictionary was created. If the key is not of the sort +/// expected by the key retain callback, the behavior is undefined. +/// @param value The value to add to or replace into the dictionary. The value +/// is retained by the dictionary using the retain callback provided +/// when the dictionary was created, and the previous value if any is +/// released. If the value is not of the sort expected by the +/// retain or release callbacks, the behavior is undefined. +@ffi.Native< + ffi.Void Function( + CFMutableDictionaryRef, ffi.Pointer, ffi.Pointer)>() +external void CFDictionarySetValue( + CFMutableDictionaryRef theDict, + ffi.Pointer key, + ffi.Pointer value, +); + +/// ! +/// @function CFDictionaryReplaceValue +/// Replaces the value of the key in the dictionary. +/// @param theDict The dictionary to which the value is to be replaced. If this +/// parameter is not a valid mutable CFDictionary, the behavior is +/// undefined. +/// @param key The key of the value to replace in the dictionary. If a key +/// which matches this key is present in the dictionary, the value +/// is changed to the given value, otherwise this function does +/// nothing ("replace if present"). +/// @param value The value to replace into the dictionary. The value +/// is retained by the dictionary using the retain callback provided +/// when the dictionary was created, and the previous value is +/// released. If the value is not of the sort expected by the +/// retain or release callbacks, the behavior is undefined. +@ffi.Native< + ffi.Void Function( + CFMutableDictionaryRef, ffi.Pointer, ffi.Pointer)>() +external void CFDictionaryReplaceValue( + CFMutableDictionaryRef theDict, + ffi.Pointer key, + ffi.Pointer value, +); + +/// ! +/// @function CFDictionaryRemoveValue +/// Removes the value of the key from the dictionary. +/// @param theDict The dictionary from which the value is to be removed. If this +/// parameter is not a valid mutable CFDictionary, the behavior is +/// undefined. +/// @param key The key of the value to remove from the dictionary. If a key +/// which matches this key is present in the dictionary, the key-value +/// pair is removed from the dictionary, otherwise this function does +/// nothing ("remove if present"). +@ffi.Native)>() +external void CFDictionaryRemoveValue( + CFMutableDictionaryRef theDict, + ffi.Pointer key, +); + +/// ! +/// @function CFDictionaryRemoveAllValues +/// Removes all the values from the dictionary, making it empty. +/// @param theDict The dictionary from which all of the values are to be +/// removed. If this parameter is not a valid mutable +/// CFDictionary, the behavior is undefined. +@ffi.Native() +external void CFDictionaryRemoveAllValues( + CFMutableDictionaryRef theDict, +); + +/// ! +/// @constant kCFTypeArrayCallBacks +/// Predefined CFArrayCallBacks structure containing a set of callbacks +/// appropriate for use when the values in a CFArray are all CFTypes. +@ffi.Native() +external final CFArrayCallBacks kCFTypeArrayCallBacks; + +/// ! +/// @function CFArrayGetTypeID +/// Returns the type identifier of all CFArray instances. +@ffi.Native() +external int CFArrayGetTypeID(); + +/// ! +/// @function CFArrayCreate +/// Creates a new immutable array with the given values. +/// @param allocator The CFAllocator which should be used to allocate +/// memory for the array and its storage for values. This +/// parameter may be NULL in which case the current default +/// CFAllocator is used. If this reference is not a valid +/// CFAllocator, the behavior is undefined. +/// @param values A C array of the pointer-sized values to be in the +/// array. The values in the array are ordered in the same order +/// in which they appear in this C array. This parameter may be +/// NULL if the numValues parameter is 0. This C array is not +/// changed or freed by this function. If this parameter is not +/// a valid pointer to a C array of at least numValues pointers, +/// the behavior is undefined. +/// @param numValues The number of values to copy from the values C +/// array into the CFArray. This number will be the count of the +/// array. +/// If this parameter is negative, or greater than the number of +/// values actually in the value's C array, the behavior is +/// undefined. +/// @param callBacks A pointer to a CFArrayCallBacks structure +/// initialized with the callbacks for the array to use on each +/// value in the array. The retain callback will be used within +/// this function, for example, to retain all of the new values +/// from the values C array. A copy of the contents of the +/// callbacks structure is made, so that a pointer to a +/// structure on the stack can be passed in, or can be reused +/// for multiple array creations. If the version field of this +/// callbacks structure is not one of the defined ones for +/// CFArray, the behavior is undefined. The retain field may be +/// NULL, in which case the CFArray will do nothing to add a +/// retain to the contained values for the array. The release +/// field may be NULL, in which case the CFArray will do nothing +/// to remove the array's retain (if any) on the values when the +/// array is destroyed. If the copyDescription field is NULL, +/// the array will create a simple description for the value. If +/// the equal field is NULL, the array will use pointer equality +/// to test for equality of values. This callbacks parameter +/// itself may be NULL, which is treated as if a valid structure +/// of version 0 with all fields NULL had been passed in. +/// Otherwise, if any of the fields are not valid pointers to +/// functions of the correct type, or this parameter is not a +/// valid pointer to a CFArrayCallBacks callbacks structure, +/// the behavior is undefined. If any of the values put into the +/// array is not one understood by one of the callback functions +/// the behavior when that callback function is used is +/// undefined. +/// @result A reference to the new immutable CFArray. +@ffi.Native< + CFArrayRef Function(CFAllocatorRef, ffi.Pointer>, + CFIndex, ffi.Pointer)>() +external CFArrayRef CFArrayCreate( + CFAllocatorRef allocator, + ffi.Pointer> values, + int numValues, + ffi.Pointer callBacks, +); + +/// ! +/// @function CFArrayCreateCopy +/// Creates a new immutable array with the values from the given array. +/// @param allocator The CFAllocator which should be used to allocate +/// memory for the array and its storage for values. This +/// parameter may be NULL in which case the current default +/// CFAllocator is used. If this reference is not a valid +/// CFAllocator, the behavior is undefined. +/// @param theArray The array which is to be copied. The values from the +/// array are copied as pointers into the new array (that is, +/// the values themselves are copied, not that which the values +/// point to, if anything). However, the values are also +/// retained by the new array. The count of the new array will +/// be the same as the given array. The new array uses the same +/// callbacks as the array to be copied. If this parameter is +/// not a valid CFArray, the behavior is undefined. +/// @result A reference to the new immutable CFArray. +@ffi.Native() +external CFArrayRef CFArrayCreateCopy( + CFAllocatorRef allocator, + CFArrayRef theArray, +); + +/// ! +/// @function CFArrayCreateMutable +/// Creates a new empty mutable array. +/// @param allocator The CFAllocator which should be used to allocate +/// memory for the array and its storage for values. This +/// parameter may be NULL in which case the current default +/// CFAllocator is used. If this reference is not a valid +/// CFAllocator, the behavior is undefined. +/// @param capacity A hint about the number of values that will be held +/// by the CFArray. Pass 0 for no hint. The implementation may +/// ignore this hint, or may use it to optimize various +/// operations. An array's actual capacity is only limited by +/// address space and available memory constraints). If this +/// parameter is negative, the behavior is undefined. +/// @param callBacks A pointer to a CFArrayCallBacks structure +/// initialized with the callbacks for the array to use on each +/// value in the array. A copy of the contents of the +/// callbacks structure is made, so that a pointer to a +/// structure on the stack can be passed in, or can be reused +/// for multiple array creations. If the version field of this +/// callbacks structure is not one of the defined ones for +/// CFArray, the behavior is undefined. The retain field may be +/// NULL, in which case the CFArray will do nothing to add a +/// retain to the contained values for the array. The release +/// field may be NULL, in which case the CFArray will do nothing +/// to remove the array's retain (if any) on the values when the +/// array is destroyed. If the copyDescription field is NULL, +/// the array will create a simple description for the value. If +/// the equal field is NULL, the array will use pointer equality +/// to test for equality of values. This callbacks parameter +/// itself may be NULL, which is treated as if a valid structure +/// of version 0 with all fields NULL had been passed in. +/// Otherwise, if any of the fields are not valid pointers to +/// functions of the correct type, or this parameter is not a +/// valid pointer to a CFArrayCallBacks callbacks structure, +/// the behavior is undefined. If any of the values put into the +/// array is not one understood by one of the callback functions +/// the behavior when that callback function is used is +/// undefined. +/// @result A reference to the new mutable CFArray. +@ffi.Native< + CFMutableArrayRef Function( + CFAllocatorRef, CFIndex, ffi.Pointer)>() +external CFMutableArrayRef CFArrayCreateMutable( + CFAllocatorRef allocator, + int capacity, + ffi.Pointer callBacks, +); + +/// ! +/// @function CFArrayCreateMutableCopy +/// Creates a new mutable array with the values from the given array. +/// @param allocator The CFAllocator which should be used to allocate +/// memory for the array and its storage for values. This +/// parameter may be NULL in which case the current default +/// CFAllocator is used. If this reference is not a valid +/// CFAllocator, the behavior is undefined. +/// @param capacity A hint about the number of values that will be held +/// by the CFArray. Pass 0 for no hint. The implementation may +/// ignore this hint, or may use it to optimize various +/// operations. An array's actual capacity is only limited by +/// address space and available memory constraints). +/// This parameter must be greater than or equal +/// to the count of the array which is to be copied, or the +/// behavior is undefined. If this parameter is negative, the +/// behavior is undefined. +/// @param theArray The array which is to be copied. The values from the +/// array are copied as pointers into the new array (that is, +/// the values themselves are copied, not that which the values +/// point to, if anything). However, the values are also +/// retained by the new array. The count of the new array will +/// be the same as the given array. The new array uses the same +/// callbacks as the array to be copied. If this parameter is +/// not a valid CFArray, the behavior is undefined. +/// @result A reference to the new mutable CFArray. +@ffi.Native() +external CFMutableArrayRef CFArrayCreateMutableCopy( + CFAllocatorRef allocator, + int capacity, + CFArrayRef theArray, +); + +/// ! +/// @function CFArrayGetCount +/// Returns the number of values currently in the array. +/// @param theArray The array to be queried. If this parameter is not a valid +/// CFArray, the behavior is undefined. +/// @result The number of values in the array. +@ffi.Native() +external int CFArrayGetCount( + CFArrayRef theArray, +); + +/// ! +/// @function CFArrayGetCountOfValue +/// Counts the number of times the given value occurs in the array. +/// @param theArray The array to be searched. If this parameter is not a +/// valid CFArray, the behavior is undefined. +/// @param range The range within the array to search. If the range +/// location or end point (defined by the location plus length +/// minus 1) is outside the index space of the array (0 to +/// N-1 inclusive, where N is the count of the array), the +/// behavior is undefined. If the range length is negative, the +/// behavior is undefined. The range may be empty (length 0). +/// @param value The value for which to find matches in the array. The +/// equal() callback provided when the array was created is +/// used to compare. If the equal() callback was NULL, pointer +/// equality (in C, ==) is used. If value, or any of the values +/// in the array, are not understood by the equal() callback, +/// the behavior is undefined. +/// @result The number of times the given value occurs in the array, +/// within the specified range. +@ffi.Native)>() +external int CFArrayGetCountOfValue( + CFArrayRef theArray, + CFRange range, + ffi.Pointer value, +); + +/// ! +/// @function CFArrayContainsValue +/// Reports whether or not the value is in the array. +/// @param theArray The array to be searched. If this parameter is not a +/// valid CFArray, the behavior is undefined. +/// @param range The range within the array to search. If the range +/// location or end point (defined by the location plus length +/// minus 1) is outside the index space of the array (0 to +/// N-1 inclusive, where N is the count of the array), the +/// behavior is undefined. If the range length is negative, the +/// behavior is undefined. The range may be empty (length 0). +/// @param value The value for which to find matches in the array. The +/// equal() callback provided when the array was created is +/// used to compare. If the equal() callback was NULL, pointer +/// equality (in C, ==) is used. If value, or any of the values +/// in the array, are not understood by the equal() callback, +/// the behavior is undefined. +/// @result true, if the value is in the specified range of the array, +/// otherwise false. +@ffi.Native< + ffi.UnsignedChar Function(CFArrayRef, CFRange, ffi.Pointer)>() +external int CFArrayContainsValue( + CFArrayRef theArray, + CFRange range, + ffi.Pointer value, +); + +/// ! +/// @function CFArrayGetValueAtIndex +/// Retrieves the value at the given index. +/// @param theArray The array to be queried. If this parameter is not a +/// valid CFArray, the behavior is undefined. +/// @param idx The index of the value to retrieve. If the index is +/// outside the index space of the array (0 to N-1 inclusive, +/// where N is the count of the array), the behavior is +/// undefined. +/// @result The value with the given index in the array. +@ffi.Native Function(CFArrayRef, CFIndex)>() +external ffi.Pointer CFArrayGetValueAtIndex( + CFArrayRef theArray, + int idx, +); + +/// ! +/// @function CFArrayGetValues +/// Fills the buffer with values from the array. +/// @param theArray The array to be queried. If this parameter is not a +/// valid CFArray, the behavior is undefined. +/// @param range The range of values within the array to retrieve. If +/// the range location or end point (defined by the location +/// plus length minus 1) is outside the index space of the +/// array (0 to N-1 inclusive, where N is the count of the +/// array), the behavior is undefined. If the range length is +/// negative, the behavior is undefined. The range may be empty +/// (length 0), in which case no values are put into the buffer. +/// @param values A C array of pointer-sized values to be filled with +/// values from the array. The values in the C array are ordered +/// in the same order in which they appear in the array. If this +/// parameter is not a valid pointer to a C array of at least +/// range.length pointers, the behavior is undefined. +@ffi.Native< + ffi.Void Function( + CFArrayRef, CFRange, ffi.Pointer>)>() +external void CFArrayGetValues( + CFArrayRef theArray, + CFRange range, + ffi.Pointer> values, +); + +/// ! +/// @function CFArrayApplyFunction +/// Calls a function once for each value in the array. +/// @param theArray The array to be operated upon. If this parameter is not +/// a valid CFArray, the behavior is undefined. +/// @param range The range of values within the array to which to apply +/// the function. If the range location or end point (defined by +/// the location plus length minus 1) is outside the index +/// space of the array (0 to N-1 inclusive, where N is the count +/// of the array), the behavior is undefined. If the range +/// length is negative, the behavior is undefined. The range may +/// be empty (length 0). +/// @param applier The callback function to call once for each value in +/// the given range in the array. If this parameter is not a +/// pointer to a function of the correct prototype, the behavior +/// is undefined. If there are values in the range which the +/// applier function does not expect or cannot properly apply +/// to, the behavior is undefined. +/// @param context A pointer-sized user-defined value, which is passed +/// as the second parameter to the applier function, but is +/// otherwise unused by this function. If the context is not +/// what is expected by the applier function, the behavior is +/// undefined. +@ffi.Native< + ffi.Void Function( + CFArrayRef, CFRange, CFArrayApplierFunction, ffi.Pointer)>() +external void CFArrayApplyFunction( + CFArrayRef theArray, + CFRange range, + CFArrayApplierFunction applier, + ffi.Pointer context, +); + +/// ! +/// @function CFArrayGetFirstIndexOfValue +/// Searches the array for the value. +/// @param theArray The array to be searched. If this parameter is not a +/// valid CFArray, the behavior is undefined. +/// @param range The range within the array to search. If the range +/// location or end point (defined by the location plus length +/// minus 1) is outside the index space of the array (0 to +/// N-1 inclusive, where N is the count of the array), the +/// behavior is undefined. If the range length is negative, the +/// behavior is undefined. The range may be empty (length 0). +/// The search progresses from the smallest index defined by +/// the range to the largest. +/// @param value The value for which to find a match in the array. The +/// equal() callback provided when the array was created is +/// used to compare. If the equal() callback was NULL, pointer +/// equality (in C, ==) is used. If value, or any of the values +/// in the array, are not understood by the equal() callback, +/// the behavior is undefined. +/// @result The lowest index of the matching values in the range, or +/// kCFNotFound if no value in the range matched. +@ffi.Native)>() +external int CFArrayGetFirstIndexOfValue( + CFArrayRef theArray, + CFRange range, + ffi.Pointer value, +); + +/// ! +/// @function CFArrayGetLastIndexOfValue +/// Searches the array for the value. +/// @param theArray The array to be searched. If this parameter is not a +/// valid CFArray, the behavior is undefined. +/// @param range The range within the array to search. If the range +/// location or end point (defined by the location plus length +/// minus 1) is outside the index space of the array (0 to +/// N-1 inclusive, where N is the count of the array), the +/// behavior is undefined. If the range length is negative, the +/// behavior is undefined. The range may be empty (length 0). +/// The search progresses from the largest index defined by the +/// range to the smallest. +/// @param value The value for which to find a match in the array. The +/// equal() callback provided when the array was created is +/// used to compare. If the equal() callback was NULL, pointer +/// equality (in C, ==) is used. If value, or any of the values +/// in the array, are not understood by the equal() callback, +/// the behavior is undefined. +/// @result The highest index of the matching values in the range, or +/// kCFNotFound if no value in the range matched. +@ffi.Native)>() +external int CFArrayGetLastIndexOfValue( + CFArrayRef theArray, + CFRange range, + ffi.Pointer value, +); + +/// ! +/// @function CFArrayBSearchValues +/// Searches the array for the value using a binary search algorithm. +/// @param theArray The array to be searched. If this parameter is not a +/// valid CFArray, the behavior is undefined. If the array is +/// not sorted from least to greatest according to the +/// comparator function, the behavior is undefined. +/// @param range The range within the array to search. If the range +/// location or end point (defined by the location plus length +/// minus 1) is outside the index space of the array (0 to +/// N-1 inclusive, where N is the count of the array), the +/// behavior is undefined. If the range length is negative, the +/// behavior is undefined. The range may be empty (length 0). +/// @param value The value for which to find a match in the array. If +/// value, or any of the values in the array, are not understood +/// by the comparator callback, the behavior is undefined. +/// @param comparator The function with the comparator function type +/// signature which is used in the binary search operation to +/// compare values in the array with the given value. If this +/// parameter is not a pointer to a function of the correct +/// prototype, the behavior is undefined. If there are values +/// in the range which the comparator function does not expect +/// or cannot properly compare, the behavior is undefined. +/// @param context A pointer-sized user-defined value, which is passed +/// as the third parameter to the comparator function, but is +/// otherwise unused by this function. If the context is not +/// what is expected by the comparator function, the behavior is +/// undefined. +/// @result The return value is either 1) the index of a value that +/// matched, if the target value matches one or more in the +/// range, 2) greater than or equal to the end point of the +/// range, if the value is greater than all the values in the +/// range, or 3) the index of the value greater than the target +/// value, if the value lies between two of (or less than all +/// of) the values in the range. +@ffi.Native< + CFIndex Function(CFArrayRef, CFRange, ffi.Pointer, + CFComparatorFunction, ffi.Pointer)>() +external int CFArrayBSearchValues( + CFArrayRef theArray, + CFRange range, + ffi.Pointer value, + CFComparatorFunction comparator, + ffi.Pointer context, +); + +/// ! +/// @function CFArrayAppendValue +/// Adds the value to the array giving it a new largest index. +/// @param theArray The array to which the value is to be added. If this +/// parameter is not a valid mutable CFArray, the behavior is +/// undefined. +/// @param value The value to add to the array. The value is retained by +/// the array using the retain callback provided when the array +/// was created. If the value is not of the sort expected by the +/// retain callback, the behavior is undefined. The value is +/// assigned to the index one larger than the previous largest +/// index, and the count of the array is increased by one. +@ffi.Native)>() +external void CFArrayAppendValue( + CFMutableArrayRef theArray, + ffi.Pointer value, +); + +/// ! +/// @function CFArrayInsertValueAtIndex +/// Adds the value to the array, giving it the given index. +/// @param theArray The array to which the value is to be added. If this +/// parameter is not a valid mutable CFArray, the behavior is +/// undefined. +/// @param idx The index to which to add the new value. If the index is +/// outside the index space of the array (0 to N inclusive, +/// where N is the count of the array before the operation), the +/// behavior is undefined. If the index is the same as N, this +/// function has the same effect as CFArrayAppendValue(). +/// @param value The value to add to the array. The value is retained by +/// the array using the retain callback provided when the array +/// was created. If the value is not of the sort expected by the +/// retain callback, the behavior is undefined. The value is +/// assigned to the given index, and all values with equal and +/// larger indices have their indexes increased by one. +@ffi.Native< + ffi.Void Function(CFMutableArrayRef, CFIndex, ffi.Pointer)>() +external void CFArrayInsertValueAtIndex( + CFMutableArrayRef theArray, + int idx, + ffi.Pointer value, +); + +/// ! +/// @function CFArraySetValueAtIndex +/// Changes the value with the given index in the array. +/// @param theArray The array in which the value is to be changed. If this +/// parameter is not a valid mutable CFArray, the behavior is +/// undefined. +/// @param idx The index to which to set the new value. If the index is +/// outside the index space of the array (0 to N inclusive, +/// where N is the count of the array before the operation), the +/// behavior is undefined. If the index is the same as N, this +/// function has the same effect as CFArrayAppendValue(). +/// @param value The value to set in the array. The value is retained by +/// the array using the retain callback provided when the array +/// was created, and the previous value with that index is +/// released. If the value is not of the sort expected by the +/// retain callback, the behavior is undefined. The indices of +/// other values is not affected. +@ffi.Native< + ffi.Void Function(CFMutableArrayRef, CFIndex, ffi.Pointer)>() +external void CFArraySetValueAtIndex( + CFMutableArrayRef theArray, + int idx, + ffi.Pointer value, +); + +/// ! +/// @function CFArrayRemoveValueAtIndex +/// Removes the value with the given index from the array. +/// @param theArray The array from which the value is to be removed. If +/// this parameter is not a valid mutable CFArray, the behavior +/// is undefined. +/// @param idx The index from which to remove the value. If the index is +/// outside the index space of the array (0 to N-1 inclusive, +/// where N is the count of the array before the operation), the +/// behavior is undefined. +@ffi.Native() +external void CFArrayRemoveValueAtIndex( + CFMutableArrayRef theArray, + int idx, +); + +/// ! +/// @function CFArrayRemoveAllValues +/// Removes all the values from the array, making it empty. +/// @param theArray The array from which all of the values are to be +/// removed. If this parameter is not a valid mutable CFArray, +/// the behavior is undefined. +@ffi.Native() +external void CFArrayRemoveAllValues( + CFMutableArrayRef theArray, +); + +/// ! +/// @function CFArrayReplaceValues +/// Replaces a range of values in the array. +/// @param theArray The array from which all of the values are to be +/// removed. If this parameter is not a valid mutable CFArray, +/// the behavior is undefined. +/// @param range The range of values within the array to replace. If the +/// range location or end point (defined by the location plus +/// length minus 1) is outside the index space of the array (0 +/// to N inclusive, where N is the count of the array), the +/// behavior is undefined. If the range length is negative, the +/// behavior is undefined. The range may be empty (length 0), +/// in which case the new values are merely inserted at the +/// range location. +/// @param newValues A C array of the pointer-sized values to be placed +/// into the array. The new values in the array are ordered in +/// the same order in which they appear in this C array. This +/// parameter may be NULL if the newCount parameter is 0. This +/// C array is not changed or freed by this function. If this +/// parameter is not a valid pointer to a C array of at least +/// newCount pointers, the behavior is undefined. +/// @param newCount The number of values to copy from the values C +/// array into the CFArray. If this parameter is different than +/// the range length, the excess newCount values will be +/// inserted after the range, or the excess range values will be +/// deleted. This parameter may be 0, in which case no new +/// values are replaced into the array and the values in the +/// range are simply removed. If this parameter is negative, or +/// greater than the number of values actually in the newValues +/// C array, the behavior is undefined. +@ffi.Native< + ffi.Void Function(CFMutableArrayRef, CFRange, + ffi.Pointer>, CFIndex)>() +external void CFArrayReplaceValues( + CFMutableArrayRef theArray, + CFRange range, + ffi.Pointer> newValues, + int newCount, +); + +/// ! +/// @function CFArrayExchangeValuesAtIndices +/// Exchanges the values at two indices of the array. +/// @param theArray The array of which the values are to be swapped. If +/// this parameter is not a valid mutable CFArray, the behavior +/// is undefined. +/// @param idx1 The first index whose values should be swapped. If the +/// index is outside the index space of the array (0 to N-1 +/// inclusive, where N is the count of the array before the +/// operation), the behavior is undefined. +/// @param idx2 The second index whose values should be swapped. If the +/// index is outside the index space of the array (0 to N-1 +/// inclusive, where N is the count of the array before the +/// operation), the behavior is undefined. +@ffi.Native() +external void CFArrayExchangeValuesAtIndices( + CFMutableArrayRef theArray, + int idx1, + int idx2, +); + +/// ! +/// @function CFArraySortValues +/// Sorts the values in the array using the given comparison function. +/// @param theArray The array whose values are to be sorted. If this +/// parameter is not a valid mutable CFArray, the behavior is +/// undefined. +/// @param range The range of values within the array to sort. If the +/// range location or end point (defined by the location plus +/// length minus 1) is outside the index space of the array (0 +/// to N-1 inclusive, where N is the count of the array), the +/// behavior is undefined. If the range length is negative, the +/// behavior is undefined. The range may be empty (length 0). +/// @param comparator The function with the comparator function type +/// signature which is used in the sort operation to compare +/// values in the array with the given value. If this parameter +/// is not a pointer to a function of the correct prototype, the +/// the behavior is undefined. If there are values in the array +/// which the comparator function does not expect or cannot +/// properly compare, the behavior is undefined. The values in +/// the range are sorted from least to greatest according to +/// this function. +/// @param context A pointer-sized user-defined value, which is passed +/// as the third parameter to the comparator function, but is +/// otherwise unused by this function. If the context is not +/// what is expected by the comparator function, the behavior is +/// undefined. +@ffi.Native< + ffi.Void Function(CFMutableArrayRef, CFRange, CFComparatorFunction, + ffi.Pointer)>() +external void CFArraySortValues( + CFMutableArrayRef theArray, + CFRange range, + CFComparatorFunction comparator, + ffi.Pointer context, +); + +/// ! +/// @function CFArrayAppendArray +/// Adds the values from an array to another array. +/// @param theArray The array to which values from the otherArray are to +/// be added. If this parameter is not a valid mutable CFArray, +/// the behavior is undefined. +/// @param otherArray The array providing the values to be added to the +/// array. If this parameter is not a valid CFArray, the +/// behavior is undefined. +/// @param otherRange The range within the otherArray from which to add +/// the values to the array. If the range location or end point +/// (defined by the location plus length minus 1) is outside +/// the index space of the otherArray (0 to N-1 inclusive, where +/// N is the count of the otherArray), the behavior is +/// undefined. The new values are retained by the array using +/// the retain callback provided when the array was created. If +/// the values are not of the sort expected by the retain +/// callback, the behavior is undefined. The values are assigned +/// to the indices one larger than the previous largest index +/// in the array, and beyond, and the count of the array is +/// increased by range.length. The values are assigned new +/// indices in the array from smallest to largest index in the +/// order in which they appear in the otherArray. +@ffi.Native() +external void CFArrayAppendArray( + CFMutableArrayRef theArray, + CFArrayRef otherArray, + CFRange otherRange, +); + +@ffi.Native() +external int CFDataGetTypeID(); + +@ffi.Native< + CFDataRef Function( + CFAllocatorRef, ffi.Pointer, CFIndex)>() +external CFDataRef CFDataCreate( + CFAllocatorRef allocator, + ffi.Pointer bytes, + int length, +); + +@ffi.Native Function(CFDataRef)>() +external ffi.Pointer CFDataGetBytePtr( + CFDataRef theData, +); + +/// ! +/// @function CFCharacterSetGetTypeID +/// Returns the type identifier of all CFCharacterSet instances. +@ffi.Native() +external int CFCharacterSetGetTypeID(); + +@ffi.Native() +external int CFNotificationCenterGetTypeID(); + +@ffi.Native() +external int CFLocaleGetTypeID(); + +/// Returns the display name for the given value. The key tells what +/// the value is, and is one of the usual locale property keys, though +/// not all locale property keys have values with display name values. +@ffi.Native() +external final CFNotificationName kCFLocaleCurrentLocaleDidChangeNotification; + +/// Locale Keys +@ffi.Native() +external final CFLocaleKey kCFLocaleIdentifier; + +@ffi.Native() +external final CFLocaleKey kCFLocaleLanguageCode; + +@ffi.Native() +external final CFLocaleKey kCFLocaleCountryCode; + +@ffi.Native() +external final CFLocaleKey kCFLocaleScriptCode; + +@ffi.Native() +external final CFLocaleKey kCFLocaleVariantCode; + +@ffi.Native() +external final CFLocaleKey kCFLocaleExemplarCharacterSet; + +@ffi.Native() +external final CFLocaleKey kCFLocaleCalendarIdentifier; + +@ffi.Native() +external final CFLocaleKey kCFLocaleCalendar; + +@ffi.Native() +external final CFLocaleKey kCFLocaleCollationIdentifier; + +@ffi.Native() +external final CFLocaleKey kCFLocaleUsesMetricSystem; + +/// "Metric", "U.S." or "U.K." +@ffi.Native() +external final CFLocaleKey kCFLocaleMeasurementSystem; + +@ffi.Native() +external final CFLocaleKey kCFLocaleDecimalSeparator; + +@ffi.Native() +external final CFLocaleKey kCFLocaleGroupingSeparator; + +@ffi.Native() +external final CFLocaleKey kCFLocaleCurrencySymbol; + +/// ISO 3-letter currency code +@ffi.Native() +external final CFLocaleKey kCFLocaleCurrencyCode; + +@ffi.Native() +external final CFLocaleKey kCFLocaleCollatorIdentifier; + +@ffi.Native() +external final CFLocaleKey kCFLocaleQuotationBeginDelimiterKey; + +@ffi.Native() +external final CFLocaleKey kCFLocaleQuotationEndDelimiterKey; + +@ffi.Native() +external final CFLocaleKey kCFLocaleAlternateQuotationBeginDelimiterKey; + +@ffi.Native() +external final CFLocaleKey kCFLocaleAlternateQuotationEndDelimiterKey; + +@ffi.Native() +external final CFCalendarIdentifier kCFGregorianCalendar; + +@ffi.Native() +external final CFCalendarIdentifier kCFBuddhistCalendar; + +@ffi.Native() +external final CFCalendarIdentifier kCFChineseCalendar; + +@ffi.Native() +external final CFCalendarIdentifier kCFHebrewCalendar; + +@ffi.Native() +external final CFCalendarIdentifier kCFIslamicCalendar; + +@ffi.Native() +external final CFCalendarIdentifier kCFIslamicCivilCalendar; + +@ffi.Native() +external final CFCalendarIdentifier kCFJapaneseCalendar; + +@ffi.Native() +external final CFCalendarIdentifier kCFRepublicOfChinaCalendar; + +@ffi.Native() +external final CFCalendarIdentifier kCFPersianCalendar; + +@ffi.Native() +external final CFCalendarIdentifier kCFIndianCalendar; + +@ffi.Native() +external final CFCalendarIdentifier kCFISO8601Calendar; + +@ffi.Native() +external final CFCalendarIdentifier kCFIslamicTabularCalendar; + +@ffi.Native() +external final CFCalendarIdentifier kCFIslamicUmmAlQuraCalendar; + +/// ! +/// @function CFErrorGetTypeID +/// Returns the type identifier of all CFError instances. +@ffi.Native() +external int CFErrorGetTypeID(); + +/// Predefined domains; value of "code" will correspond to preexisting values in these domains. +@ffi.Native() +external final CFErrorDomain kCFErrorDomainPOSIX; + +@ffi.Native() +external final CFErrorDomain kCFErrorDomainOSStatus; + +@ffi.Native() +external final CFErrorDomain kCFErrorDomainMach; + +@ffi.Native() +external final CFErrorDomain kCFErrorDomainCocoa; + +/// Key to identify the end user-presentable description in userInfo. Should be one or more complete sentence(s) describing both what failed and why. For instance 'You can't save the file "To Do List" because the volume "Macintosh HD" is out of space.' +@ffi.Native() +external final CFStringRef kCFErrorLocalizedDescriptionKey; + +/// Key to identify the end user-presentable failing operation ("what failed") description in userInfo. Should be one or more complete sentence(s), for instance 'The file "To Do List" couldn't be saved.' +@ffi.Native() +external final CFStringRef kCFErrorLocalizedFailureKey; + +/// Key to identify the end user-presentable failure reason ("why it failed") description in userInfo. Should be one or more complete sentence(s), for instance 'The volume "Macintosh HD" is out of space.' +@ffi.Native() +external final CFStringRef kCFErrorLocalizedFailureReasonKey; + +/// Key to identify the end user-presentable recovery suggestion in userInfo. Should be one or more complete sentence(s), for instance 'Remove some files from the volume, and then try again.' +@ffi.Native() +external final CFStringRef kCFErrorLocalizedRecoverySuggestionKey; + +/// Key to identify the description in the userInfo dictionary. Should be a complete sentence if possible. Should not contain domain name or error code. +@ffi.Native() +external final CFStringRef kCFErrorDescriptionKey; + +/// Key to identify the underlying error in userInfo. +@ffi.Native() +external final CFStringRef kCFErrorUnderlyingErrorKey; + +/// Key to identify associated URL in userInfo. Typically one of this or kCFErrorFilePathKey is provided. +@ffi.Native() +external final CFStringRef kCFErrorURLKey; + +/// Key to identify associated file path in userInfo. Typically one of this or kCFErrorURLKey is provided. +@ffi.Native() +external final CFStringRef kCFErrorFilePathKey; + +/// CFString type ID +@ffi.Native() +external int CFStringGetTypeID(); + +@ffi.Native< + CFStringRef Function( + CFAllocatorRef, ffi.Pointer, CFStringEncoding)>() +external CFStringRef CFStringCreateWithCString( + CFAllocatorRef alloc, + ffi.Pointer cStr, + int encoding, +); + +/// Number of 16-bit Unicode characters in the string. +@ffi.Native() +external int CFStringGetLength( + CFStringRef theString, +); + +@ffi.Native< + ffi.UnsignedChar Function( + CFStringRef, ffi.Pointer, CFIndex, CFStringEncoding)>() +external int CFStringGetCString( + CFStringRef theString, + ffi.Pointer buffer, + int bufferSize, + int encoding, +); + +@ffi.Native Function(CFStringRef, CFStringEncoding)>() +external ffi.Pointer CFStringGetCStringPtr( + CFStringRef theString, + int encoding, +); + +@ffi.Native() +external int CFStringGetMaximumSizeForEncoding( + int length, + int encoding, +); + +/// Transform identifiers for CFStringTransform() +@ffi.Native() +external final CFStringRef kCFStringTransformStripCombiningMarks; + +@ffi.Native() +external final CFStringRef kCFStringTransformToLatin; + +@ffi.Native() +external final CFStringRef kCFStringTransformFullwidthHalfwidth; + +@ffi.Native() +external final CFStringRef kCFStringTransformLatinKatakana; + +@ffi.Native() +external final CFStringRef kCFStringTransformLatinHiragana; + +@ffi.Native() +external final CFStringRef kCFStringTransformHiraganaKatakana; + +@ffi.Native() +external final CFStringRef kCFStringTransformMandarinLatin; + +@ffi.Native() +external final CFStringRef kCFStringTransformLatinHangul; + +@ffi.Native() +external final CFStringRef kCFStringTransformLatinArabic; + +@ffi.Native() +external final CFStringRef kCFStringTransformLatinHebrew; + +@ffi.Native() +external final CFStringRef kCFStringTransformLatinThai; + +@ffi.Native() +external final CFStringRef kCFStringTransformLatinCyrillic; + +@ffi.Native() +external final CFStringRef kCFStringTransformLatinGreek; + +@ffi.Native() +external final CFStringRef kCFStringTransformToXMLHex; + +@ffi.Native() +external final CFStringRef kCFStringTransformToUnicodeName; + +@ffi.Native() +external final CFStringRef kCFStringTransformStripDiacritics; + +typedef CFIndex = ffi.Long; +typedef DartCFIndex = int; +typedef CFTypeID = ffi.UnsignedLong; +typedef DartCFTypeID = int; + +/// Null representant +typedef CFNullRef = ffi.Pointer<__CFNull>; + +final class __CFNull extends ffi.Opaque {} + +/// Allocator API +/// +/// Most of the time when specifying an allocator to Create functions, the NULL +/// argument indicates "use the default"; this is the same as using kCFAllocatorDefault +/// or the return value from CFAllocatorGetDefault(). This assures that you will use +/// the allocator in effect at that time. +typedef CFAllocatorRef = ffi.Pointer<__CFAllocator>; + +final class __CFAllocator extends ffi.Opaque {} + +/// Base "type" of all "CF objects", and polymorphic functions on them +typedef CFTypeRef = ffi.Pointer; + +final class CFDictionaryKeyCallBacks extends ffi.Struct { + @CFIndex() + external int version; + + external CFDictionaryRetainCallBack retain; + + external CFDictionaryReleaseCallBack release; + + external CFDictionaryCopyDescriptionCallBack copyDescription; + + external CFDictionaryEqualCallBack equal; + + external CFDictionaryHashCallBack hash; +} + +/// ! +/// @typedef CFDictionaryKeyCallBacks +/// Structure containing the callbacks for keys of a CFDictionary. +/// @field version The version number of the structure type being passed +/// in as a parameter to the CFDictionary creation functions. +/// This structure is version 0. +/// @field retain The callback used to add a retain for the dictionary +/// on keys as they are used to put values into the dictionary. +/// This callback returns the value to use as the key in the +/// dictionary, which is usually the value parameter passed to +/// this callback, but may be a different value if a different +/// value should be used as the key. The dictionary's allocator +/// is passed as the first argument. +/// @field release The callback used to remove a retain previously added +/// for the dictionary from keys as their values are removed from +/// the dictionary. The dictionary's allocator is passed as the +/// first argument. +/// @field copyDescription The callback used to create a descriptive +/// string representation of each key in the dictionary. This +/// is used by the CFCopyDescription() function. +/// @field equal The callback used to compare keys in the dictionary for +/// equality. +/// @field hash The callback used to compute a hash code for keys as they +/// are used to access, add, or remove values in the dictionary. +typedef CFDictionaryRetainCallBack + = ffi.Pointer>; +typedef CFDictionaryRetainCallBackFunction = ffi.Pointer Function( + CFAllocatorRef allocator, ffi.Pointer value); +typedef CFDictionaryReleaseCallBack + = ffi.Pointer>; +typedef CFDictionaryReleaseCallBackFunction = ffi.Void Function( + CFAllocatorRef allocator, ffi.Pointer value); +typedef DartCFDictionaryReleaseCallBackFunction = void Function( + CFAllocatorRef allocator, ffi.Pointer value); +typedef CFDictionaryCopyDescriptionCallBack = ffi + .Pointer>; +typedef CFDictionaryCopyDescriptionCallBackFunction = CFStringRef Function( + ffi.Pointer value); +typedef CFStringRef = ffi.Pointer; + +final class CFString extends ffi.Opaque {} + +typedef CFDictionaryEqualCallBack + = ffi.Pointer>; +typedef CFDictionaryEqualCallBackFunction = ffi.UnsignedChar Function( + ffi.Pointer value1, ffi.Pointer value2); +typedef DartCFDictionaryEqualCallBackFunction = int Function( + ffi.Pointer value1, ffi.Pointer value2); +typedef CFDictionaryHashCallBack + = ffi.Pointer>; +typedef CFDictionaryHashCallBackFunction = CFHashCode Function( + ffi.Pointer value); +typedef DartCFDictionaryHashCallBackFunction = DartCFHashCode Function( + ffi.Pointer value); +typedef CFHashCode = ffi.UnsignedLong; +typedef DartCFHashCode = int; + +/// ! +/// @typedef CFDictionaryValueCallBacks +/// Structure containing the callbacks for values of a CFDictionary. +/// @field version The version number of the structure type being passed +/// in as a parameter to the CFDictionary creation functions. +/// This structure is version 0. +/// @field retain The callback used to add a retain for the dictionary +/// on values as they are put into the dictionary. +/// This callback returns the value to use as the value in the +/// dictionary, which is usually the value parameter passed to +/// this callback, but may be a different value if a different +/// value should be added to the dictionary. The dictionary's +/// allocator is passed as the first argument. +/// @field release The callback used to remove a retain previously added +/// for the dictionary from values as they are removed from +/// the dictionary. The dictionary's allocator is passed as the +/// first argument. +/// @field copyDescription The callback used to create a descriptive +/// string representation of each value in the dictionary. This +/// is used by the CFCopyDescription() function. +/// @field equal The callback used to compare values in the dictionary for +/// equality in some operations. +final class CFDictionaryValueCallBacks extends ffi.Struct { + @CFIndex() + external int version; + + external CFDictionaryRetainCallBack retain; + + external CFDictionaryReleaseCallBack release; + + external CFDictionaryCopyDescriptionCallBack copyDescription; + + external CFDictionaryEqualCallBack equal; +} + +/// ! +/// @typedef CFDictionaryRef +/// This is the type of a reference to immutable CFDictionarys. +typedef CFDictionaryRef = ffi.Pointer; + +final class CFDictionary extends ffi.Opaque {} + +/// ! +/// @typedef CFMutableDictionaryRef +/// This is the type of a reference to mutable CFDictionarys. +typedef CFMutableDictionaryRef = ffi.Pointer; + +/// ! +/// @typedef CFDictionaryApplierFunction +/// Type of the callback function used by the apply functions of +/// CFDictionarys. +/// @param key The current key for the value. +/// @param value The current value from the dictionary. +/// @param context The user-defined context parameter given to the apply +/// function. +typedef CFDictionaryApplierFunction + = ffi.Pointer>; +typedef CFDictionaryApplierFunctionFunction = ffi.Void Function( + ffi.Pointer key, + ffi.Pointer value, + ffi.Pointer context); +typedef DartCFDictionaryApplierFunctionFunction = void Function( + ffi.Pointer key, + ffi.Pointer value, + ffi.Pointer context); + +final class CFArrayCallBacks extends ffi.Struct { + @CFIndex() + external int version; + + external CFArrayRetainCallBack retain; + + external CFArrayReleaseCallBack release; + + external CFArrayCopyDescriptionCallBack copyDescription; + + external CFArrayEqualCallBack equal; +} + +/// ! +/// @typedef CFArrayCallBacks +/// Structure containing the callbacks of a CFArray. +/// @field version The version number of the structure type being passed +/// in as a parameter to the CFArray creation functions. This +/// structure is version 0. +/// @field retain The callback used to add a retain for the array on +/// values as they are put into the array. This callback returns +/// the value to store in the array, which is usually the value +/// parameter passed to this callback, but may be a different +/// value if a different value should be stored in the array. +/// The array's allocator is passed as the first argument. +/// @field release The callback used to remove a retain previously added +/// for the array from values as they are removed from the +/// array. The array's allocator is passed as the first +/// argument. +/// @field copyDescription The callback used to create a descriptive +/// string representation of each value in the array. This is +/// used by the CFCopyDescription() function. +/// @field equal The callback used to compare values in the array for +/// equality for some operations. +typedef CFArrayRetainCallBack + = ffi.Pointer>; +typedef CFArrayRetainCallBackFunction = ffi.Pointer Function( + CFAllocatorRef allocator, ffi.Pointer value); +typedef CFArrayReleaseCallBack + = ffi.Pointer>; +typedef CFArrayReleaseCallBackFunction = ffi.Void Function( + CFAllocatorRef allocator, ffi.Pointer value); +typedef DartCFArrayReleaseCallBackFunction = void Function( + CFAllocatorRef allocator, ffi.Pointer value); +typedef CFArrayCopyDescriptionCallBack + = ffi.Pointer>; +typedef CFArrayCopyDescriptionCallBackFunction = CFStringRef Function( + ffi.Pointer value); +typedef CFArrayEqualCallBack + = ffi.Pointer>; +typedef CFArrayEqualCallBackFunction = ffi.UnsignedChar Function( + ffi.Pointer value1, ffi.Pointer value2); +typedef DartCFArrayEqualCallBackFunction = int Function( + ffi.Pointer value1, ffi.Pointer value2); + +/// ! +/// @typedef CFArrayRef +/// This is the type of a reference to immutable CFArrays. +typedef CFArrayRef = ffi.Pointer; + +final class CFArray extends ffi.Opaque {} + +/// ! +/// @typedef CFMutableArrayRef +/// This is the type of a reference to mutable CFArrays. +typedef CFMutableArrayRef = ffi.Pointer; + +/// Range type +final class CFRange extends ffi.Struct { + @CFIndex() + external int location; + + @CFIndex() + external int length; +} + +/// ! +/// @typedef CFArrayApplierFunction +/// Type of the callback function used by the apply functions of +/// CFArrays. +/// @param value The current value from the array. +/// @param context The user-defined context parameter given to the apply +/// function. +typedef CFArrayApplierFunction + = ffi.Pointer>; +typedef CFArrayApplierFunctionFunction = ffi.Void Function( + ffi.Pointer value, ffi.Pointer context); +typedef DartCFArrayApplierFunctionFunction = void Function( + ffi.Pointer value, ffi.Pointer context); + +/// A standard comparison function +typedef CFComparatorFunction + = ffi.Pointer>; +typedef CFComparatorFunctionFunction = CFComparisonResult Function( + ffi.Pointer val1, + ffi.Pointer val2, + ffi.Pointer context); +typedef DartCFComparatorFunctionFunction = DartCFIndex Function( + ffi.Pointer val1, + ffi.Pointer val2, + ffi.Pointer context); + +/// Values returned from comparison functions +typedef CFComparisonResult = CFIndex; +typedef CFDataRef = ffi.Pointer; + +final class CFData extends ffi.Opaque {} + +typedef CFNotificationName = CFStringRef; +typedef CFLocaleKey = CFStringRef; + +/// Values for kCFLocaleCalendarIdentifier +typedef CFCalendarIdentifier = CFStringRef; +typedef CFErrorDomain = CFStringRef; + +/// Identifier for character encoding; the values are the same as Text Encoding Converter TextEncoding. +typedef CFStringEncoding = ffi.UnsignedInt; +typedef DartCFStringEncoding = int; + +const int kCFCompareLessThan = -1; + +const int kCFCompareEqualTo = 0; + +const int kCFCompareGreaterThan = 1; + +const int kCFDataSearchBackwards = 1; + +const int kCFDataSearchAnchored = 2; + +const int kCFCharacterSetControl = 1; + +const int kCFCharacterSetWhitespace = 2; + +const int kCFCharacterSetWhitespaceAndNewline = 3; + +const int kCFCharacterSetDecimalDigit = 4; + +const int kCFCharacterSetLetter = 5; + +const int kCFCharacterSetLowercaseLetter = 6; + +const int kCFCharacterSetUppercaseLetter = 7; + +const int kCFCharacterSetNonBase = 8; + +const int kCFCharacterSetDecomposable = 9; + +const int kCFCharacterSetAlphaNumeric = 10; + +const int kCFCharacterSetPunctuation = 11; + +const int kCFCharacterSetCapitalizedLetter = 13; + +const int kCFCharacterSetSymbol = 14; + +const int kCFCharacterSetNewline = 15; + +const int kCFCharacterSetIllegal = 12; + +const int kCFNotificationDeliverImmediately = 1; + +const int kCFNotificationPostToAllSessions = 2; + +const int kCFLocaleLanguageDirectionUnknown = 0; + +const int kCFLocaleLanguageDirectionLeftToRight = 1; + +const int kCFLocaleLanguageDirectionRightToLeft = 2; + +const int kCFLocaleLanguageDirectionTopToBottom = 3; + +const int kCFLocaleLanguageDirectionBottomToTop = 4; + +const int kCFStringEncodingMacRoman = 0; + +const int kCFStringEncodingWindowsLatin1 = 1280; + +const int kCFStringEncodingISOLatin1 = 513; + +const int kCFStringEncodingNextStepLatin = 2817; + +const int kCFStringEncodingASCII = 1536; + +const int kCFStringEncodingUnicode = 256; + +const int kCFStringEncodingUTF8 = 134217984; + +const int kCFStringEncodingNonLossyASCII = 3071; + +const int kCFStringEncodingUTF16 = 256; + +const int kCFStringEncodingUTF16BE = 268435712; + +const int kCFStringEncodingUTF16LE = 335544576; + +const int kCFStringEncodingUTF32 = 201326848; + +const int kCFStringEncodingUTF32BE = 402653440; + +const int kCFStringEncodingUTF32LE = 469762304; + +const int kCFCompareCaseInsensitive = 1; + +const int kCFCompareBackwards = 4; + +const int kCFCompareAnchored = 8; + +const int kCFCompareNonliteral = 16; + +const int kCFCompareLocalized = 32; + +const int kCFCompareNumerically = 64; + +const int kCFCompareDiacriticInsensitive = 128; + +const int kCFCompareWidthInsensitive = 256; + +const int kCFCompareForcedOrdering = 512; + +const int kCFStringNormalizationFormD = 0; + +const int kCFStringNormalizationFormKD = 1; + +const int kCFStringNormalizationFormC = 2; + +const int kCFStringNormalizationFormKC = 3; diff --git a/packages/celest_core/lib/src/native/darwin/darwin_ffi_helpers.dart b/packages/celest_core/lib/src/native/darwin/darwin_ffi_helpers.dart new file mode 100644 index 00000000..433c4024 --- /dev/null +++ b/packages/celest_core/lib/src/native/darwin/darwin_ffi_helpers.dart @@ -0,0 +1,133 @@ +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import 'core_foundation.ffi.dart'; + +extension StringToCFString on String { + /// Converts `this` to a [CFString] within the given [arena]. + Pointer toCFString(Arena arena) { + final str = toNativeUtf8(allocator: arena); + final cfStr = CFStringCreateWithCString( + nullptr, // default allocator + str.cast(), + kCFStringEncodingUTF8, + ); + arena.onReleaseAll(() { + CFRelease(cfStr.cast()); + }); + return cfStr; + } + + /// Converts `this` to a [CFData] within the given [arena]. + Pointer toCFData(Arena arena) { + final data = toNativeUtf8(allocator: arena); + final cfData = CFDataCreate( + nullptr, // default allocator + data.cast(), + data.length, + ); + arena.onReleaseAll(() { + CFRelease(cfData.cast()); + }); + return cfData; + } +} + +extension MapToCFDictionary on Map { + /// Converts `this` to a [CFDictionary] within the given [arena]. + Pointer toCFDictionary(Arena arena) { + final cfKeys = arena(length); + final cfValues = arena(length); + var i = 0; + for (final entry in entries) { + cfKeys[i] = entry.key.cast(); + cfValues[i] = entry.value.cast(); + i++; + } + final cfDict = CFDictionaryCreate( + nullptr, // default allocator + cfKeys, + cfValues, + length, + nullptr, // kCFTypeDictionaryKeyCallBacks + nullptr, // kCFTypeDictionaryValueCallBacks + ); + arena.onReleaseAll(() { + CFRelease(cfDict.cast()); + }); + return cfDict; + } +} + +extension CFDataRefToString on CFDataRef { + /// Converts `this` to a [String]. + String? toDartString() { + if (this == nullptr) { + return null; + } + final ptr = CFDataGetBytePtr(this); + if (ptr == nullptr) { + return null; + } + return ptr.cast().toDartString(); + } +} + +extension CFStringRefToString on CFStringRef { + /// Converts `this` to a [String]. + String? toDartString() { + if (this == nullptr) { + return null; + } + final cStringPtr = CFStringGetCStringPtr( + this, + kCFStringEncodingUTF8, + ); + if (cStringPtr != nullptr) { + return cStringPtr.cast().toDartString(); + } + // Call CFStringGetCString as a backup. + // See: https://developer.apple.com/documentation/corefoundation/1542133-cfstringgetcstringptr + final strLen = CFStringGetLength(this); + final maxLen = CFStringGetMaximumSizeForEncoding( + strLen, + kCFStringEncodingUTF8, + ) + + 1 /* terminating NUL byte */; + final buffer = calloc(maxLen); + try { + final ret = CFStringGetCString( + this, + buffer, + maxLen, + kCFStringEncodingUTF8, + ); + if (ret == 0 /* FALSE */) { + return null; + } + return buffer.cast().toDartString(); + } finally { + calloc.free(buffer); + } + } +} + +extension CFArrayToList on CFArrayRef { + /// Converts `this` to a [List]. + List toList() { + if (this == nullptr) { + return const []; + } + final length = CFArrayGetCount(this); + if (length == 0) { + return const []; + } + final list = []; + for (var i = 0; i < length; i++) { + final value = CFArrayGetValueAtIndex(this, i); + list.add(value); + } + return list; + } +} diff --git a/packages/celest_core/lib/src/native/darwin/security.ffi.dart b/packages/celest_core/lib/src/native/darwin/security.ffi.dart new file mode 100644 index 00000000..5693f1f3 --- /dev/null +++ b/packages/celest_core/lib/src/native/darwin/security.ffi.dart @@ -0,0 +1,2758 @@ +// ignore_for_file: type=lint +// ignore_for_file: return_of_invalid_type +// ignore_for_file: unnecessary_non_null_assertion + +// AUTO GENERATED FILE, DO NOT EDIT. +// +// Generated by `package:ffigen`. +import 'dart:ffi' as ffi; +import 'package:celest_core/src/native/darwin/core_foundation.ffi.dart' as cf; + +@ffi.Native() +external double kCFCoreFoundationVersionNumber; + +/// Constant used by some functions to indicate failed searches. +@ffi.Native() +external final int kCFNotFound; + +/// the singleton null instance +@ffi.Native>() +external final ffi.Pointer<__CFNull> kCFNull; + +/// This is a synonym for NULL, if you'd rather use a named constant. +@ffi.Native>() +external final ffi.Pointer<__CFAllocator> kCFAllocatorDefault; + +/// Default system allocator; you rarely need to use this. +@ffi.Native>() +external final ffi.Pointer<__CFAllocator> kCFAllocatorSystemDefault; + +/// This allocator uses malloc(), realloc(), and free(). This should not be +/// generally used; stick to kCFAllocatorDefault whenever possible. This +/// allocator is useful as the "bytesDeallocator" in CFData or +/// "contentsDeallocator" in CFString where the memory was obtained as a +/// result of malloc() type functions. +@ffi.Native>() +external final ffi.Pointer<__CFAllocator> kCFAllocatorMalloc; + +/// This allocator explicitly uses the default malloc zone, returned by +/// malloc_default_zone(). It should only be used when an object is +/// safe to be allocated in non-scanned memory. +@ffi.Native>() +external final ffi.Pointer<__CFAllocator> kCFAllocatorMallocZone; + +/// Null allocator which does nothing and allocates no memory. This allocator +/// is useful as the "bytesDeallocator" in CFData or "contentsDeallocator" +/// in CFString where the memory should not be freed. +@ffi.Native>() +external final ffi.Pointer<__CFAllocator> kCFAllocatorNull; + +/// Special allocator argument to CFAllocatorCreate() which means +/// "use the functions given in the context to allocate the allocator +/// itself as well". +@ffi.Native>() +external final ffi.Pointer<__CFAllocator> kCFAllocatorUseContext; + +/// ! +/// @function SecCopyErrorMessageString +/// @abstract Returns a string describing the specified error result code. +/// @param status An error result code of type OSStatus or CSSM_RETURN, as returned by a Security or CSSM function. +/// @reserved Reserved for future use. Your code should pass NULL in this parameter. +/// @result A reference to an error string, or NULL if no error string is available for the specified result code. Your code must release this reference by calling the CFRelease function. +@ffi.Native)>() +external cf.CFStringRef SecCopyErrorMessageString( + int status, + ffi.Pointer reserved, +); + +@ffi.Native>() +external final ffi.Pointer<__CFBoolean> kCFBooleanTrue; + +@ffi.Native>() +external final ffi.Pointer<__CFBoolean> kCFBooleanFalse; + +@ffi.Native>() +external final ffi.Pointer<__CFNumber> kCFNumberPositiveInfinity; + +@ffi.Native>() +external final ffi.Pointer<__CFNumber> kCFNumberNegativeInfinity; + +@ffi.Native>() +external final ffi.Pointer<__CFNumber> kCFNumberNaN; + +/// ! +/// @constant kCFTypeArrayCallBacks +/// Predefined CFArrayCallBacks structure containing a set of callbacks +/// appropriate for use when the values in a CFArray are all CFTypes. +@ffi.Native() +external final CFArrayCallBacks kCFTypeArrayCallBacks; + +/// ! +/// @constant kCFTypeDictionaryKeyCallBacks +/// Predefined CFDictionaryKeyCallBacks structure containing a +/// set of callbacks appropriate for use when the keys of a +/// CFDictionary are all CFTypes. +@ffi.Native() +external final CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks; + +/// ! +/// @constant kCFCopyStringDictionaryKeyCallBacks +/// Predefined CFDictionaryKeyCallBacks structure containing a +/// set of callbacks appropriate for use when the keys of a +/// CFDictionary are all CFStrings, which may be mutable and +/// need to be copied in order to serve as constant keys for +/// the values in the dictionary. +@ffi.Native() +external final CFDictionaryKeyCallBacks kCFCopyStringDictionaryKeyCallBacks; + +/// ! +/// @constant kCFTypeDictionaryValueCallBacks +/// Predefined CFDictionaryValueCallBacks structure containing a set +/// of callbacks appropriate for use when the values in a CFDictionary +/// are all CFTypes. +@ffi.Native() +external final CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks; + +/// ! +/// @enum Class Key Constant +/// @discussion Predefined key constant used to get or set item class values in +/// a dictionary. Its value is one of the constants defined in the Value +/// Constants for kSecClass. +/// @constant kSecClass Specifies a dictionary key whose value is the item's +/// class code. You use this key to get or set a value of type CFTypeRef +/// that contains the item class code. +@ffi.Native() +external cf.CFStringRef kSecClass; + +/// ! +/// @enum Class Value Constants +/// @discussion Predefined item class constants used to get or set values in +/// a dictionary. The kSecClass constant is the key and its value is one +/// of the constants defined here. Note: on Mac OS X 10.6, only items +/// of class kSecClassInternetPassword are supported. +/// @constant kSecClassInternetPassword Specifies Internet password items. +/// @constant kSecClassGenericPassword Specifies generic password items. +/// @constant kSecClassCertificate Specifies certificate items. +/// @constant kSecClassKey Specifies key items. +/// @constant kSecClassIdentity Specifies identity items. +@ffi.Native() +external cf.CFStringRef kSecClassInternetPassword; + +@ffi.Native() +external cf.CFStringRef kSecClassGenericPassword; + +@ffi.Native() +external cf.CFStringRef kSecClassCertificate; + +@ffi.Native() +external cf.CFStringRef kSecClassKey; + +@ffi.Native() +external cf.CFStringRef kSecClassIdentity; + +/// ! +/// @enum Attribute Key Constants +/// @discussion Predefined item attribute keys used to get or set values in a +/// dictionary. Not all attributes apply to each item class. The table +/// below lists the currently defined attributes for each item class: +/// +/// kSecClassGenericPassword item attributes: +/// kSecAttrAccess (OS X only) +/// kSecAttrAccessControl +/// kSecAttrAccessGroup (iOS; also OS X if kSecAttrSynchronizable and/or kSecUseDataProtectionKeychain set) +/// kSecAttrAccessible (iOS; also OS X if kSecAttrSynchronizable and/or kSecUseDataProtectionKeychain set) +/// kSecAttrCreationDate +/// kSecAttrModificationDate +/// kSecAttrDescription +/// kSecAttrComment +/// kSecAttrCreator +/// kSecAttrType +/// kSecAttrLabel +/// kSecAttrIsInvisible +/// kSecAttrIsNegative +/// kSecAttrAccount +/// kSecAttrService +/// kSecAttrGeneric +/// kSecAttrSynchronizable +/// +/// kSecClassInternetPassword item attributes: +/// kSecAttrAccess (OS X only) +/// kSecAttrAccessControl +/// kSecAttrAccessGroup (iOS; also OS X if kSecAttrSynchronizable and/or kSecUseDataProtectionKeychain set) +/// kSecAttrAccessible (iOS; also OS X if kSecAttrSynchronizable and/or kSecUseDataProtectionKeychain set) +/// kSecAttrCreationDate +/// kSecAttrModificationDate +/// kSecAttrDescription +/// kSecAttrComment +/// kSecAttrCreator +/// kSecAttrType +/// kSecAttrLabel +/// kSecAttrIsInvisible +/// kSecAttrIsNegative +/// kSecAttrAccount +/// kSecAttrSecurityDomain +/// kSecAttrServer +/// kSecAttrProtocol +/// kSecAttrAuthenticationType +/// kSecAttrPort +/// kSecAttrPath +/// kSecAttrSynchronizable +/// +/// kSecClassCertificate item attributes: +/// kSecAttrAccessible (iOS only) +/// kSecAttrAccessControl (iOS only) +/// kSecAttrAccessGroup (iOS only) +/// kSecAttrCertificateType +/// kSecAttrCertificateEncoding +/// kSecAttrLabel +/// kSecAttrSubject +/// kSecAttrIssuer +/// kSecAttrSerialNumber +/// kSecAttrSubjectKeyID +/// kSecAttrPublicKeyHash +/// kSecAttrSynchronizable +/// +/// kSecClassKey item attributes: +/// kSecAttrAccess (OS X only) +/// kSecAttrAccessControl +/// kSecAttrAccessGroup (iOS; also OS X if kSecAttrSynchronizable and/or kSecUseDataProtectionKeychain set) +/// kSecAttrAccessible (iOS; also OS X if kSecAttrSynchronizable and/or kSecUseDataProtectionKeychain set) +/// kSecAttrKeyClass +/// kSecAttrLabel +/// kSecAttrApplicationLabel +/// kSecAttrIsPermanent +/// kSecAttrApplicationTag +/// kSecAttrKeyType +/// kSecAttrPRF (OS X only) +/// kSecAttrSalt (OS X only) +/// kSecAttrRounds (OS X only) +/// kSecAttrKeySizeInBits +/// kSecAttrEffectiveKeySize +/// kSecAttrCanEncrypt +/// kSecAttrCanDecrypt +/// kSecAttrCanDerive +/// kSecAttrCanSign +/// kSecAttrCanVerify +/// kSecAttrCanWrap +/// kSecAttrCanUnwrap +/// kSecAttrSynchronizable +/// +/// Note that the attributes kSecAttrCan* describe attributes of the +/// key itself at relatively high level. Some of these attributes are +/// mathematical -- for example, a DSA key cannot encrypt. Others are +/// key-level policy issues -- for example, it is good cryptographic +/// hygiene to use an RSA key either for encryption or signing but not +/// both. Compare these to the certificate-level policy values in +/// SecPolicy.h. +/// +/// kSecClassIdentity item attributes: +/// Since an identity is the combination of a private key and a +/// certificate, this class shares attributes of both kSecClassKey and +/// kSecClassCertificate. +/// +/// @constant kSecAttrAccessible Specifies a dictionary key whose value +/// indicates when your application needs access to an item's data. You +/// should choose the most restrictive option that meets your application's +/// needs to allow the system to protect that item in the best way possible. +/// See the "kSecAttrAccessible Value Constants" section for a list of +/// values which can be specified. +/// IMPORTANT: This attribute is currently not supported for OS X keychain +/// items, unless the kSecAttrSynchronizable attribute is also present. If +/// both attributes are specified on either OS X or iOS, the value for the +/// kSecAttrAccessible key may only be one whose name does not end with +/// "ThisDeviceOnly", as those cannot sync to another device. +/// +/// @constant kSecAttrAccessControl Specifies a dictionary key whose value +/// is SecAccessControl instance which contains access control conditions +/// for item. +/// IMPORTANT: This attribute is mutually exclusive with kSecAttrAccess +/// attribute. +/// +/// @constant kSecAttrAccess Specifies a dictionary key whose value +/// is a SecAccessRef describing the access control settings for this item. +/// This key is available on OS X only. +/// +/// @constant kSecAttrAccessGroup Specifies a dictionary key whose value is +/// a CFStringRef indicating which access group a item is in. The access +/// groups that a particular application has membership in are determined by +/// two entitlements for that application. The application-identifier +/// entitlement contains the application's single access group, unless +/// there is a keychain-access-groups entitlement present. The latter +/// has as its value a list of access groups; the first item in this list +/// is the default access group. Unless a specific access group is provided +/// as the value of kSecAttrAccessGroup when SecItemAdd is called, new items +/// are created in the application's default access group. Specifying this +/// attribute in SecItemCopyMatching, SecItemUpdate, or SecItemDelete calls +/// limits the search to the specified access group (of which the calling +/// application must be a member to obtain matching results.) To share +/// keychain items between multiple applications, each application must have +/// a common group listed in its keychain-access-groups entitlement, and each +/// must specify this shared access group name as the value for the +/// kSecAttrAccessGroup key in the dictionary passed to SecItem functions. +/// +/// @constant kSecAttrSynchronizable Specifies a dictionary key whose value is +/// a CFBooleanRef indicating whether the item in question can be synchronized. +/// To add a new item which can be synced to other devices, or to obtain +/// synchronizable results from a query, supply this key with a value of +/// kCFBooleanTrue. If the key is not supplied, or has a value of +/// kCFBooleanFalse, then no synchronizable items will be added or returned. +/// A predefined value, kSecAttrSynchronizableAny, may be provided instead of +/// kCFBooleanTrue if both synchronizable and non-synchronizable results are +/// desired. +/// +/// IMPORTANT: Specifying the kSecAttrSynchronizable key has several caveats: +/// +/// - Updating or deleting items using the kSecAttrSynchronizable key will +/// affect all copies of the item, not just the one on your local device. +/// Be sure that it makes sense to use the same password on all devices +/// before deciding to make a password synchronizable. +/// - Starting in iOS 14, macOS 11, and watchOS 7, the keychain +/// synchronizes passwords, certificates, and cryptographic keys. +/// Earlier OS versions synchronize only passwords. +/// - Items stored or obtained using the kSecAttrSynchronizable key cannot +/// specify SecAccessRef-based access control with kSecAttrAccess. If a +/// password is intended to be shared between multiple applications, the +/// kSecAttrAccessGroup key must be specified, and each application +/// using this password must have a 'keychain-access-groups' entitlement +/// with the specified access group value. +/// - Items stored or obtained using the kSecAttrSynchronizable key may +/// not also specify a kSecAttrAccessible value which is incompatible +/// with syncing (namely, those whose names end with "ThisDeviceOnly".) +/// - On macOS, when kSecAttrSynchronizable is set to true, returning +/// references is supported only for Certificate, Key or Identity items. +/// - Persistent references to synchronizable items should be avoided; +/// while they may work locally, they cannot be moved between devices, +/// and may not resolve if the item is modified on some other device. +/// - When specifying a query that uses the kSecAttrSynchronizable key, +/// search keys are limited to the item's class and attributes. +/// The only search constant which may be used is kSecMatchLimit; other +/// constants using the kSecMatch prefix are not supported at this time. +/// +/// @constant kSecAttrSynchronizableAny Specifies that both synchronizable and +/// non-synchronizable results should be returned from this query. This may be +/// used as a value for the kSecAttrSynchronizable dictionary key in a call to +/// SecItemCopyMatching, SecItemUpdate, or SecItemDelete. +/// +/// @constant kSecAttrCreationDate (read-only) Specifies a dictionary key whose +/// value is the item's creation date. You use this key to get a value +/// of type CFDateRef that represents the date the item was created. +/// @constant kSecAttrModificationDate (read-only) Specifies a dictionary key +/// whose value is the item's modification date. You use this key to get +/// a value of type CFDateRef that represents the last time the item was +/// updated. +/// @constant kSecAttrDescription Specifies a dictionary key whose value is +/// the item's description attribute. You use this key to set or get a +/// value of type CFStringRef that represents a user-visible string +/// describing this particular kind of item (e.g., "disk image password"). +/// @constant kSecAttrComment Specifies a dictionary key whose value is the +/// item's comment attribute. You use this key to set or get a value of +/// type CFStringRef containing the user-editable comment for this item. +/// @constant kSecAttrCreator Specifies a dictionary key whose value is the +/// item's creator attribute. You use this key to set or get a value of +/// type CFNumberRef that represents the item's creator. This number is +/// the unsigned integer representation of a four-character code (e.g., +/// 'aCrt'). +/// @constant kSecAttrType Specifies a dictionary key whose value is the item's +/// type attribute. You use this key to set or get a value of type +/// CFNumberRef that represents the item's type. This number is the +/// unsigned integer representation of a four-character code (e.g., +/// 'aTyp'). +/// @constant kSecAttrLabel Specifies a dictionary key whose value is the +/// item's label attribute. You use this key to set or get a value of +/// type CFStringRef containing the user-visible label for this item. +/// @constant kSecAttrIsInvisible Specifies a dictionary key whose value is the +/// item's invisible attribute. You use this key to set or get a value +/// of type CFBooleanRef that indicates whether the item is invisible +/// (i.e., should not be displayed.) +/// @constant kSecAttrIsNegative Specifies a dictionary key whose value is the +/// item's negative attribute. You use this key to set or get a value of +/// type CFBooleanRef that indicates whether there is a valid password +/// associated with this keychain item. This is useful if your application +/// doesn't want a password for some particular service to be stored in +/// the keychain, but prefers that it always be entered by the user. +/// @constant kSecAttrAccount Specifies a dictionary key whose value is the +/// item's account attribute. You use this key to set or get a CFStringRef +/// that contains an account name. (Items of class +/// kSecClassGenericPassword, kSecClassInternetPassword have this +/// attribute.) +/// @constant kSecAttrService Specifies a dictionary key whose value is the +/// item's service attribute. You use this key to set or get a CFStringRef +/// that represents the service associated with this item. (Items of class +/// kSecClassGenericPassword have this attribute.) +/// @constant kSecAttrGeneric Specifies a dictionary key whose value is the +/// item's generic attribute. You use this key to set or get a value of +/// CFDataRef that contains a user-defined attribute. (Items of class +/// kSecClassGenericPassword have this attribute.) +/// @constant kSecAttrSecurityDomain Specifies a dictionary key whose value +/// is the item's security domain attribute. You use this key to set or +/// get a CFStringRef value that represents the Internet security domain. +/// (Items of class kSecClassInternetPassword have this attribute.) +/// @constant kSecAttrServer Specifies a dictionary key whose value is the +/// item's server attribute. You use this key to set or get a value of +/// type CFStringRef that contains the server's domain name or IP address. +/// (Items of class kSecClassInternetPassword have this attribute.) +/// @constant kSecAttrProtocol Specifies a dictionary key whose value is the +/// item's protocol attribute. You use this key to set or get a value of +/// type CFNumberRef that denotes the protocol for this item (see the +/// SecProtocolType enum in SecKeychainItem.h). (Items of class +/// kSecClassInternetPassword have this attribute.) +/// @constant kSecAttrAuthenticationType Specifies a dictionary key whose value +/// is the item's authentication type attribute. You use this key to set +/// or get a value of type CFNumberRef that denotes the authentication +/// scheme for this item (see the kSecAttrAuthenticationType value +/// constants below). +/// @constant kSecAttrPort Specifies a dictionary key whose value is the item's +/// port attribute. You use this key to set or get a CFNumberRef value +/// that represents an Internet port number. (Items of class +/// kSecClassInternetPassword have this attribute.) +/// @constant kSecAttrPath Specifies a dictionary key whose value is the item's +/// path attribute, typically this is the path component of the URL. You use +/// this key to set or get a CFStringRef value that represents a path. (Items +/// of class kSecClassInternetPassword have this attribute.) +/// @constant kSecAttrSubject (read-only) Specifies a dictionary key whose +/// value is the item's subject. You use this key to get a value of type +/// CFDataRef that contains the X.500 subject name of a certificate. +/// (Items of class kSecClassCertificate have this attribute.) +/// @constant kSecAttrIssuer (read-only) Specifies a dictionary key whose value +/// is the item's issuer. You use this key to get a value of type +/// CFDataRef that contains the X.500 issuer name of a certificate. (Items +/// of class kSecClassCertificate have this attribute.) +/// @constant kSecAttrSerialNumber (read-only) Specifies a dictionary key whose +/// value is the item's serial number. You use this key to get a value +/// of type CFDataRef that contains the serial number data of a +/// certificate. (Items of class kSecClassCertificate have this +/// attribute.) +/// @constant kSecAttrSubjectKeyID (read-only) Specifies a dictionary key whose +/// value is the item's subject key ID. You use this key to get a value +/// of type CFDataRef that contains the subject key ID of a certificate. +/// (Items of class kSecClassCertificate have this attribute.) +/// @constant kSecAttrPublicKeyHash (read-only) Specifies a dictionary key +/// whose value is the item's public key hash. You use this key to get a +/// value of type CFDataRef that contains the hash of a certificate's +/// public key. (Items of class kSecClassCertificate have this attribute.) +/// @constant kSecAttrCertificateType (read-only) Specifies a dictionary key +/// whose value is the item's certificate type. You use this key to get +/// a value of type CFNumberRef that denotes the certificate type +/// (On iOS, currently the value of this attribute must be equal to the +/// version of the X509 certificate. So, 1 for v1, 2 for v2, and 3 for v3 +/// certificates). (On OSX, see the CSSM_CERT_TYPE enum in cssmtype.h). +/// Only items of class kSecClassCertificate have this attribute. +/// @constant kSecAttrCertificateEncoding (read-only) Specifies a dictionary +/// key whose value is the item's certificate encoding. You use this key +/// to get a value of type CFNumberRef that denotes the certificate +/// encoding (On iOS, currently only the value 3 meaning +/// kSecAttrCertificateEncodingDER is supported). On OSX, see the +/// CSSM_CERT_ENCODING enum in cssmtype.h. Only items of class +/// kSecClassCertificate have this attribute. +/// @constant kSecAttrKeyClass (read only) Specifies a dictionary key whose +/// value is one of kSecAttrKeyClassPublic, kSecAttrKeyClassPrivate or +/// kSecAttrKeyClassSymmetric. +/// @constant kSecAttrApplicationLabel Specifies a dictionary key whose value +/// is the key's application label attribute. This is different from the +/// kSecAttrLabel (which is intended to be human-readable). This attribute +/// is used to look up a key programmatically; in particular, for keys of +/// class kSecAttrKeyClassPublic and kSecAttrKeyClassPrivate, the value of +/// this attribute is the hash of the public key. This item is a type of CFDataRef. +/// Legacy keys may contain a UUID in this field as a CFStringRef. +/// @constant kSecAttrIsPermanent Specifies a dictionary key whose value is a +/// CFBooleanRef indicating whether the key in question will be stored +/// permanently. +/// @constant kSecAttrIsSensitive Specifies a dictionary key whose value is a +/// CFBooleanRef indicating that the key in question can only be exported +/// in a wrapped (encrypted) format. OS X only. +/// @constant kSecAttrIsExtractable Specifies a dictionary key whose value is a +/// CFBooleanRef indicating whether the key in question can be exported from +/// its keychain container. OS X only. +/// @constant kSecAttrApplicationTag Specifies a dictionary key whose value is a +/// CFDataRef containing private tag data. +/// @constant kSecAttrKeyType Specifies a dictionary key whose value is a +/// CFNumberRef indicating the algorithm associated with this key +/// (On iOS, currently only the value 42 is supported, alternatively you can use +/// kSecAttrKeyTypeRSA). (On OSX, see the CSSM_ALGORITHMS enum in cssmtype.h). +/// +/// @constant kSecAttrPRF Specifies a dictionary key whose value is the PRF +/// (pseudo-random function) for this key (see "kSecAttrPRF Value Constants".) +/// OS X only. +/// @constant kSecAttrSalt Specifies a dictionary key whose value is a +/// CFData containing the salt to use for this key. OS X only. +/// @constant kSecAttrRounds Specifies a dictionary key whose value is the +/// number of rounds for the pseudo-random function specified by kSecAttrPRF. +/// OS X only. +/// @constant kSecAttrKeySizeInBits Specifies a dictionary key whose value +/// is a CFNumberRef indicating the number of bits in this key. +/// @constant kSecAttrEffectiveKeySize Specifies a dictionary key whose value +/// is a CFNumberRef indicating the effective number of bits in this key. +/// For example, a DES key has a kSecAttrKeySizeInBits of 64, but a +/// kSecAttrEffectiveKeySize of 56 bits. +/// @constant kSecAttrCanEncrypt Specifies a dictionary key whole value is a +/// CFBooleanRef indicating whether the key in question can be used to +/// encrypt data. +/// @constant kSecAttrCanDecrypt Specifies a dictionary key whose value is a +/// CFBooleanRef indicating whether the key in question can be used to +/// decrypt data. +/// @constant kSecAttrCanDerive Specifies a dictionary key whole value is a +/// CFBooleanRef indicating whether the key in question can be used to +/// derive another key. +/// @constant kSecAttrCanSign Specifies a dictionary key whole value is a +/// CFBooleanRef indicating whether the key in question can be used to +/// create a digital signature. +/// @constant kSecAttrCanVerify Specifies a dictionary key whole value is a +/// CFBooleanRef indicating whether the key in question can be used to +/// verify a digital signature. +/// @constant kSecAttrCanWrap Specifies a dictionary key whole value is a +/// CFBooleanRef indicating whether the key in question can be used to +/// wrap another key. +/// @constant kSecAttrCanUnwrap Specifies a dictionary key whole value is a +/// CFBooleanRef indicating whether the key in question can be used to +/// unwrap another key. +/// @constant kSecAttrSyncViewHint Specifies a dictionary key whose value is +/// a CFStringRef. This value is part of the primary key of each item, and +/// can be used to help distiguish Sync Views when defining their +/// queries. iOS and sychronizable items only. +/// @constant kSecAttrTokenID Specifies a dictionary key whose presence +/// indicates that item is backed by external token. Value of this attribute +/// is CFStringRef uniquely identifying containing token. When this attribute +/// is not present, item is stored in internal keychain database. +/// Note that once item is created, this attribute cannot be changed - in other +/// words it is not possible to migrate existing items to, from or between tokens. +/// Currently the only available value for this attribute is +/// kSecAttrTokenIDSecureEnclave, which indicates that item (private key) is +/// backed by device's Secure Enclave. +@ffi.Native() +external cf.CFStringRef kSecAttrAccessible; + +@ffi.Native() +external cf.CFStringRef kSecAttrAccess; + +@ffi.Native() +external cf.CFStringRef kSecAttrAccessControl; + +@ffi.Native() +external cf.CFStringRef kSecAttrAccessGroup; + +@ffi.Native() +external cf.CFStringRef kSecAttrSynchronizable; + +@ffi.Native() +external cf.CFStringRef kSecAttrSynchronizableAny; + +@ffi.Native() +external cf.CFStringRef kSecAttrCreationDate; + +@ffi.Native() +external cf.CFStringRef kSecAttrModificationDate; + +@ffi.Native() +external cf.CFStringRef kSecAttrDescription; + +@ffi.Native() +external cf.CFStringRef kSecAttrComment; + +@ffi.Native() +external cf.CFStringRef kSecAttrCreator; + +@ffi.Native() +external cf.CFStringRef kSecAttrType; + +@ffi.Native() +external cf.CFStringRef kSecAttrLabel; + +@ffi.Native() +external cf.CFStringRef kSecAttrIsInvisible; + +@ffi.Native() +external cf.CFStringRef kSecAttrIsNegative; + +@ffi.Native() +external cf.CFStringRef kSecAttrAccount; + +@ffi.Native() +external cf.CFStringRef kSecAttrService; + +@ffi.Native() +external cf.CFStringRef kSecAttrGeneric; + +@ffi.Native() +external cf.CFStringRef kSecAttrSecurityDomain; + +@ffi.Native() +external cf.CFStringRef kSecAttrServer; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocol; + +@ffi.Native() +external cf.CFStringRef kSecAttrAuthenticationType; + +@ffi.Native() +external cf.CFStringRef kSecAttrPort; + +@ffi.Native() +external cf.CFStringRef kSecAttrPath; + +@ffi.Native() +external cf.CFStringRef kSecAttrSubject; + +@ffi.Native() +external cf.CFStringRef kSecAttrIssuer; + +@ffi.Native() +external cf.CFStringRef kSecAttrSerialNumber; + +@ffi.Native() +external cf.CFStringRef kSecAttrSubjectKeyID; + +@ffi.Native() +external cf.CFStringRef kSecAttrPublicKeyHash; + +@ffi.Native() +external cf.CFStringRef kSecAttrCertificateType; + +@ffi.Native() +external cf.CFStringRef kSecAttrCertificateEncoding; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyClass; + +@ffi.Native() +external cf.CFStringRef kSecAttrApplicationLabel; + +@ffi.Native() +external cf.CFStringRef kSecAttrIsPermanent; + +@ffi.Native() +external cf.CFStringRef kSecAttrIsSensitive; + +@ffi.Native() +external cf.CFStringRef kSecAttrIsExtractable; + +@ffi.Native() +external cf.CFStringRef kSecAttrApplicationTag; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyType; + +@ffi.Native() +external cf.CFStringRef kSecAttrPRF; + +@ffi.Native() +external cf.CFStringRef kSecAttrSalt; + +@ffi.Native() +external cf.CFStringRef kSecAttrRounds; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeySizeInBits; + +@ffi.Native() +external cf.CFStringRef kSecAttrEffectiveKeySize; + +@ffi.Native() +external cf.CFStringRef kSecAttrCanEncrypt; + +@ffi.Native() +external cf.CFStringRef kSecAttrCanDecrypt; + +@ffi.Native() +external cf.CFStringRef kSecAttrCanDerive; + +@ffi.Native() +external cf.CFStringRef kSecAttrCanSign; + +@ffi.Native() +external cf.CFStringRef kSecAttrCanVerify; + +@ffi.Native() +external cf.CFStringRef kSecAttrCanWrap; + +@ffi.Native() +external cf.CFStringRef kSecAttrCanUnwrap; + +@ffi.Native() +external cf.CFStringRef kSecAttrSyncViewHint; + +@ffi.Native() +external cf.CFStringRef kSecAttrTokenID; + +@ffi.Native() +external cf.CFStringRef kSecAttrPersistantReference; + +@ffi.Native() +external cf.CFStringRef kSecAttrPersistentReference; + +/// ! +/// @enum kSecAttrAccessible Value Constants +/// @discussion Predefined item attribute constants used to get or set values +/// in a dictionary. The kSecAttrAccessible constant is the key and its +/// value is one of the constants defined here. +/// When asking SecItemCopyMatching to return the item's data, the error +/// errSecInteractionNotAllowed will be returned if the item's data is not +/// available until a device unlock occurs. +/// @constant kSecAttrAccessibleWhenUnlocked Item data can only be accessed +/// while the device is unlocked. This is recommended for items that only +/// need be accesible while the application is in the foreground. Items +/// with this attribute will migrate to a new device when using encrypted +/// backups. +/// @constant kSecAttrAccessibleAfterFirstUnlock Item data can only be +/// accessed once the device has been unlocked after a restart. This is +/// recommended for items that need to be accesible by background +/// applications. Items with this attribute will migrate to a new device +/// when using encrypted backups. +/// @constant kSecAttrAccessibleAlways Item data can always be accessed +/// regardless of the lock state of the device. This is not recommended +/// for anything except system use. Items with this attribute will migrate +/// to a new device when using encrypted backups. +/// @constant kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly Item data can +/// only be accessed while the device is unlocked. This is recommended for +/// items that only need to be accessible while the application is in the +/// foreground and requires a passcode to be set on the device. Items with +/// this attribute will never migrate to a new device, so after a backup +/// is restored to a new device, these items will be missing. This +/// attribute will not be available on devices without a passcode. Disabling +/// the device passcode will cause all previously protected items to +/// be deleted. +/// @constant kSecAttrAccessibleWhenUnlockedThisDeviceOnly Item data can only +/// be accessed while the device is unlocked. This is recommended for items +/// that only need be accesible while the application is in the foreground. +/// Items with this attribute will never migrate to a new device, so after +/// a backup is restored to a new device, these items will be missing. +/// @constant kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly Item data can +/// only be accessed once the device has been unlocked after a restart. +/// This is recommended for items that need to be accessible by background +/// applications. Items with this attribute will never migrate to a new +/// device, so after a backup is restored to a new device these items will +/// be missing. +/// @constant kSecAttrAccessibleAlwaysThisDeviceOnly Item data can always +/// be accessed regardless of the lock state of the device. This option +/// is not recommended for anything except system use. Items with this +/// attribute will never migrate to a new device, so after a backup is +/// restored to a new device, these items will be missing. +@ffi.Native() +external cf.CFStringRef kSecAttrAccessibleWhenUnlocked; + +@ffi.Native() +external cf.CFStringRef kSecAttrAccessibleAfterFirstUnlock; + +@ffi.Native() +external cf.CFStringRef kSecAttrAccessibleAlways; + +@ffi.Native() +external cf.CFStringRef kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly; + +@ffi.Native() +external cf.CFStringRef kSecAttrAccessibleWhenUnlockedThisDeviceOnly; + +@ffi.Native() +external cf.CFStringRef kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + +@ffi.Native() +external cf.CFStringRef kSecAttrAccessibleAlwaysThisDeviceOnly; + +/// ! +/// @enum kSecAttrProtocol Value Constants +/// @discussion Predefined item attribute constants used to get or set values +/// in a dictionary. The kSecAttrProtocol constant is the key and its +/// value is one of the constants defined here. +/// @constant kSecAttrProtocolFTP. +/// @constant kSecAttrProtocolFTPAccount. +/// @constant kSecAttrProtocolHTTP. +/// @constant kSecAttrProtocolIRC. +/// @constant kSecAttrProtocolNNTP. +/// @constant kSecAttrProtocolPOP3. +/// @constant kSecAttrProtocolSMTP. +/// @constant kSecAttrProtocolSOCKS. +/// @constant kSecAttrProtocolIMAP. +/// @constant kSecAttrProtocolLDAP. +/// @constant kSecAttrProtocolAppleTalk. +/// @constant kSecAttrProtocolAFP. +/// @constant kSecAttrProtocolTelnet. +/// @constant kSecAttrProtocolSSH. +/// @constant kSecAttrProtocolFTPS. +/// @constant kSecAttrProtocolHTTPS. +/// @constant kSecAttrProtocolHTTPProxy. +/// @constant kSecAttrProtocolHTTPSProxy. +/// @constant kSecAttrProtocolFTPProxy. +/// @constant kSecAttrProtocolSMB. +/// @constant kSecAttrProtocolRTSP. +/// @constant kSecAttrProtocolRTSPProxy. +/// @constant kSecAttrProtocolDAAP. +/// @constant kSecAttrProtocolEPPC. +/// @constant kSecAttrProtocolIPP. +/// @constant kSecAttrProtocolNNTPS. +/// @constant kSecAttrProtocolLDAPS. +/// @constant kSecAttrProtocolTelnetS. +/// @constant kSecAttrProtocolIMAPS. +/// @constant kSecAttrProtocolIRCS. +/// @constant kSecAttrProtocolPOP3S. +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolFTP; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolFTPAccount; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolHTTP; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolIRC; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolNNTP; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolPOP3; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolSMTP; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolSOCKS; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolIMAP; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolLDAP; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolAppleTalk; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolAFP; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolTelnet; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolSSH; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolFTPS; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolHTTPS; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolHTTPProxy; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolHTTPSProxy; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolFTPProxy; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolSMB; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolRTSP; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolRTSPProxy; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolDAAP; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolEPPC; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolIPP; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolNNTPS; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolLDAPS; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolTelnetS; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolIMAPS; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolIRCS; + +@ffi.Native() +external cf.CFStringRef kSecAttrProtocolPOP3S; + +/// ! +/// @enum kSecAttrAuthenticationType Value Constants +/// @discussion Predefined item attribute constants used to get or set values +/// in a dictionary. The kSecAttrAuthenticationType constant is the key +/// and its value is one of the constants defined here. +/// @constant kSecAttrAuthenticationTypeNTLM. +/// @constant kSecAttrAuthenticationTypeMSN. +/// @constant kSecAttrAuthenticationTypeDPA. +/// @constant kSecAttrAuthenticationTypeRPA. +/// @constant kSecAttrAuthenticationTypeHTTPBasic. +/// @constant kSecAttrAuthenticationTypeHTTPDigest. +/// @constant kSecAttrAuthenticationTypeHTMLForm. +/// @constant kSecAttrAuthenticationTypeDefault. +@ffi.Native() +external cf.CFStringRef kSecAttrAuthenticationTypeNTLM; + +@ffi.Native() +external cf.CFStringRef kSecAttrAuthenticationTypeMSN; + +@ffi.Native() +external cf.CFStringRef kSecAttrAuthenticationTypeDPA; + +@ffi.Native() +external cf.CFStringRef kSecAttrAuthenticationTypeRPA; + +@ffi.Native() +external cf.CFStringRef kSecAttrAuthenticationTypeHTTPBasic; + +@ffi.Native() +external cf.CFStringRef kSecAttrAuthenticationTypeHTTPDigest; + +@ffi.Native() +external cf.CFStringRef kSecAttrAuthenticationTypeHTMLForm; + +@ffi.Native() +external cf.CFStringRef kSecAttrAuthenticationTypeDefault; + +/// ! +/// @enum kSecAttrKeyClass Value Constants +/// @discussion Predefined item attribute constants used to get or set values +/// in a dictionary. The kSecAttrKeyClass constant is the key +/// and its value is one of the constants defined here. +/// @constant kSecAttrKeyClassPublic. +/// @constant kSecAttrKeyClassPrivate. +/// @constant kSecAttrKeyClassSymmetric. +@ffi.Native() +external cf.CFStringRef kSecAttrKeyClassPublic; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyClassPrivate; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyClassSymmetric; + +/// ! +/// @enum kSecAttrKeyType Value Constants +/// @discussion Predefined item attribute constants used to get or set values +/// in a dictionary. The kSecAttrKeyType constant is the key +/// and its value is one of the constants defined here. +/// @constant kSecAttrKeyTypeECSECPrimeRandom. The used curve is P-192, P-256, P-384 or P-521. +/// The size is specified by kSecAttrKeySizeInBits attribute. Curves are defined in FIPS PUB 186-4 standard. +/// @constant kSecAttrKeyTypeEC This is the legacy name for kSecAttrKeyTypeECSECPrimeRandom, new applications should not use it. +/// @constant kSecAttrKeyTypeDSA (OSX only) +/// @constant kSecAttrKeyTypeAES (OSX only) +/// @constant kSecAttrKeyType3DES (OSX only) +/// @constant kSecAttrKeyTypeRC4 (OSX only) +/// @constant kSecAttrKeyTypeRC2 (OSX only) +/// @constant kSecAttrKeyTypeCAST (OSX only) +/// @constant kSecAttrKeyTypeECDSA (deprecated; use kSecAttrKeyTypeECSECPrimeRandom instead.) (OSX only) +@ffi.Native() +external cf.CFStringRef kSecAttrKeyTypeRSA; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyTypeDSA; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyTypeAES; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyTypeDES; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyType3DES; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyTypeRC4; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyTypeRC2; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyTypeCAST; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyTypeECDSA; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyTypeEC; + +@ffi.Native() +external cf.CFStringRef kSecAttrKeyTypeECSECPrimeRandom; + +/// @enum kSecAttrPRF Value Constants +/// @discussion Predefined item attribute constants used to specify the PRF +/// to use with SecKeyDeriveFromPassword. OS X only. +/// @constant kSecAttrPRFHmacAlgSHA1 +/// @constant kSecAttrPRFHmacAlgSHA224 +/// @constant kSecAttrPRFHmacAlgSHA256 +/// @constant kSecAttrPRFHmacAlgSHA384 +/// @constant kSecAttrPRFHmacAlgSHA512 +@ffi.Native() +external cf.CFStringRef kSecAttrPRFHmacAlgSHA1; + +@ffi.Native() +external cf.CFStringRef kSecAttrPRFHmacAlgSHA224; + +@ffi.Native() +external cf.CFStringRef kSecAttrPRFHmacAlgSHA256; + +@ffi.Native() +external cf.CFStringRef kSecAttrPRFHmacAlgSHA384; + +@ffi.Native() +external cf.CFStringRef kSecAttrPRFHmacAlgSHA512; + +/// ! +/// @enum Search Constants +/// @discussion Predefined search constants used to set values in a query +/// dictionary. You can specify a combination of search attributes and +/// item attributes when looking for matching items with the +/// SecItemCopyMatching function. +/// @constant kSecMatchPolicy Specifies a dictionary key whose value is a +/// SecPolicyRef. If provided, returned certificates or identities must +/// verify with this policy. +/// @constant kSecMatchItemList OS X only. Specifies a dictionary key whose value is a +/// CFArray of SecKeychainItemRef items. If provided, returned items will be +/// limited to the subset which are contained in this list. +/// @constant kSecMatchSearchList Specifies a dictionary key whose value is a +/// CFArray of SecKeychainRef items. If provided, the search will be limited +/// to the keychains contained in this list. +/// @constant kSecMatchIssuers Specifies a dictionary key whose value is a +/// CFArray of X.500 names (of type CFDataRef). If provided, returned +/// certificates or identities will be limited to those whose +/// certificate chain contains one of the issuers provided in this list. +/// @constant kSecMatchEmailAddressIfPresent Specifies a dictionary key whose +/// value is a CFStringRef containing an RFC822 email address. If +/// provided, returned certificates or identities will be limited to those +/// that contain the address in their subject or subject alternative name. +/// @constant kSecMatchSubjectContains Specifies a dictionary key whose value +/// is a CFStringRef. If provided, returned certificates or identities +/// will be limited to those containing this string in the subject. +/// @constant kSecMatchSubjectStartsWith OS X only. Specifies a dictionary key whose value +/// is a CFStringRef. If provided, returned certificates or identities +/// will be limited to those with subject names that start with this string. +/// @constant kSecMatchSubjectEndsWith OS X only. Specifies a dictionary key whose value +/// is a CFStringRef. If provided, returned certificates or identities +/// will be limited to those with subject names that end with this string. +/// @constant kSecMatchSubjectWholeString OS X only. Specifies a dictionary key whose +/// value is a CFStringRef. If provided, returned certificates or identities +/// will be limited to those matching this string exactly in the subject. +/// @constant kSecMatchCaseInsensitive Specifies a dictionary key whose value +/// is a CFBooleanRef. If this value is kCFBooleanFalse, or is not +/// provided, then case-sensitive string matching is performed. +/// @constant kSecMatchDiacriticInsensitive OS X only. Specifies a dictionary key whose +/// value is a CFBooleanRef. If this value is kCFBooleanFalse, or is not +/// provided, then diacritic-sensitive string matching is performed. +/// @constant kSecMatchWidthInsensitive OS X only. Specifies a dictionary key whose +/// value is a CFBooleanRef. If this value is kCFBooleanFalse, or is not +/// provided, then string matching is width-sensitive (e.g. 'a' != 0xFF41). +/// @constant kSecMatchTrustedOnly Specifies a dictionary key whose value is +/// a CFBooleanRef. If provided with a value of kCFBooleanTrue, only +/// certificates which can be verified back to a trusted anchor will be +/// returned. If this value is kCFBooleanFalse, or is not provided, then +/// both trusted and untrusted certificates may be returned. +/// @constant kSecMatchValidOnDate Specifies a dictionary key whose value is +/// of type CFDateRef. If provided, returned keys, certificates or +/// identities will be limited to those which are valid for the given date. +/// Pass a value of kCFNull to indicate the current date. +/// @constant kSecMatchLimit Specifies a dictionary key whose value is a +/// CFNumberRef. If provided, this value specifies the maximum number of +/// results to return. If not provided, results are limited to the first +/// item found. Predefined values are provided for a single item +/// (kSecMatchLimitOne) and all matching items (kSecMatchLimitAll). +/// @constant kSecMatchLimitOne Specifies that results are limited to the first +/// item found; used as a value for the kSecMatchLimit dictionary key. +/// @constant kSecMatchLimitAll Specifies that an unlimited number of results +/// may be returned; used as a value for the kSecMatchLimit dictionary +/// key. +@ffi.Native() +external cf.CFStringRef kSecMatchPolicy; + +@ffi.Native() +external cf.CFStringRef kSecMatchItemList; + +@ffi.Native() +external cf.CFStringRef kSecMatchSearchList; + +@ffi.Native() +external cf.CFStringRef kSecMatchIssuers; + +@ffi.Native() +external cf.CFStringRef kSecMatchEmailAddressIfPresent; + +@ffi.Native() +external cf.CFStringRef kSecMatchSubjectContains; + +@ffi.Native() +external cf.CFStringRef kSecMatchSubjectStartsWith; + +@ffi.Native() +external cf.CFStringRef kSecMatchSubjectEndsWith; + +@ffi.Native() +external cf.CFStringRef kSecMatchSubjectWholeString; + +@ffi.Native() +external cf.CFStringRef kSecMatchCaseInsensitive; + +@ffi.Native() +external cf.CFStringRef kSecMatchDiacriticInsensitive; + +@ffi.Native() +external cf.CFStringRef kSecMatchWidthInsensitive; + +@ffi.Native() +external cf.CFStringRef kSecMatchTrustedOnly; + +@ffi.Native() +external cf.CFStringRef kSecMatchValidOnDate; + +@ffi.Native() +external cf.CFStringRef kSecMatchLimit; + +@ffi.Native() +external cf.CFStringRef kSecMatchLimitOne; + +@ffi.Native() +external cf.CFStringRef kSecMatchLimitAll; + +/// ! +/// @enum Return Type Key Constants +/// @discussion Predefined return type keys used to set values in a dictionary. +/// You use these keys to specify the type of results which should be +/// returned by the SecItemCopyMatching or SecItemAdd function. You can +/// specify zero or more of these return types. If more than one of these +/// result types is specified, the result is returned as a CFDictionaryRef +/// whose keys are the result types and values are the requested data. +/// @constant kSecReturnData Specifies a dictionary key whose value is of type +/// CFBooleanRef. A value of kCFBooleanTrue indicates that the data of +/// an item (CFDataRef) should be returned. For keys and password +/// items, data is secret (encrypted) and may require the user to enter +/// a password for access. +/// @constant kSecReturnAttributes Specifies a dictionary key whose value is +/// of type CFBooleanRef. A value of kCFBooleanTrue indicates that the +/// (non-encrypted) attributes of an item (CFDictionaryRef) should be +/// returned. +/// @constant kSecReturnRef Specifies a dictionary key whose value is a +/// CFBooleanRef. A value of kCFBooleanTrue indicates that a reference +/// should be returned. Depending on the item class requested, the +/// returned reference(s) may be of type SecKeychainItemRef, SecKeyRef, +/// SecCertificateRef, or SecIdentityRef. Note that returning references is +/// supported only for Certificate, Key or Identity items on iOS, watchOS and +/// tvOS. Similarly, returning references is supported only for Certificate, Key +/// or Identity items on macOS when either kSecUseDataProtectionKeychain +/// is set to true or kSecAttrSynchronizable is set to true. +/// @constant kSecReturnPersistentRef Specifies a dictionary key whose value +/// is of type CFBooleanRef. A value of kCFBooleanTrue indicates that a +/// persistent reference to an item (CFDataRef) should be returned. +@ffi.Native() +external cf.CFStringRef kSecReturnData; + +@ffi.Native() +external cf.CFStringRef kSecReturnAttributes; + +@ffi.Native() +external cf.CFStringRef kSecReturnRef; + +@ffi.Native() +external cf.CFStringRef kSecReturnPersistentRef; + +/// ! +/// @enum Value Type Key Constants +/// @discussion Predefined value type keys used to pass values in a dictionary. +/// You can specify zero or more of these types depending on the function +/// you are calling. For SecItemCopyMatching or SecItemAdd these are +/// used as keys in the results dictionary. +/// @constant kSecValueData Specifies a dictionary key whose value is of type +/// CFDataRef. For keys and password items, data is secret (encrypted) +/// and may require the user to enter a password for access. +/// @constant kSecValueRef Specifies a dictionary key whose value, depending +/// on the item class requested, is of type SecKeychainItemRef, SecKeyRef, +/// SecCertificateRef, or SecIdentityRef. +/// @constant kSecValuePersistentRef Specifies a dictionary key whose value +/// is of type CFDataRef. The bytes in this CFDataRef can be stored by +/// the caller and used on a subsequent invocation of the application (or +/// even a different application) to retrieve the item referenced by it. +@ffi.Native() +external cf.CFStringRef kSecValueData; + +@ffi.Native() +external cf.CFStringRef kSecValueRef; + +@ffi.Native() +external cf.CFStringRef kSecValuePersistentRef; + +/// ! +/// @enum Other Constants +/// @discussion Predefined constants used to set values in a dictionary. +/// @constant kSecUseItemList Specifies a dictionary key whose value is a +/// CFArray of items. If provided, this array is treated as the set of +/// all possible items to search, or add if the API being called is +/// SecItemAdd. The items in this array may be of type SecKeyRef, +/// SecCertificateRef, SecIdentityRef, or CFDataRef (for a persistent +/// item reference.) The items in the array must all be of the same +/// type. When this attribute is provided, no keychains are searched. +/// @constant kSecUseKeychain OS X only. Specifies a dictionary key whose value is a +/// keychain reference. You use this key to specify a value of type +/// SecKeychainRef to which SecItemAdd will add the provided item(s). +/// @constant kSecUseOperationPrompt Specifies a dictionary key whose value +/// is a CFStringRef that represents a user-visible string describing +/// the operation for which the application is attempting to authenticate. +/// The application is responsible for the text localization. +/// @constant kSecUseNoAuthenticationUI OS X only. Specifies a dictionary key whose value +/// is a CFBooleanRef. If provided with a value of kCFBooleanTrue, the error +/// errSecInteractionNotAllowed will be returned if the item is attempting +/// to authenticate with UI. +/// @constant kSecUseAuthenticationUI Specifies a dictionary key whose value +/// is one of kSecUseAuthenticationUIAllow, kSecUseAuthenticationUIFail, kSecUseAuthenticationUISkip. +/// @constant kSecUseAuthenticationContext Specifies a dictionary key whose value +/// is LAContext to be used for keychain item authentication. +/// If the item requires authentication and this key is omitted, a new context +/// will be created just for the purpose of the single call. +/// If the specified context has been previously authenticated, the operation +/// will succeed without asking user for authentication. +/// If the specified context has not been previously authenticated, the new +/// authentication will be started on this context, allowing caller to +/// eventually reuse the successfully authenticated context in subsequent +/// keychain operations. +/// @constant kSecUseDataProtectionKeychain Specifies a dictionary key whose value +/// is a CFBooleanRef. Set to kCFBooleanTrue to use kSecAttrAccessGroup and/or +/// kSecAttrAccessible on macOS without requiring the item to be marked synchronizable. +/// Note that when kSecUseDataProtectionKeychain is set to true, returning references is +/// supported only for Certificate, Key or Identity items. +/// @constant kSecUseUserIndependentKeychain Specifies a dctionary key whose value is a CFBooleanRef +/// indicating whether the item is shared with other personas on the system. +@ffi.Native() +external cf.CFStringRef kSecUseItemList; + +@ffi.Native() +external cf.CFStringRef kSecUseKeychain; + +@ffi.Native() +external cf.CFStringRef kSecUseOperationPrompt; + +@ffi.Native() +external cf.CFStringRef kSecUseNoAuthenticationUI; + +@ffi.Native() +external cf.CFStringRef kSecUseAuthenticationUI; + +@ffi.Native() +external cf.CFStringRef kSecUseAuthenticationContext; + +@ffi.Native() +external cf.CFStringRef kSecUseDataProtectionKeychain; + +@ffi.Native() +external cf.CFStringRef kSecUseUserIndependentKeychain; + +/// ! +/// @enum kSecUseAuthenticationUI Value Constants +/// @discussion Predefined item attribute constants used to get or set values +/// in a dictionary. The kSecUseAuthenticationUI constant is the key and its +/// value is one of the constants defined here. +/// If the key kSecUseAuthenticationUI not provided then kSecUseAuthenticationUIAllow +/// is used as default. +/// @constant kSecUseAuthenticationUIAllow Specifies that authenticate UI can appear. +/// @constant kSecUseAuthenticationUIFail Specifies that the error +/// errSecInteractionNotAllowed will be returned if an item needs +/// to authenticate with UI +/// @constant kSecUseAuthenticationUISkip Specifies that all items which need +/// to authenticate with UI will be silently skipped. This value can be used +/// only with SecItemCopyMatching. +@ffi.Native() +external cf.CFStringRef kSecUseAuthenticationUIAllow; + +@ffi.Native() +external cf.CFStringRef kSecUseAuthenticationUIFail; + +@ffi.Native() +external cf.CFStringRef kSecUseAuthenticationUISkip; + +/// ! +/// @enum kSecAttrTokenID Value Constants +/// @discussion Predefined item attribute constant used to get or set values +/// in a dictionary. The kSecAttrTokenID constant is the key and its value +/// can be kSecAttrTokenIDSecureEnclave. +/// @constant kSecAttrTokenIDSecureEnclave Specifies well-known identifier of the +/// token implemented using device's Secure Enclave. The only keychain items +/// supported by the Secure Enclave token are 256-bit elliptic curve keys +/// (kSecAttrKeyTypeECSecPrimeRandom). Keys must be generated on the secure enclave using +/// SecKeyGenerateKeyPair call with kSecAttrTokenID set to +/// kSecAttrTokenIDSecureEnclave in the parameters dictionary, it is not +/// possible to import pregenerated keys to kSecAttrTokenIDSecureEnclave token. +@ffi.Native() +external cf.CFStringRef kSecAttrTokenIDSecureEnclave; + +/// ! +/// @enum kSecAttrAccessGroup Value Constants +/// @constant kSecAttrAccessGroupToken Represents well-known access group +/// which contains items provided by external token (typically smart card). +/// This may be used as a value for kSecAttrAccessGroup attribute. Every +/// application has access to this access group so it is not needed to +/// explicitly list it in keychain-access-groups entitlement, but application +/// must explicitly state this access group in keychain queries in order to +/// be able to access items from external tokens. +@ffi.Native() +external cf.CFStringRef kSecAttrAccessGroupToken; + +/// ! +/// @function SecItemCopyMatching +/// @abstract Returns one or more items which match a search query. +/// @param query A dictionary containing an item class specification and +/// optional attributes for controlling the search. See the "Keychain +/// Search Attributes" section for a description of currently defined +/// search attributes. +/// @param result On return, a CFTypeRef reference to the found item(s). The +/// exact type of the result is based on the search attributes supplied +/// in the query, as discussed below. +/// @result A result code. See "Security Error Codes" (SecBase.h). +/// @discussion Attributes defining a search are specified by adding key/value +/// pairs to the query dictionary. +/// +/// A typical query consists of: +/// +/// a kSecClass key, whose value is a constant from the Class +/// Constants section that specifies the class of item(s) to be searched +/// one or more keys from the "Attribute Key Constants" section, whose value +/// is the attribute data to be matched +/// one or more keys from the "Search Constants" section, whose value is +/// used to further refine the search +/// a key from the "Return Type Key Constants" section, specifying the type of +/// results desired +/// +/// Result types are specified as follows: +/// +/// To obtain the data of a matching item (CFDataRef), specify +/// kSecReturnData with a value of kCFBooleanTrue. +/// To obtain the attributes of a matching item (CFDictionaryRef), specify +/// kSecReturnAttributes with a value of kCFBooleanTrue. +/// To obtain a reference to a matching item (SecKeychainItemRef, +/// SecKeyRef, SecCertificateRef, or SecIdentityRef), specify kSecReturnRef +/// with a value of kCFBooleanTrue. Note that returning references is +/// supported only for Certificate, Key or Identity items on iOS, watchOS and +/// tvOS. Similarly, returning references is supported only for Certificate, Key +/// or Identity items on macOS when either kSecUseDataProtectionKeychain +/// is set to true or kSecAttrSynchronizable is set to true. +/// To obtain a persistent reference to a matching item (CFDataRef), +/// specify kSecReturnPersistentRef with a value of kCFBooleanTrue. Note +/// that unlike normal references, a persistent reference may be stored +/// on disk or passed between processes. +/// If more than one of these result types is specified, the result is +/// returned as a CFDictionaryRef containing all the requested data. +/// If a result type is not specified, no results are returned. +/// +/// By default, this function returns only the first match found. To obtain +/// more than one matching item at a time, specify kSecMatchLimit with a value +/// greater than 1. The result will be a CFArrayRef containing up to that +/// number of matching items; the items' types are described above. +/// +/// To filter a provided list of items down to those matching the query, +/// specify a kSecMatchItemList whose value is a CFArray of SecKeychainItemRef, +/// SecKeyRef, SecCertificateRef, or SecIdentityRef items. The objects in the +/// provided array must be of the same type. +/// +/// On iOS, to convert from a persistent item reference to a normal item reference, +/// specify a kSecValuePersistentRef whose value a CFDataRef (the persistent +/// reference), and a kSecReturnRef whose value is kCFBooleanTrue. +/// +/// On OSX, to convert from persistent item references to normal item references, +/// specify a kSecMatchItemList whose value is a CFArray containing one or +/// more CFDataRef elements (the persistent reference), and a kSecReturnRef +/// whose value is kCFBooleanTrue. The objects in the provided array must be +/// of the same type. +@ffi.Native)>() +external int SecItemCopyMatching( + cf.CFDictionaryRef query, + ffi.Pointer result, +); + +/// ! +/// @function SecItemAdd +/// @abstract Add one or more items to a keychain. +/// @param attributes A dictionary containing an item class specification and +/// optional entries specifying the item's attribute values. See the +/// "Attribute Key Constants" section for a description of currently defined +/// attributes. +/// @param result On return, a CFTypeRef reference to the newly added item(s). +/// The exact type of the result is based on the values supplied +/// in attributes, as discussed below. Pass NULL if this result is not +/// required. +/// @result A result code. See "Security Error Codes" (SecBase.h). +/// @discussion Attributes defining an item are specified by adding key/value +/// pairs to the attributes dictionary. To add multiple items to a keychain +/// at once use the kSecUseItemList key with an array of items as its value. +/// This is currently only supported for non password items. +/// +/// On OSX, To add an item to a particular keychain, supply kSecUseKeychain +/// with a SecKeychainRef as its value. +/// +/// On iOS, watchOS & tvOS, Certificate, Key, and Identity items may be +/// added by reference, but neither Internet Passwords nor Generic Passwords +/// may be. Similarly, on macOS with either kSecUseDataProtectionKeychain +/// set to true or kSecAttrSynchronizable set to true, Certificate, Key, and Identity +/// items may be added by reference, but neither Internet Passwords nor Generic +/// Passwords may be. +/// +/// Result types are specified as follows: +/// +/// To obtain the data of the added item (CFDataRef), specify +/// kSecReturnData with a value of kCFBooleanTrue. +/// To obtain all the attributes of the added item (CFDictionaryRef), +/// specify kSecReturnAttributes with a value of kCFBooleanTrue. +/// To obtain a reference to the added item (SecKeychainItemRef, SecKeyRef, +/// SecCertificateRef, or SecIdentityRef), specify kSecReturnRef with a +/// value of kCFBooleanTrue. See also note about kSecReturnRef and +/// macOS. +/// To obtain a persistent reference to the added item (CFDataRef), specify +/// kSecReturnPersistentRef with a value of kCFBooleanTrue. Note that +/// unlike normal references, a persistent reference may be stored on disk +/// or passed between processes. +/// If more than one of these result types is specified, the result is +/// returned as a CFDictionaryRef containing all the requested data. +/// On iOS, if a result type is not specified, no results are returned. +/// On OSX, the added item is returned. +@ffi.Native)>() +external int SecItemAdd( + cf.CFDictionaryRef attributes, + ffi.Pointer result, +); + +/// ! +/// @function SecItemUpdate +/// @abstract Modify zero or more items which match a search query. +/// @param query A dictionary containing an item class specification and +/// optional attributes for controlling the search. See the "Attribute +/// Constants" and "Search Constants" sections for a description of +/// currently defined search attributes. +/// @param attributesToUpdate A dictionary containing one or more attributes +/// whose values should be set to the ones specified. Only real keychain +/// attributes are permitted in this dictionary (no "meta" attributes are +/// allowed.) See the "Attribute Key Constants" section for a description of +/// currently defined value attributes. +/// @result A result code. See "Security Error Codes" (SecBase.h). +/// @discussion Attributes defining a search are specified by adding key/value +/// pairs to the query dictionary. +@ffi.Native() +external int SecItemUpdate( + cf.CFDictionaryRef query, + cf.CFDictionaryRef attributesToUpdate, +); + +/// ! +/// @function SecItemDelete +/// @abstract Delete zero or more items which match a search query. +/// @param query A dictionary containing an item class specification and +/// optional attributes for controlling the search. See the "Attribute +/// Constants" and "Search Constants" sections for a description of +/// currently defined search attributes. +/// @result A result code. See "Security Error Codes" (SecBase.h). +/// @discussion Attributes defining a search are specified by adding key/value +/// pairs to the query dictionary. +/// +/// By default, this function deletes all items matching the specified query. +/// You can change this behavior by specifying one of the follow keys: +/// +/// To delete an item identified by a transient reference, on iOS, specify +/// kSecValueRef with a item reference. On OS X, give a kSecMatchItemList +/// containing an item reference. +/// To delete an item identified by a persistent reference, on iOS, specify +/// kSecValuePersistentRef with a persistent reference returned by +/// using the kSecReturnPersistentRef key to SecItemCopyMatching or +/// SecItemAdd. on OSX, use kSecMatchItemList with a persistent reference +/// returned by using the kSecReturnPersistentRef key with +/// SecItemCopyMatching or SecItemAdd. +/// To delete multiple items specify kSecMatchItemList with an array +/// of references. +/// If more than one of these result keys is specified, the behavior is +/// undefined. +@ffi.Native() +external int SecItemDelete( + cf.CFDictionaryRef query, +); + +/// ! +/// @function SecKeychainItemGetTypeID +/// @abstract Returns the type identifier of SecKeychainItem instances. +/// @result The CFTypeID of SecKeychainItem instances. +@ffi.Native() +external int SecKeychainItemGetTypeID(); + +/// ! +/// @function SecKeychainItemModifyAttributesAndData +/// @abstract Updates an existing keychain item after changing its attributes or data. +/// @param itemRef A reference to the keychain item to modify. +/// @param attrList The list of attributes to modify, along with their new values. Pass NULL if you don't need to modify any attributes. +/// @param length The length of the buffer pointed to by data. +/// @param data Pointer to a buffer containing the data to store. Pass NULL if you don't need to modify the data. +/// @result A result code. See "Security Error Codes" (SecBase.h). +/// @discussion The keychain item is written to the keychain's permanent data store. If the keychain item has not previously been added to a keychain, a call to the SecKeychainItemModifyContent function does nothing and returns errSecSuccess. +@ffi.Native< + ffi.Int Function(SecKeychainItemRef, ffi.Pointer, + ffi.UnsignedInt, ffi.Pointer)>() +external int SecKeychainItemModifyAttributesAndData( + SecKeychainItemRef itemRef, + ffi.Pointer attrList, + int length, + ffi.Pointer data, +); + +/// ! +/// @function SecKeychainItemCreateFromContent +/// @abstract Creates a new keychain item from the supplied parameters. +/// @param itemClass A constant identifying the class of item to create. +/// @param attrList The list of attributes of the item to create. +/// @param length The length of the buffer pointed to by data. +/// @param data A pointer to a buffer containing the data to store. +/// @param initialAccess A reference to the access for this keychain item. +/// @param keychainRef A reference to the keychain in which to add the item. +/// @param itemRef On return, a pointer to a reference to the newly created keychain item (optional). When the item reference is no longer required, call CFRelease to deallocate memory occupied by the item. +/// @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if not enough valid parameters are supplied, or errSecAllocate (-108) if there is not enough memory in the current heap zone to create the object. +@ffi.Native< + ffi.Int Function( + SecItemClass, + ffi.Pointer, + ffi.UnsignedInt, + ffi.Pointer, + SecKeychainRef, + SecAccessRef, + ffi.Pointer)>() +external int SecKeychainItemCreateFromContent( + int itemClass, + ffi.Pointer attrList, + int length, + ffi.Pointer data, + SecKeychainRef keychainRef, + SecAccessRef initialAccess, + ffi.Pointer itemRef, +); + +/// ! +/// @function SecKeychainItemModifyContent +/// @abstract Updates an existing keychain item after changing its attributes or data. This call should only be used in conjunction with SecKeychainItemCopyContent(). +/// @param itemRef A reference to the keychain item to modify. +/// @param attrList The list of attributes to modify, along with their new values. Pass NULL if you don't need to modify any attributes. +/// @param length The length of the buffer pointed to by data. +/// @param data A pointer to a buffer containing the data to store. Pass NULL if you don't need to modify the data. +/// @result A result code. See "Security Error Codes" (SecBase.h). +@ffi.Native< + ffi.Int Function(SecKeychainItemRef, ffi.Pointer, + ffi.UnsignedInt, ffi.Pointer)>() +external int SecKeychainItemModifyContent( + SecKeychainItemRef itemRef, + ffi.Pointer attrList, + int length, + ffi.Pointer data, +); + +/// ! +/// @function SecKeychainItemCopyContent +/// @abstract Copies the data and/or attributes stored in the given keychain item. It is recommended that you use SecKeychainItemCopyAttributesAndData(). You must call SecKeychainItemFreeContent when you no longer need the attributes and data. If you want to modify the attributes returned here, use SecKeychainModifyContent(). +/// @param itemRef A reference to the keychain item to modify. +/// @param itemClass On return, the item's class. Pass NULL if you don't require this information. +/// @param attrList On input, the list of attributes to retrieve. On output, the attributes are filled in. Pass NULL if you don't need to retrieve any attributes. You must call SecKeychainItemFreeContent when you no longer need the attributes. +/// @param length On return, the length of the buffer pointed to by outData. +/// @param outData On return, a pointer to a buffer containing the data in this item. Pass NULL if you don't need to retrieve the data. You must call SecKeychainItemFreeContent when you no longer need the data. +/// @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if not enough valid parameters are supplied. +@ffi.Native< + ffi.Int Function( + SecKeychainItemRef, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer>)>() +external int SecKeychainItemCopyContent( + SecKeychainItemRef itemRef, + ffi.Pointer itemClass, + ffi.Pointer attrList, + ffi.Pointer length, + ffi.Pointer> outData, +); + +/// ! +/// @function SecKeychainItemFreeContent +/// @abstract Releases the memory used by the keychain attribute list and the keychain data retrieved in a previous call to SecKeychainItemCopyContent. +/// @param attrList A pointer to the attribute list to release. Pass NULL to ignore this parameter. +/// @param data A pointer to the data buffer to release. Pass NULL to ignore this parameter. +@ffi.Native< + ffi.Int Function( + ffi.Pointer, ffi.Pointer)>() +external int SecKeychainItemFreeContent( + ffi.Pointer attrList, + ffi.Pointer data, +); + +/// ! +/// @function SecKeychainItemCopyAttributesAndData +/// @abstract Copies the data and/or attributes stored in the given keychain item. You must call SecKeychainItemFreeAttributesAndData when you no longer need the attributes and data. If you want to modify the attributes returned here, use SecKeychainModifyAttributesAndData. +/// @param itemRef A reference to the keychain item to copy. +/// @param info A list of tags and formats of the attributes you wish to retrieve. Pass NULL if you don't need to retrieve any attributes. You can call SecKeychainAttributeInfoForItemID to obtain a list with all possible attribute tags and formats for the item's class. +/// @param itemClass On return, the item's class. Pass NULL if you don't require this information. +/// @param attrList On return, a pointer to the list of retrieved attributes. Pass NULL if you don't need to retrieve any attributes. You must call SecKeychainItemFreeAttributesAndData when you no longer need this list. +/// @param length On return, the length of the buffer pointed to by outData. +/// @param outData On return, a pointer to a buffer containing the data in this item. Pass NULL if you don't need to retrieve the data. You must call SecKeychainItemFreeAttributesAndData when you no longer need the data. +/// @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if not enough valid parameters are supplied. +@ffi.Native< + ffi.Int Function( + SecKeychainItemRef, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer>, + ffi.Pointer, + ffi.Pointer>)>() +external int SecKeychainItemCopyAttributesAndData( + SecKeychainItemRef itemRef, + ffi.Pointer info, + ffi.Pointer itemClass, + ffi.Pointer> attrList, + ffi.Pointer length, + ffi.Pointer> outData, +); + +/// ! +/// @function SecKeychainItemFreeAttributesAndData +/// @abstract Releases the memory used by the keychain attribute list and the keychain data retrieved in a previous call to SecKeychainItemCopyAttributesAndData. +/// @param attrList A pointer to the attribute list to release. Pass NULL to ignore this parameter. +/// @param data A pointer to the data buffer to release. Pass NULL to ignore this parameter. +/// @result A result code. See "Security Error Codes" (SecBase.h). +@ffi.Native< + ffi.Int Function( + ffi.Pointer, ffi.Pointer)>() +external int SecKeychainItemFreeAttributesAndData( + ffi.Pointer attrList, + ffi.Pointer data, +); + +/// ! +/// @function SecKeychainItemDelete +/// @abstract Deletes a keychain item from the default keychain's permanent data store. +/// @param itemRef A keychain item reference of the item to delete. +/// @result A result code. See "Security Error Codes" (SecBase.h). +/// @discussion If itemRef has not previously been added to the keychain, SecKeychainItemDelete does nothing and returns errSecSuccess. IMPORTANT: SecKeychainItemDelete does not dispose the memory occupied by the item reference itself; use the CFRelease function when you are completely finished with an item. +@ffi.Native() +external int SecKeychainItemDelete( + SecKeychainItemRef itemRef, +); + +/// ! +/// @function SecKeychainItemCopyKeychain +/// @abstract Copies an existing keychain reference from a keychain item. +/// @param itemRef A keychain item reference. +/// @param keychainRef On return, the keychain reference for the specified item. Release this reference by calling the CFRelease function. +/// @result A result code. See "Security Error Codes" (SecBase.h). +@ffi.Native)>() +external int SecKeychainItemCopyKeychain( + SecKeychainItemRef itemRef, + ffi.Pointer keychainRef, +); + +/// ! +/// @function SecKeychainItemCreateCopy +/// @abstract Copies a keychain item. +/// @param itemRef A reference to the keychain item to copy. +/// @param destKeychainRef A reference to the keychain in which to insert the copied keychain item. +/// @param initialAccess The initial access for the copied keychain item. +/// @param itemCopy On return, a reference to the copied keychain item. +/// @result A result code. See "Security Error Codes" (SecBase.h). +@ffi.Native< + ffi.Int Function(SecKeychainItemRef, SecKeychainRef, SecAccessRef, + ffi.Pointer)>() +external int SecKeychainItemCreateCopy( + SecKeychainItemRef itemRef, + SecKeychainRef destKeychainRef, + SecAccessRef initialAccess, + ffi.Pointer itemCopy, +); + +/// ! +/// @function SecKeychainItemCreatePersistentReference +/// @abstract Returns a CFDataRef which can be used as a persistent reference to the given keychain item. The data obtained can be turned back into a SecKeychainItemRef later by calling SecKeychainItemCopyFromPersistentReference(). +/// @param itemRef A reference to a keychain item. +/// @param persistentItemRef On return, a CFDataRef containing a persistent reference. You must release this data reference by calling the CFRelease function. +/// @result A result code. See "Security Error Codes" (SecBase.h). +@ffi.Native)>() +external int SecKeychainItemCreatePersistentReference( + SecKeychainItemRef itemRef, + ffi.Pointer persistentItemRef, +); + +/// ! +/// @function SecKeychainItemCopyFromPersistentReference +/// @abstract Returns a SecKeychainItemRef, given a persistent reference previously obtained by calling SecKeychainItemCreatePersistentReference(). +/// @param persistentItemRef A CFDataRef containing a persistent reference to a keychain item. +/// @param itemRef On return, a SecKeychainItemRef for the keychain item described by the persistent reference. You must release this item reference by calling the CFRelease function. +/// @result A result code. See "Security Error Codes" (SecBase.h). +@ffi.Native)>() +external int SecKeychainItemCopyFromPersistentReference( + cf.CFDataRef persistentItemRef, + ffi.Pointer itemRef, +); + +/// ! +/// @function SecKeychainItemGetDLDBHandle +/// @abstract Returns the CSSM_DL_DB_HANDLE for a given keychain item reference. +/// @param keyItemRef A keychain item reference. +/// @param dldbHandle On return, a CSSM_DL_DB_HANDLE for the keychain database containing the given item. The handle is valid until the keychain reference is released. +/// @result A result code. See "Security Error Codes" (SecBase.h). +/// @discussion This API is deprecated for 10.7. It should no longer be needed. +@ffi.Native< + ffi.Int Function(SecKeychainItemRef, ffi.Pointer)>() +external int SecKeychainItemGetDLDBHandle( + SecKeychainItemRef keyItemRef, + ffi.Pointer dldbHandle, +); + +/// ! +/// @function SecKeychainItemGetUniqueRecordID +/// @abstract Returns a CSSM_DB_UNIQUE_RECORD for the given keychain item reference. +/// @param itemRef A keychain item reference. +/// @param uniqueRecordID On return, a pointer to a CSSM_DB_UNIQUE_RECORD structure for the given item. The unique record is valid until the item reference is released. +/// @result A result code. See "Security Error Codes" (SecBase.h). +/// @discussion This API is deprecated for 10.7. It should no longer be needed. +@ffi.Native< + ffi.Int Function( + SecKeychainItemRef, ffi.Pointer>)>() +external int SecKeychainItemGetUniqueRecordID( + SecKeychainItemRef itemRef, + ffi.Pointer> uniqueRecordID, +); + +/// ! +/// @function SecKeychainItemCopyAccess +/// @abstract Copies the access of a given keychain item. +/// @param itemRef A reference to a keychain item. +/// @param access On return, a reference to the keychain item's access. +/// @result A result code. See "Security Error Codes" (SecBase.h). +@ffi.Native)>() +external int SecKeychainItemCopyAccess( + SecKeychainItemRef itemRef, + ffi.Pointer access, +); + +/// ! +/// @function SecKeychainItemSetAccess +/// @abstract Sets the access of a given keychain item. +/// @param itemRef A reference to a keychain item. +/// @param access A reference to an access to replace the keychain item's current access. +/// @result A result code. See "Security Error Codes" (SecBase.h). +@ffi.Native() +external int SecKeychainItemSetAccess( + SecKeychainItemRef itemRef, + SecAccessRef access, +); + +final class __CFNull extends ffi.Opaque {} + +final class __CFAllocator extends ffi.Opaque {} + +final class SecKeychainItem extends ffi.Opaque {} + +final class __CFBoolean extends ffi.Opaque {} + +final class __CFNumber extends ffi.Opaque {} + +final class CFArrayCallBacks extends ffi.Struct { + @ffi.Long() + external int version; + + external ffi.Pointer< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer<__CFAllocator>, ffi.Pointer)>> retain; + + external ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer<__CFAllocator>, ffi.Pointer)>> release; + + external ffi.Pointer< + ffi.NativeFunction)>> + copyDescription; + + external ffi.Pointer< + ffi.NativeFunction< + ffi.UnsignedChar Function( + ffi.Pointer, ffi.Pointer)>> equal; +} + +final class CFDictionaryKeyCallBacks extends ffi.Struct { + @ffi.Long() + external int version; + + external ffi.Pointer< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer<__CFAllocator>, ffi.Pointer)>> retain; + + external ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer<__CFAllocator>, ffi.Pointer)>> release; + + external ffi.Pointer< + ffi.NativeFunction)>> + copyDescription; + + external ffi.Pointer< + ffi.NativeFunction< + ffi.UnsignedChar Function( + ffi.Pointer, ffi.Pointer)>> equal; + + external ffi.Pointer< + ffi.NativeFunction)>> + hash; +} + +/// ! +/// @typedef CFDictionaryValueCallBacks +/// Structure containing the callbacks for values of a CFDictionary. +/// @field version The version number of the structure type being passed +/// in as a parameter to the CFDictionary creation functions. +/// This structure is version 0. +/// @field retain The callback used to add a retain for the dictionary +/// on values as they are put into the dictionary. +/// This callback returns the value to use as the value in the +/// dictionary, which is usually the value parameter passed to +/// this callback, but may be a different value if a different +/// value should be added to the dictionary. The dictionary's +/// allocator is passed as the first argument. +/// @field release The callback used to remove a retain previously added +/// for the dictionary from values as they are removed from +/// the dictionary. The dictionary's allocator is passed as the +/// first argument. +/// @field copyDescription The callback used to create a descriptive +/// string representation of each value in the dictionary. This +/// is used by the CFCopyDescription() function. +/// @field equal The callback used to compare values in the dictionary for +/// equality in some operations. +final class CFDictionaryValueCallBacks extends ffi.Struct { + @ffi.Long() + external int version; + + external ffi.Pointer< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer<__CFAllocator>, ffi.Pointer)>> retain; + + external ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer<__CFAllocator>, ffi.Pointer)>> release; + + external ffi.Pointer< + ffi.NativeFunction)>> + copyDescription; + + external ffi.Pointer< + ffi.NativeFunction< + ffi.UnsignedChar Function( + ffi.Pointer, ffi.Pointer)>> equal; +} + +/// ! +/// @typedef SecKeychainItemRef +/// @abstract Contains information about a keychain item. +typedef SecKeychainItemRef = ffi.Pointer; + +/// ! +/// @typedef SecKeychainAttributeList +/// @abstract Represents a list of keychain attributes. +/// @field count An unsigned 32-bit integer that represents the number of keychain attributes in the array. +/// @field attr A pointer to the first keychain attribute in the array. +final class SecKeychainAttributeList extends ffi.Struct { + @ffi.UnsignedInt() + external int count; + + external ffi.Pointer attr; +} + +/// ! +/// @struct SecKeychainAttribute +/// @abstract Contains keychain attributes. +/// @field tag A 4-byte attribute tag. +/// @field length The length of the buffer pointed to by data. +/// @field data A pointer to the attribute data. +final class SecKeychainAttribute extends ffi.Struct { + @SecKeychainAttrType() + external int tag; + + @ffi.UnsignedInt() + external int length; + + external ffi.Pointer data; +} + +/// ! +/// @typedef SecKeychainAttrType +/// @abstract Represents a keychain attribute type. +typedef SecKeychainAttrType = ffi.UnsignedInt; +typedef DartSecKeychainAttrType = int; + +/// ! +/// @enum ItemClassConstants +/// @abstract Specifies a keychain item's class code. +/// @constant kSecInternetPasswordItemClass Indicates that the item is an Internet password. +/// @constant kSecGenericPasswordItemClass Indicates that the item is a generic password. +/// @constant kSecAppleSharePasswordItemClass Indicates that the item is an AppleShare password. +/// Note: AppleShare passwords are no longer used by OS X, starting in Leopard (10.5). Use of this item class is deprecated in OS X 10.9 and later; kSecInternetPasswordItemClass should be used instead when storing or looking up passwords for an Apple Filing Protocol (AFP) server. +/// @constant kSecCertificateItemClass Indicates that the item is a digital certificate. +/// @constant kSecPublicKeyItemClass Indicates that the item is a public key. +/// @constant kSecPrivateKeyItemClass Indicates that the item is a private key. +/// @constant kSecSymmetricKeyItemClass Indicates that the item is a symmetric key. +/// @discussion The SecItemClass enumeration defines constants your application can use to specify the type of the keychain item you wish to create, dispose, add, delete, update, copy, or locate. You can also use these constants with the tag constant SecItemAttr. +typedef SecItemClass = ffi.UnsignedInt; +typedef DartSecItemClass = int; + +/// ! +/// @typedef SecKeychainRef +/// @abstract Contains information about a keychain. +typedef SecKeychainRef = ffi.Pointer<__SecKeychain>; + +final class __SecKeychain extends ffi.Opaque {} + +/// ! +/// @typedef SecAccessRef +/// @abstract Contains information about an access. +typedef SecAccessRef = ffi.Pointer<__SecAccess>; + +final class __SecAccess extends ffi.Opaque {} + +/// ! +/// @typedef SecKeychainAttributeInfo +/// @abstract Represents an attribute. +/// @field count The number of tag-format pairs in the respective arrays. +/// @field tag A pointer to the first attribute tag in the array. +/// @field format A pointer to the first CSSM_DB_ATTRIBUTE_FORMAT in the array. +/// @discussion Each tag and format item form a pair. +final class SecKeychainAttributeInfo extends ffi.Struct { + @ffi.UnsignedInt() + external int count; + + external ffi.Pointer tag; + + external ffi.Pointer format; +} + +/// From DL. +final class cssm_dl_db_handle extends ffi.Struct { + @ffi.IntPtr() + external int DLHandle; + + @ffi.IntPtr() + external int DBHandle; +} + +final class cssm_db_unique_record extends ffi.Struct { + external cssm_db_index_info RecordLocator; + + external SecAsn1Item RecordIdentifier; +} + +final class cssm_db_index_info extends ffi.Struct { + @ffi.Uint32() + external int IndexType; + + @ffi.Uint32() + external int IndexedDataLocation; + + external cssm_db_attribute_info Info; +} + +final class cssm_db_attribute_info extends ffi.Struct { + @ffi.Uint32() + external int AttributeNameFormat; + + external cssm_db_attribute_label Label; + + @ffi.Uint32() + external int AttributeFormat; +} + +final class cssm_db_attribute_label extends ffi.Union { + /// e.g., "record label" + external ffi.Pointer AttributeName; + + /// e.g., CSSMOID_RECORDLABEL + external SecAsn1Oid AttributeOID; + + /// e.g., FOUR_CHAR_CODE('recl') + @ffi.Uint32() + external int AttributeID; +} + +typedef SecAsn1Oid = cssm_data; + +final class cssm_data extends ffi.Struct { + @ffi.Size() + external int Length; + + external ffi.Pointer Data; +} + +typedef SecAsn1Item = cssm_data; + +const int errSecSuccess = 0; + +const int errSecUnimplemented = -4; + +const int errSecDiskFull = -34; + +const int errSecDskFull = -34; + +const int errSecIO = -36; + +const int errSecOpWr = -49; + +const int errSecParam = -50; + +const int errSecWrPerm = -61; + +const int errSecAllocate = -108; + +const int errSecUserCanceled = -128; + +const int errSecBadReq = -909; + +const int errSecInternalComponent = -2070; + +const int errSecCoreFoundationUnknown = -4960; + +const int errSecMissingEntitlement = -34018; + +const int errSecRestrictedAPI = -34020; + +const int errSecNotAvailable = -25291; + +const int errSecReadOnly = -25292; + +const int errSecAuthFailed = -25293; + +const int errSecNoSuchKeychain = -25294; + +const int errSecInvalidKeychain = -25295; + +const int errSecDuplicateKeychain = -25296; + +const int errSecDuplicateCallback = -25297; + +const int errSecInvalidCallback = -25298; + +const int errSecDuplicateItem = -25299; + +const int errSecItemNotFound = -25300; + +const int errSecBufferTooSmall = -25301; + +const int errSecDataTooLarge = -25302; + +const int errSecNoSuchAttr = -25303; + +const int errSecInvalidItemRef = -25304; + +const int errSecInvalidSearchRef = -25305; + +const int errSecNoSuchClass = -25306; + +const int errSecNoDefaultKeychain = -25307; + +const int errSecInteractionNotAllowed = -25308; + +const int errSecReadOnlyAttr = -25309; + +const int errSecWrongSecVersion = -25310; + +const int errSecKeySizeNotAllowed = -25311; + +const int errSecNoStorageModule = -25312; + +const int errSecNoCertificateModule = -25313; + +const int errSecNoPolicyModule = -25314; + +const int errSecInteractionRequired = -25315; + +const int errSecDataNotAvailable = -25316; + +const int errSecDataNotModifiable = -25317; + +const int errSecCreateChainFailed = -25318; + +const int errSecInvalidPrefsDomain = -25319; + +const int errSecInDarkWake = -25320; + +const int errSecACLNotSimple = -25240; + +const int errSecPolicyNotFound = -25241; + +const int errSecInvalidTrustSetting = -25242; + +const int errSecNoAccessForItem = -25243; + +const int errSecInvalidOwnerEdit = -25244; + +const int errSecTrustNotAvailable = -25245; + +const int errSecUnsupportedFormat = -25256; + +const int errSecUnknownFormat = -25257; + +const int errSecKeyIsSensitive = -25258; + +const int errSecMultiplePrivKeys = -25259; + +const int errSecPassphraseRequired = -25260; + +const int errSecInvalidPasswordRef = -25261; + +const int errSecInvalidTrustSettings = -25262; + +const int errSecNoTrustSettings = -25263; + +const int errSecPkcs12VerifyFailure = -25264; + +const int errSecNotSigner = -26267; + +const int errSecDecode = -26275; + +const int errSecServiceNotAvailable = -67585; + +const int errSecInsufficientClientID = -67586; + +const int errSecDeviceReset = -67587; + +const int errSecDeviceFailed = -67588; + +const int errSecAppleAddAppACLSubject = -67589; + +const int errSecApplePublicKeyIncomplete = -67590; + +const int errSecAppleSignatureMismatch = -67591; + +const int errSecAppleInvalidKeyStartDate = -67592; + +const int errSecAppleInvalidKeyEndDate = -67593; + +const int errSecConversionError = -67594; + +const int errSecAppleSSLv2Rollback = -67595; + +const int errSecQuotaExceeded = -67596; + +const int errSecFileTooBig = -67597; + +const int errSecInvalidDatabaseBlob = -67598; + +const int errSecInvalidKeyBlob = -67599; + +const int errSecIncompatibleDatabaseBlob = -67600; + +const int errSecIncompatibleKeyBlob = -67601; + +const int errSecHostNameMismatch = -67602; + +const int errSecUnknownCriticalExtensionFlag = -67603; + +const int errSecNoBasicConstraints = -67604; + +const int errSecNoBasicConstraintsCA = -67605; + +const int errSecInvalidAuthorityKeyID = -67606; + +const int errSecInvalidSubjectKeyID = -67607; + +const int errSecInvalidKeyUsageForPolicy = -67608; + +const int errSecInvalidExtendedKeyUsage = -67609; + +const int errSecInvalidIDLinkage = -67610; + +const int errSecPathLengthConstraintExceeded = -67611; + +const int errSecInvalidRoot = -67612; + +const int errSecCRLExpired = -67613; + +const int errSecCRLNotValidYet = -67614; + +const int errSecCRLNotFound = -67615; + +const int errSecCRLServerDown = -67616; + +const int errSecCRLBadURI = -67617; + +const int errSecUnknownCertExtension = -67618; + +const int errSecUnknownCRLExtension = -67619; + +const int errSecCRLNotTrusted = -67620; + +const int errSecCRLPolicyFailed = -67621; + +const int errSecIDPFailure = -67622; + +const int errSecSMIMEEmailAddressesNotFound = -67623; + +const int errSecSMIMEBadExtendedKeyUsage = -67624; + +const int errSecSMIMEBadKeyUsage = -67625; + +const int errSecSMIMEKeyUsageNotCritical = -67626; + +const int errSecSMIMENoEmailAddress = -67627; + +const int errSecSMIMESubjAltNameNotCritical = -67628; + +const int errSecSSLBadExtendedKeyUsage = -67629; + +const int errSecOCSPBadResponse = -67630; + +const int errSecOCSPBadRequest = -67631; + +const int errSecOCSPUnavailable = -67632; + +const int errSecOCSPStatusUnrecognized = -67633; + +const int errSecEndOfData = -67634; + +const int errSecIncompleteCertRevocationCheck = -67635; + +const int errSecNetworkFailure = -67636; + +const int errSecOCSPNotTrustedToAnchor = -67637; + +const int errSecRecordModified = -67638; + +const int errSecOCSPSignatureError = -67639; + +const int errSecOCSPNoSigner = -67640; + +const int errSecOCSPResponderMalformedReq = -67641; + +const int errSecOCSPResponderInternalError = -67642; + +const int errSecOCSPResponderTryLater = -67643; + +const int errSecOCSPResponderSignatureRequired = -67644; + +const int errSecOCSPResponderUnauthorized = -67645; + +const int errSecOCSPResponseNonceMismatch = -67646; + +const int errSecCodeSigningBadCertChainLength = -67647; + +const int errSecCodeSigningNoBasicConstraints = -67648; + +const int errSecCodeSigningBadPathLengthConstraint = -67649; + +const int errSecCodeSigningNoExtendedKeyUsage = -67650; + +const int errSecCodeSigningDevelopment = -67651; + +const int errSecResourceSignBadCertChainLength = -67652; + +const int errSecResourceSignBadExtKeyUsage = -67653; + +const int errSecTrustSettingDeny = -67654; + +const int errSecInvalidSubjectName = -67655; + +const int errSecUnknownQualifiedCertStatement = -67656; + +const int errSecMobileMeRequestQueued = -67657; + +const int errSecMobileMeRequestRedirected = -67658; + +const int errSecMobileMeServerError = -67659; + +const int errSecMobileMeServerNotAvailable = -67660; + +const int errSecMobileMeServerAlreadyExists = -67661; + +const int errSecMobileMeServerServiceErr = -67662; + +const int errSecMobileMeRequestAlreadyPending = -67663; + +const int errSecMobileMeNoRequestPending = -67664; + +const int errSecMobileMeCSRVerifyFailure = -67665; + +const int errSecMobileMeFailedConsistencyCheck = -67666; + +const int errSecNotInitialized = -67667; + +const int errSecInvalidHandleUsage = -67668; + +const int errSecPVCReferentNotFound = -67669; + +const int errSecFunctionIntegrityFail = -67670; + +const int errSecInternalError = -67671; + +const int errSecMemoryError = -67672; + +const int errSecInvalidData = -67673; + +const int errSecMDSError = -67674; + +const int errSecInvalidPointer = -67675; + +const int errSecSelfCheckFailed = -67676; + +const int errSecFunctionFailed = -67677; + +const int errSecModuleManifestVerifyFailed = -67678; + +const int errSecInvalidGUID = -67679; + +const int errSecInvalidHandle = -67680; + +const int errSecInvalidDBList = -67681; + +const int errSecInvalidPassthroughID = -67682; + +const int errSecInvalidNetworkAddress = -67683; + +const int errSecCRLAlreadySigned = -67684; + +const int errSecInvalidNumberOfFields = -67685; + +const int errSecVerificationFailure = -67686; + +const int errSecUnknownTag = -67687; + +const int errSecInvalidSignature = -67688; + +const int errSecInvalidName = -67689; + +const int errSecInvalidCertificateRef = -67690; + +const int errSecInvalidCertificateGroup = -67691; + +const int errSecTagNotFound = -67692; + +const int errSecInvalidQuery = -67693; + +const int errSecInvalidValue = -67694; + +const int errSecCallbackFailed = -67695; + +const int errSecACLDeleteFailed = -67696; + +const int errSecACLReplaceFailed = -67697; + +const int errSecACLAddFailed = -67698; + +const int errSecACLChangeFailed = -67699; + +const int errSecInvalidAccessCredentials = -67700; + +const int errSecInvalidRecord = -67701; + +const int errSecInvalidACL = -67702; + +const int errSecInvalidSampleValue = -67703; + +const int errSecIncompatibleVersion = -67704; + +const int errSecPrivilegeNotGranted = -67705; + +const int errSecInvalidScope = -67706; + +const int errSecPVCAlreadyConfigured = -67707; + +const int errSecInvalidPVC = -67708; + +const int errSecEMMLoadFailed = -67709; + +const int errSecEMMUnloadFailed = -67710; + +const int errSecAddinLoadFailed = -67711; + +const int errSecInvalidKeyRef = -67712; + +const int errSecInvalidKeyHierarchy = -67713; + +const int errSecAddinUnloadFailed = -67714; + +const int errSecLibraryReferenceNotFound = -67715; + +const int errSecInvalidAddinFunctionTable = -67716; + +const int errSecInvalidServiceMask = -67717; + +const int errSecModuleNotLoaded = -67718; + +const int errSecInvalidSubServiceID = -67719; + +const int errSecAttributeNotInContext = -67720; + +const int errSecModuleManagerInitializeFailed = -67721; + +const int errSecModuleManagerNotFound = -67722; + +const int errSecEventNotificationCallbackNotFound = -67723; + +const int errSecInputLengthError = -67724; + +const int errSecOutputLengthError = -67725; + +const int errSecPrivilegeNotSupported = -67726; + +const int errSecDeviceError = -67727; + +const int errSecAttachHandleBusy = -67728; + +const int errSecNotLoggedIn = -67729; + +const int errSecAlgorithmMismatch = -67730; + +const int errSecKeyUsageIncorrect = -67731; + +const int errSecKeyBlobTypeIncorrect = -67732; + +const int errSecKeyHeaderInconsistent = -67733; + +const int errSecUnsupportedKeyFormat = -67734; + +const int errSecUnsupportedKeySize = -67735; + +const int errSecInvalidKeyUsageMask = -67736; + +const int errSecUnsupportedKeyUsageMask = -67737; + +const int errSecInvalidKeyAttributeMask = -67738; + +const int errSecUnsupportedKeyAttributeMask = -67739; + +const int errSecInvalidKeyLabel = -67740; + +const int errSecUnsupportedKeyLabel = -67741; + +const int errSecInvalidKeyFormat = -67742; + +const int errSecUnsupportedVectorOfBuffers = -67743; + +const int errSecInvalidInputVector = -67744; + +const int errSecInvalidOutputVector = -67745; + +const int errSecInvalidContext = -67746; + +const int errSecInvalidAlgorithm = -67747; + +const int errSecInvalidAttributeKey = -67748; + +const int errSecMissingAttributeKey = -67749; + +const int errSecInvalidAttributeInitVector = -67750; + +const int errSecMissingAttributeInitVector = -67751; + +const int errSecInvalidAttributeSalt = -67752; + +const int errSecMissingAttributeSalt = -67753; + +const int errSecInvalidAttributePadding = -67754; + +const int errSecMissingAttributePadding = -67755; + +const int errSecInvalidAttributeRandom = -67756; + +const int errSecMissingAttributeRandom = -67757; + +const int errSecInvalidAttributeSeed = -67758; + +const int errSecMissingAttributeSeed = -67759; + +const int errSecInvalidAttributePassphrase = -67760; + +const int errSecMissingAttributePassphrase = -67761; + +const int errSecInvalidAttributeKeyLength = -67762; + +const int errSecMissingAttributeKeyLength = -67763; + +const int errSecInvalidAttributeBlockSize = -67764; + +const int errSecMissingAttributeBlockSize = -67765; + +const int errSecInvalidAttributeOutputSize = -67766; + +const int errSecMissingAttributeOutputSize = -67767; + +const int errSecInvalidAttributeRounds = -67768; + +const int errSecMissingAttributeRounds = -67769; + +const int errSecInvalidAlgorithmParms = -67770; + +const int errSecMissingAlgorithmParms = -67771; + +const int errSecInvalidAttributeLabel = -67772; + +const int errSecMissingAttributeLabel = -67773; + +const int errSecInvalidAttributeKeyType = -67774; + +const int errSecMissingAttributeKeyType = -67775; + +const int errSecInvalidAttributeMode = -67776; + +const int errSecMissingAttributeMode = -67777; + +const int errSecInvalidAttributeEffectiveBits = -67778; + +const int errSecMissingAttributeEffectiveBits = -67779; + +const int errSecInvalidAttributeStartDate = -67780; + +const int errSecMissingAttributeStartDate = -67781; + +const int errSecInvalidAttributeEndDate = -67782; + +const int errSecMissingAttributeEndDate = -67783; + +const int errSecInvalidAttributeVersion = -67784; + +const int errSecMissingAttributeVersion = -67785; + +const int errSecInvalidAttributePrime = -67786; + +const int errSecMissingAttributePrime = -67787; + +const int errSecInvalidAttributeBase = -67788; + +const int errSecMissingAttributeBase = -67789; + +const int errSecInvalidAttributeSubprime = -67790; + +const int errSecMissingAttributeSubprime = -67791; + +const int errSecInvalidAttributeIterationCount = -67792; + +const int errSecMissingAttributeIterationCount = -67793; + +const int errSecInvalidAttributeDLDBHandle = -67794; + +const int errSecMissingAttributeDLDBHandle = -67795; + +const int errSecInvalidAttributeAccessCredentials = -67796; + +const int errSecMissingAttributeAccessCredentials = -67797; + +const int errSecInvalidAttributePublicKeyFormat = -67798; + +const int errSecMissingAttributePublicKeyFormat = -67799; + +const int errSecInvalidAttributePrivateKeyFormat = -67800; + +const int errSecMissingAttributePrivateKeyFormat = -67801; + +const int errSecInvalidAttributeSymmetricKeyFormat = -67802; + +const int errSecMissingAttributeSymmetricKeyFormat = -67803; + +const int errSecInvalidAttributeWrappedKeyFormat = -67804; + +const int errSecMissingAttributeWrappedKeyFormat = -67805; + +const int errSecStagedOperationInProgress = -67806; + +const int errSecStagedOperationNotStarted = -67807; + +const int errSecVerifyFailed = -67808; + +const int errSecQuerySizeUnknown = -67809; + +const int errSecBlockSizeMismatch = -67810; + +const int errSecPublicKeyInconsistent = -67811; + +const int errSecDeviceVerifyFailed = -67812; + +const int errSecInvalidLoginName = -67813; + +const int errSecAlreadyLoggedIn = -67814; + +const int errSecInvalidDigestAlgorithm = -67815; + +const int errSecInvalidCRLGroup = -67816; + +const int errSecCertificateCannotOperate = -67817; + +const int errSecCertificateExpired = -67818; + +const int errSecCertificateNotValidYet = -67819; + +const int errSecCertificateRevoked = -67820; + +const int errSecCertificateSuspended = -67821; + +const int errSecInsufficientCredentials = -67822; + +const int errSecInvalidAction = -67823; + +const int errSecInvalidAuthority = -67824; + +const int errSecVerifyActionFailed = -67825; + +const int errSecInvalidCertAuthority = -67826; + +const int errSecInvalidCRLAuthority = -67827; + +const int errSecInvaldCRLAuthority = -67827; + +const int errSecInvalidCRLEncoding = -67828; + +const int errSecInvalidCRLType = -67829; + +const int errSecInvalidCRL = -67830; + +const int errSecInvalidFormType = -67831; + +const int errSecInvalidID = -67832; + +const int errSecInvalidIdentifier = -67833; + +const int errSecInvalidIndex = -67834; + +const int errSecInvalidPolicyIdentifiers = -67835; + +const int errSecInvalidTimeString = -67836; + +const int errSecInvalidReason = -67837; + +const int errSecInvalidRequestInputs = -67838; + +const int errSecInvalidResponseVector = -67839; + +const int errSecInvalidStopOnPolicy = -67840; + +const int errSecInvalidTuple = -67841; + +const int errSecMultipleValuesUnsupported = -67842; + +const int errSecNotTrusted = -67843; + +const int errSecNoDefaultAuthority = -67844; + +const int errSecRejectedForm = -67845; + +const int errSecRequestLost = -67846; + +const int errSecRequestRejected = -67847; + +const int errSecUnsupportedAddressType = -67848; + +const int errSecUnsupportedService = -67849; + +const int errSecInvalidTupleGroup = -67850; + +const int errSecInvalidBaseACLs = -67851; + +const int errSecInvalidTupleCredentials = -67852; + +const int errSecInvalidTupleCredendtials = -67852; + +const int errSecInvalidEncoding = -67853; + +const int errSecInvalidValidityPeriod = -67854; + +const int errSecInvalidRequestor = -67855; + +const int errSecRequestDescriptor = -67856; + +const int errSecInvalidBundleInfo = -67857; + +const int errSecInvalidCRLIndex = -67858; + +const int errSecNoFieldValues = -67859; + +const int errSecUnsupportedFieldFormat = -67860; + +const int errSecUnsupportedIndexInfo = -67861; + +const int errSecUnsupportedLocality = -67862; + +const int errSecUnsupportedNumAttributes = -67863; + +const int errSecUnsupportedNumIndexes = -67864; + +const int errSecUnsupportedNumRecordTypes = -67865; + +const int errSecFieldSpecifiedMultiple = -67866; + +const int errSecIncompatibleFieldFormat = -67867; + +const int errSecInvalidParsingModule = -67868; + +const int errSecDatabaseLocked = -67869; + +const int errSecDatastoreIsOpen = -67870; + +const int errSecMissingValue = -67871; + +const int errSecUnsupportedQueryLimits = -67872; + +const int errSecUnsupportedNumSelectionPreds = -67873; + +const int errSecUnsupportedOperator = -67874; + +const int errSecInvalidDBLocation = -67875; + +const int errSecInvalidAccessRequest = -67876; + +const int errSecInvalidIndexInfo = -67877; + +const int errSecInvalidNewOwner = -67878; + +const int errSecInvalidModifyMode = -67879; + +const int errSecMissingRequiredExtension = -67880; + +const int errSecExtendedKeyUsageNotCritical = -67881; + +const int errSecTimestampMissing = -67882; + +const int errSecTimestampInvalid = -67883; + +const int errSecTimestampNotTrusted = -67884; + +const int errSecTimestampServiceNotAvailable = -67885; + +const int errSecTimestampBadAlg = -67886; + +const int errSecTimestampBadRequest = -67887; + +const int errSecTimestampBadDataFormat = -67888; + +const int errSecTimestampTimeNotAvailable = -67889; + +const int errSecTimestampUnacceptedPolicy = -67890; + +const int errSecTimestampUnacceptedExtension = -67891; + +const int errSecTimestampAddInfoNotAvailable = -67892; + +const int errSecTimestampSystemFailure = -67893; + +const int errSecSigningTimeMissing = -67894; + +const int errSecTimestampRejection = -67895; + +const int errSecTimestampWaiting = -67896; + +const int errSecTimestampRevocationWarning = -67897; + +const int errSecTimestampRevocationNotification = -67898; + +const int errSecCertificatePolicyNotAllowed = -67899; + +const int errSecCertificateNameNotAllowed = -67900; + +const int errSecCertificateValidityPeriodTooLong = -67901; + +const int errSecCertificateIsCA = -67902; + +const int errSecCertificateDuplicateExtension = -67903; diff --git a/packages/celest_core/lib/src/secure_storage/secure_storage.android.dart b/packages/celest_core/lib/src/secure_storage/secure_storage.android.dart new file mode 100644 index 00000000..a9b0c3df --- /dev/null +++ b/packages/celest_core/lib/src/secure_storage/secure_storage.android.dart @@ -0,0 +1,39 @@ +import 'package:celest_core/src/native/android/jni_bindings.ffi.dart'; +import 'package:celest_core/src/secure_storage/secure_storage_platform.vm.dart'; +import 'package:jni/jni.dart'; + +final class SecureStoragePlatformAndroid extends SecureStoragePlatform { + SecureStoragePlatformAndroid({ + required this.scope, + }) : super.base() { + Jni.initDLApi(); + } + + final String scope; + late final Activity _mainActivity = + Activity.fromRef(Jni.getCurrentActivity()); + late final CelestSecureStorage _secureStorage = + CelestSecureStorage(_mainActivity, scope.toJString()); + + @override + void clear() => _secureStorage.clear(); + + @override + String? delete(String key) { + final value = _secureStorage.delete(key.toJString()); + if (value.isNull) { + return null; + } + return value.toDartString(); + } + + @override + String? read(String key) => + _secureStorage.read(key.toJString()).toDartString(); + + @override + String write(String key, String value) { + _secureStorage.write(key.toJString(), value.toJString()); + return value; + } +} diff --git a/packages/celest_core/lib/src/secure_storage/secure_storage.dart b/packages/celest_core/lib/src/secure_storage/secure_storage.dart new file mode 100644 index 00000000..55400f14 --- /dev/null +++ b/packages/celest_core/lib/src/secure_storage/secure_storage.dart @@ -0,0 +1,12 @@ +import 'package:celest_core/src/secure_storage/secure_storage_platform.vm.dart' + if (dart.library.js_interop) 'package:celest_core/src/secure_storage/secure_storage_platform.web.dart'; + +abstract interface class SecureStorage { + factory SecureStorage({String? scope}) = SecureStoragePlatform; + + void init() {} + String? read(String key); + String write(String key, String value); + String? delete(String key); + void clear(); +} diff --git a/packages/celest_core/lib/src/secure_storage/secure_storage.darwin.dart b/packages/celest_core/lib/src/secure_storage/secure_storage.darwin.dart new file mode 100644 index 00000000..e73ee466 --- /dev/null +++ b/packages/celest_core/lib/src/secure_storage/secure_storage.darwin.dart @@ -0,0 +1,189 @@ +import 'dart:ffi'; +import 'dart:io'; + +import 'package:celest_core/src/native/darwin/core_foundation.ffi.dart'; +import 'package:celest_core/src/native/darwin/darwin_ffi_helpers.dart'; +import 'package:celest_core/src/native/darwin/security.ffi.dart'; +import 'package:celest_core/src/secure_storage/secure_storage_exception.dart'; +import 'package:celest_core/src/secure_storage/secure_storage_platform.vm.dart'; +import 'package:celest_core/src/util/globals.dart'; +import 'package:ffi/ffi.dart'; + +final class SecureStoragePlatformDarwin extends SecureStoragePlatform { + SecureStoragePlatformDarwin({ + required this.scope, + }) : super.base(); + + final String scope; + static final _useDataProtection = Platform.isMacOS && kReleaseMode; + + Map _baseQuery(Arena arena) { + final service = scope.toCFString(arena); + return { + kSecClass: kSecClassGenericPassword, + kSecAttrService: service, + if (_useDataProtection) kSecUseDataProtectionKeychain: kCFBooleanTrue, + }; + } + + @override + void clear() => using((arena) => _clear(arena: arena)); + + @override + String? delete(String key) => using((arena) { + final current = _read(key, arena: arena); + _delete(key, arena: arena); + return current; + }); + + @override + String? read(String key) => using((arena) => _read(key, arena: arena)); + + @override + String write(String key, String value) => using((arena) { + _write(key, value, arena: arena); + return value; + }); + + String? _read(String key, {required Arena arena}) { + final attributes = _baseQuery(arena); + final query = { + ...attributes, + kSecAttrAccount: key.toCFString(arena), + kSecReturnData: kCFBooleanTrue, + kSecMatchLimit: kSecMatchLimitOne, + kSecReturnData: kCFBooleanTrue, + }; + try { + final result = arena(); + _check( + () => SecItemCopyMatching(query.toCFDictionary(arena), result), + key: key, + ); + final data = result.value.cast(); + if (data == nullptr) { + return null; + } + arena.onReleaseAll(() => CFRelease(data.cast())); + return data.toDartString(); + } on SecureStorageItemNotFoundException { + return null; + } on Exception catch (e, st) { + // May happen if the data is not UTF-8 encoded or corrupted. + Error.throwWithStackTrace( + SecureStorageUnknownException(e.toString()), + st, + ); + } + } + + void _write(String key, String value, {required Arena arena}) { + final query = { + ..._baseQuery(arena), + kSecAttrAccount: key.toCFString(arena), + }; + final gets = SecItemCopyMatching(query.toCFDictionary(arena), nullptr); + if (gets != errSecSuccess && gets != errSecItemNotFound) { + throw SecurityFrameworkException.fromStatus(gets, key: key); + } + final itemExists = gets == errSecSuccess; + if (itemExists) { + // Update the item. + final attributes = { + kSecValueData: value.toCFData(arena), + }; + return _check( + () => SecItemUpdate( + query.toCFDictionary(arena), + attributes.toCFDictionary(arena), + ), + key: key, + ); + } + // Else, add the item. + final attributes = { + ...query, + kSecValueData: value.toCFData(arena), + }; + _check( + () => SecItemAdd(attributes.toCFDictionary(arena), nullptr), + key: key, + ); + } + + void _delete(String key, {required Arena arena}) { + final query = { + ..._baseQuery(arena), + kSecAttrAccount: key.toCFString(arena), + }; + try { + _check( + () => SecItemDelete(query.toCFDictionary(arena)), + key: key, + ); + } on SecureStorageItemNotFoundException { + // OK. Keychain will throw this error if the item is not found. + } + } + + void _clear({required Arena arena}) { + final query = { + ..._baseQuery(arena), + // Required when `useDataProtection` is disabled, however can only be + // passed on macOS. Passing it on iOS will fail. + if (Platform.isMacOS && !_useDataProtection) + kSecMatchLimit: kSecMatchLimitAll, + }; + try { + _check(() => SecItemDelete(query.toCFDictionary(arena))); + } on SecureStorageItemNotFoundException { + // OK. Keychain will throw this error if there are no items. + } + } + + void _check( + int Function() action, { + String? key, + }) { + final status = action(); + if (status != errSecSuccess) { + throw SecurityFrameworkException.fromStatus(status, key: key); + } + } +} + +extension type SecurityFrameworkException(SecureStorageException exception) + implements SecureStorageException { + factory SecurityFrameworkException.fromStatus(int status, {String? key}) { + if (kReleaseMode) { + key = null; + } + final cfMessage = SecCopyErrorMessageString(status, nullptr); + try { + final message = cfMessage.toDartString(); + final exception = switch (status) { + errSecItemNotFound => + SecureStorageItemNotFoundException(message: message), + errSecDuplicateItem => + SecureStorageDuplicateItemException(message: message), + errSecUserCanceled || + errSecAuthFailed || + errSecInteractionRequired => + SecureStorageAccessDeniedException(message: message), + errSecMissingEntitlement => const SecureStorageAccessDeniedException( + message: 'The app is missing the required entitlements', + ), + _ => SecureStorageUnknownException(message), + }; + return SecurityFrameworkException(exception); + } on Exception { + return SecurityFrameworkException( + SecureStorageUnknownException( + 'Unknown error occurred in Security.framework. Status: $status', + ), + ); + } finally { + CFRelease(cfMessage.cast()); + } + } +} diff --git a/packages/celest_core/lib/src/secure_storage/secure_storage.stub.dart b/packages/celest_core/lib/src/secure_storage/secure_storage.stub.dart new file mode 100644 index 00000000..856f05c9 --- /dev/null +++ b/packages/celest_core/lib/src/secure_storage/secure_storage.stub.dart @@ -0,0 +1,24 @@ +import 'package:celest_core/src/secure_storage/secure_storage_platform.web.dart'; + +/// An in-memory implementation of [SecureStoragePlatform] for platforms which +/// do not support secure storage. +final class SecureStoragePlatformStub extends SecureStoragePlatform { + SecureStoragePlatformStub({ + required this.scope, + }) : super.base(); + + final _storage = {}; + final String scope; + + @override + void clear() => _storage.removeWhere((key, _) => key.startsWith('$scope:')); + + @override + String? delete(String key) => _storage.remove('$scope:$key'); + + @override + String? read(String key) => _storage['$scope:$key']; + + @override + String write(String key, String value) => _storage['$scope:$key'] = value; +} diff --git a/packages/celest_core/lib/src/secure_storage/secure_storage_exception.dart b/packages/celest_core/lib/src/secure_storage/secure_storage_exception.dart new file mode 100644 index 00000000..0738a113 --- /dev/null +++ b/packages/celest_core/lib/src/secure_storage/secure_storage_exception.dart @@ -0,0 +1,69 @@ +import 'package:celest_core/src/exception/celest_exception.dart'; +import 'package:celest_core/src/util/globals.dart'; + +sealed class SecureStorageException implements CelestException { + const SecureStorageException(); +} + +final class SecureStorageItemNotFoundException extends SecureStorageException { + const SecureStorageItemNotFoundException({ + String? message, + this.key, + }) : message = message ?? 'The item was not found in secure storage'; + + @override + final String message; + final String? key; + + @override + String toString() { + final sb = StringBuffer('ItemNotFoundException: $message'); + if (!kReleaseMode && key != null) { + sb.write(' (key: $key)'); + } + return sb.toString(); + } +} + +final class SecureStorageDuplicateItemException extends SecureStorageException { + const SecureStorageDuplicateItemException({ + String? message, + this.key, + }) : message = message ?? 'The item already exists in secure storage'; + + @override + final String message; + final String? key; + + @override + String toString() { + final sb = StringBuffer('DuplicateItemException: $message'); + if (!kReleaseMode && key != null) { + sb.write(' (key: $key)'); + } + return sb.toString(); + } +} + +final class SecureStorageAccessDeniedException extends SecureStorageException { + const SecureStorageAccessDeniedException({ + String? message, + }) : message = message ?? 'Access to secure storage was denied'; + + @override + final String message; + + @override + String toString() => 'AccessDeniedException: $message'; +} + +final class SecureStorageUnknownException extends SecureStorageException { + const SecureStorageUnknownException([String? message]) + : message = message ?? 'An unknown error occurred in secure storage'; + + @override + final String message; + + @override + String toString() => 'UnknownException: $message'; +} diff --git a/packages/celest_core/lib/src/secure_storage/secure_storage_platform.vm.dart b/packages/celest_core/lib/src/secure_storage/secure_storage_platform.vm.dart new file mode 100644 index 00000000..3ad26930 --- /dev/null +++ b/packages/celest_core/lib/src/secure_storage/secure_storage_platform.vm.dart @@ -0,0 +1,28 @@ +import 'dart:io'; + +import 'package:celest_core/src/secure_storage/secure_storage.android.dart'; +import 'package:celest_core/src/secure_storage/secure_storage.dart'; +import 'package:celest_core/src/secure_storage/secure_storage.darwin.dart'; +import 'package:meta/meta.dart'; + +abstract base class SecureStoragePlatform implements SecureStorage { + factory SecureStoragePlatform({ + String? scope, + }) { + if (Platform.isIOS || Platform.isMacOS) { + return SecureStoragePlatformDarwin(scope: scope ?? _defaultScope); + } + if (Platform.isAndroid) { + return SecureStoragePlatformAndroid(scope: scope ?? _defaultScope); + } + throw UnsupportedError('This platform is not yet supported.'); + } + + static const _defaultScope = 'dev.celest.celest'; + + @override + void init() {} + + @protected + const SecureStoragePlatform.base(); +} diff --git a/packages/celest_core/lib/src/secure_storage/secure_storage_platform.web.dart b/packages/celest_core/lib/src/secure_storage/secure_storage_platform.web.dart new file mode 100644 index 00000000..76773183 --- /dev/null +++ b/packages/celest_core/lib/src/secure_storage/secure_storage_platform.web.dart @@ -0,0 +1,18 @@ +import 'package:celest_core/src/secure_storage/secure_storage.dart'; +import 'package:celest_core/src/secure_storage/secure_storage.stub.dart'; +import 'package:meta/meta.dart'; + +abstract base class SecureStoragePlatform implements SecureStorage { + factory SecureStoragePlatform({ + String? scope, + }) => + SecureStoragePlatformStub(scope: scope ?? _defaultScope); + + static const _defaultScope = 'dev.celest.celest'; + + @override + void init() {} + + @protected + const SecureStoragePlatform.base(); +} diff --git a/packages/celest_core/pubspec.yaml b/packages/celest_core/pubspec.yaml index a6bb16a4..3918892a 100644 --- a/packages/celest_core/pubspec.yaml +++ b/packages/celest_core/pubspec.yaml @@ -9,8 +9,24 @@ environment: dependencies: collection: ^1.18.0 + ffi: ^2.1.2 + jni: ^0.7.2 meta: ^1.10.0 + os_detect: ^2.0.1 dev_dependencies: + # TODO(dnys1): Use ^12.0.0 when released + # Needed to support global fields. + ffigen: + git: + url: https://github.com/dart-lang/native + path: pkgs/ffigen + jnigen: ^0.7.0 lints: ^3.0.0 test: ^1.24.0 + +flutter: + plugin: + platforms: + android: + ffiPlugin: true diff --git a/packages/celest_core/test/secure_storage/secure_storage_darwin_test.dart b/packages/celest_core/test/secure_storage/secure_storage_darwin_test.dart new file mode 100644 index 00000000..4137b3ea --- /dev/null +++ b/packages/celest_core/test/secure_storage/secure_storage_darwin_test.dart @@ -0,0 +1,72 @@ +@TestOn('mac-os') + +import 'package:celest_core/src/native/darwin/security.ffi.dart'; +import 'package:celest_core/src/secure_storage/secure_storage.dart'; +import 'package:celest_core/src/secure_storage/secure_storage.darwin.dart'; +import 'package:test/test.dart'; + +const key1 = 'key1'; +const key2 = 'key2'; +const value1 = 'value1'; +const value2 = 'value2'; + +void main() { + group('SecureStorage', () { + group('macos', () { + group('clear', () { + final storage = SecureStorage(scope: 'clear'); + + setUp(() { + storage.clear(); + }); + + tearDown(() { + storage.clear(); + }); + + test('removes all keys from storage', () { + // seed storage and confirm values are present + storage + ..write(key1, value1) + ..write(key2, value2); + expect(storage.read(key1), value1); + expect(storage.read(key2), value2); + + // remove all + storage.clear(); + + // assert all data was removed + expect(storage.read(key1), isNull); + expect(storage.read(key2), isNull); + }); + + test('does not throw when no items present', () { + expect(storage.clear, returnsNormally); + }); + }); + }); + }); + + group('SecurityFrameworkException', () { + test('errSecInvalidOwnerEdit', () { + final error = SecurityFrameworkException.fromStatus( + errSecInvalidOwnerEdit, + ); + expect( + error.message, + 'Invalid attempt to change the owner of this item.', + ); + }); + + test('no error', () { + final error = SecurityFrameworkException.fromStatus(errSecSuccess); + expect(error.message, 'No error.'); + }); + + test('invalid code', () { + const invalidCode = 1 << 20; + final error = SecurityFrameworkException.fromStatus(invalidCode); + expect(error.message, 'OSStatus $invalidCode'); + }); + }); +} diff --git a/packages/celest_core/test/secure_storage/secure_storage_test.dart b/packages/celest_core/test/secure_storage/secure_storage_test.dart new file mode 100644 index 00000000..3fc45291 --- /dev/null +++ b/packages/celest_core/test/secure_storage/secure_storage_test.dart @@ -0,0 +1,5 @@ +import '../../example/integration_test/secure_storage_shared.dart'; + +void main() { + sharedTests(); +} diff --git a/packages/celest_core/test/json_value_test.dart b/packages/celest_core/test/serialization/json_value_test.dart similarity index 100% rename from packages/celest_core/test/json_value_test.dart rename to packages/celest_core/test/serialization/json_value_test.dart diff --git a/packages/celest_core/tool/ffigen.sh b/packages/celest_core/tool/ffigen.sh new file mode 100755 index 00000000..10438207 --- /dev/null +++ b/packages/celest_core/tool/ffigen.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -euo pipefail + +echo "Building example app..." +pushd example +flutter pub get +flutter build apk +popd + +echo "Generating FFI bindings..." +dart run ffigen --config=ffigen.core_foundation.yaml +dart run ffigen --config=ffigen.security.yaml + +echo "Generating JNI bindings..." +dart run jnigen --config=jnigen.yaml From 74870878ab40db3c7b9c00f40d4db276e8ed6fbe Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 12:38:34 -0800 Subject: [PATCH 02/14] feat(core): Add secure storage module Adds a secure storage interface which uses FFI bindings to the platform-specific Keychain implementation. --- .github/workflows/celest_core.yaml | 63 +++++++++++++++--------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index 3f800c88..2b42e82e 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -7,31 +7,33 @@ on: # Prevent duplicate runs due to Graphite # https://graphite.dev/docs/troubleshooting#why-are-my-actions-running-twice -concurrency: - group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}-${{ github.ref == 'refs/heads/main' && github.sha || ''}} - cancel-in-progress: true +# concurrency: +# group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}-${{ github.ref == 'refs/heads/main' && github.sha || ''}} +# cancel-in-progress: true jobs: - # analyze_and_format: - # runs-on: ubuntu-latest - # timeout-minutes: 10 - # steps: - # - name: Git Checkout - # uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # 4.1.1 - # - name: Setup Dart - # uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # 1.6.2 - # - name: Get Packages - # working-directory: packages/celest_core - # run: dart pub get - # - name: Analyze - # working-directory: packages/celest_core - # run: dart analyze --fatal-infos --fatal-warnings - # - name: Format - # working-directory: packages/celest_core - # run: dart format --set-exit-if-changed . + analyze_and_format: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Git Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # 4.1.1 + - name: Setup Flutter + uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # 2.13.0 + with: + cache: true + - name: Get Packages + working-directory: packages/celest_core + run: dart pub get + - name: Analyze + working-directory: packages/celest_core + run: dart analyze + - name: Format + working-directory: packages/celest_core + run: dart format --set-exit-if-changed . test: - # needs: analyze_and_format - runs-on: macos-xl + needs: analyze_and_format + runs-on: macos-13-large timeout-minutes: 15 steps: - name: Git Checkout @@ -40,10 +42,6 @@ jobs: uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # 2.13.0 with: cache: true - - name: Setup Android - uses: ReactiveCircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 # 2.30.1 - with: - api-level: 34 - name: Get Packages working-directory: packages/celest_core run: dart pub get @@ -54,8 +52,11 @@ jobs: working-directory: packages/celest_core/example run: flutter pub get - name: Test (Example) - working-directory: packages/celest_core/example - run: | - for OS in "sdk iPhone macos"; do - flutter test -d $OS integration_test/secure_storage_test.dart - done + uses: ReactiveCircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 # 2.30.1 + with: + api-level: 34 + script: | + cd packages/celest_core/example + for OS in "sdk iPhone macos"; do + flutter test -d $OS integration_test/secure_storage_test.dart + done From b0c12f29eca1fd1e20a6ad68862a4c5c09afff7f Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 13:10:32 -0800 Subject: [PATCH 03/14] fix android arch --- .github/workflows/celest_core.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index 2b42e82e..f44d9de9 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -55,6 +55,7 @@ jobs: uses: ReactiveCircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 # 2.30.1 with: api-level: 34 + arch: x86_64 script: | cd packages/celest_core/example for OS in "sdk iPhone macos"; do From e68c8dc188456534dc350c2c8e0a8e60602edf71 Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 13:18:30 -0800 Subject: [PATCH 04/14] use amplify action --- .github/workflows/celest_core.yaml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index f44d9de9..e4a905ec 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -7,9 +7,9 @@ on: # Prevent duplicate runs due to Graphite # https://graphite.dev/docs/troubleshooting#why-are-my-actions-running-twice -# concurrency: -# group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}-${{ github.ref == 'refs/heads/main' && github.sha || ''}} -# cancel-in-progress: true +concurrency: + group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}-${{ github.ref == 'refs/heads/main' && github.sha || ''}} + cancel-in-progress: true jobs: analyze_and_format: @@ -52,10 +52,9 @@ jobs: working-directory: packages/celest_core/example run: flutter pub get - name: Test (Example) - uses: ReactiveCircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 # 2.30.1 + uses: aws-amplify/amplify-flutter/.github/composite_actions/launch_android_emulator@main with: api-level: 34 - arch: x86_64 script: | cd packages/celest_core/example for OS in "sdk iPhone macos"; do From daaf6969c326ad8b8d56614d78f289507ea4562a Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 13:29:09 -0800 Subject: [PATCH 05/14] clean up --- .github/workflows/celest_core.yaml | 3 +- .../celest_core/ffigen.core_foundation.yaml | 3 - packages/celest_core/ffigen.security.yaml | 6 - .../native/darwin/core_foundation.ffi.dart | 725 +----------------- .../src/native/darwin/darwin_ffi_helpers.dart | 23 +- .../lib/src/native/darwin/security.ffi.dart | 6 +- 6 files changed, 10 insertions(+), 756 deletions(-) diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index e4a905ec..f931c818 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -57,6 +57,7 @@ jobs: api-level: 34 script: | cd packages/celest_core/example - for OS in "sdk iPhone macos"; do + for OS in sdk iPhone macos + do flutter test -d $OS integration_test/secure_storage_test.dart done diff --git a/packages/celest_core/ffigen.core_foundation.yaml b/packages/celest_core/ffigen.core_foundation.yaml index 2af63fa6..d88260a5 100644 --- a/packages/celest_core/ffigen.core_foundation.yaml +++ b/packages/celest_core/ffigen.core_foundation.yaml @@ -32,8 +32,6 @@ globals: functions: include: - CFDictionary.* - - CFArray.* - - CF(.*)GetTypeID - CFDataCreate - CFStringGetCStringPtr - CFStringGetCString @@ -47,7 +45,6 @@ structs: "__CFString": CFString "__CFData": CFData "__CFDictionary": CFDictionary - "__CFArray": CFArray unnamed-enums: include: - kCF.* diff --git a/packages/celest_core/ffigen.security.yaml b/packages/celest_core/ffigen.security.yaml index bbe4a82b..a2f42176 100644 --- a/packages/celest_core/ffigen.security.yaml +++ b/packages/celest_core/ffigen.security.yaml @@ -31,16 +31,10 @@ typedefs: functions: include: - Sec.* - - SecKeychainItem.* globals: include: - kSec.* - kCF.* -structs: - include: - - __SecKeychainItem - rename: - "__SecKeychainItem": SecKeychainItem unnamed-enums: include: - errSec.* diff --git a/packages/celest_core/lib/src/native/darwin/core_foundation.ffi.dart b/packages/celest_core/lib/src/native/darwin/core_foundation.ffi.dart index baf28626..48ee9279 100644 --- a/packages/celest_core/lib/src/native/darwin/core_foundation.ffi.dart +++ b/packages/celest_core/lib/src/native/darwin/core_foundation.ffi.dart @@ -14,9 +14,6 @@ external double kCFCoreFoundationVersionNumber; @ffi.Native() external final int kCFNotFound; -@ffi.Native() -external int CFNullGetTypeID(); - /// the singleton null instance @ffi.Native() external final CFNullRef kCFNull; @@ -55,15 +52,6 @@ external final CFAllocatorRef kCFAllocatorNull; @ffi.Native() external final CFAllocatorRef kCFAllocatorUseContext; -@ffi.Native() -external int CFAllocatorGetTypeID(); - -/// Polymorphic CF functions -@ffi.Native() -external int CFGetTypeID( - CFTypeRef cf, -); - @ffi.Native() external void CFRelease( CFTypeRef cf, @@ -650,642 +638,6 @@ external void CFDictionaryRemoveAllValues( @ffi.Native() external final CFArrayCallBacks kCFTypeArrayCallBacks; -/// ! -/// @function CFArrayGetTypeID -/// Returns the type identifier of all CFArray instances. -@ffi.Native() -external int CFArrayGetTypeID(); - -/// ! -/// @function CFArrayCreate -/// Creates a new immutable array with the given values. -/// @param allocator The CFAllocator which should be used to allocate -/// memory for the array and its storage for values. This -/// parameter may be NULL in which case the current default -/// CFAllocator is used. If this reference is not a valid -/// CFAllocator, the behavior is undefined. -/// @param values A C array of the pointer-sized values to be in the -/// array. The values in the array are ordered in the same order -/// in which they appear in this C array. This parameter may be -/// NULL if the numValues parameter is 0. This C array is not -/// changed or freed by this function. If this parameter is not -/// a valid pointer to a C array of at least numValues pointers, -/// the behavior is undefined. -/// @param numValues The number of values to copy from the values C -/// array into the CFArray. This number will be the count of the -/// array. -/// If this parameter is negative, or greater than the number of -/// values actually in the value's C array, the behavior is -/// undefined. -/// @param callBacks A pointer to a CFArrayCallBacks structure -/// initialized with the callbacks for the array to use on each -/// value in the array. The retain callback will be used within -/// this function, for example, to retain all of the new values -/// from the values C array. A copy of the contents of the -/// callbacks structure is made, so that a pointer to a -/// structure on the stack can be passed in, or can be reused -/// for multiple array creations. If the version field of this -/// callbacks structure is not one of the defined ones for -/// CFArray, the behavior is undefined. The retain field may be -/// NULL, in which case the CFArray will do nothing to add a -/// retain to the contained values for the array. The release -/// field may be NULL, in which case the CFArray will do nothing -/// to remove the array's retain (if any) on the values when the -/// array is destroyed. If the copyDescription field is NULL, -/// the array will create a simple description for the value. If -/// the equal field is NULL, the array will use pointer equality -/// to test for equality of values. This callbacks parameter -/// itself may be NULL, which is treated as if a valid structure -/// of version 0 with all fields NULL had been passed in. -/// Otherwise, if any of the fields are not valid pointers to -/// functions of the correct type, or this parameter is not a -/// valid pointer to a CFArrayCallBacks callbacks structure, -/// the behavior is undefined. If any of the values put into the -/// array is not one understood by one of the callback functions -/// the behavior when that callback function is used is -/// undefined. -/// @result A reference to the new immutable CFArray. -@ffi.Native< - CFArrayRef Function(CFAllocatorRef, ffi.Pointer>, - CFIndex, ffi.Pointer)>() -external CFArrayRef CFArrayCreate( - CFAllocatorRef allocator, - ffi.Pointer> values, - int numValues, - ffi.Pointer callBacks, -); - -/// ! -/// @function CFArrayCreateCopy -/// Creates a new immutable array with the values from the given array. -/// @param allocator The CFAllocator which should be used to allocate -/// memory for the array and its storage for values. This -/// parameter may be NULL in which case the current default -/// CFAllocator is used. If this reference is not a valid -/// CFAllocator, the behavior is undefined. -/// @param theArray The array which is to be copied. The values from the -/// array are copied as pointers into the new array (that is, -/// the values themselves are copied, not that which the values -/// point to, if anything). However, the values are also -/// retained by the new array. The count of the new array will -/// be the same as the given array. The new array uses the same -/// callbacks as the array to be copied. If this parameter is -/// not a valid CFArray, the behavior is undefined. -/// @result A reference to the new immutable CFArray. -@ffi.Native() -external CFArrayRef CFArrayCreateCopy( - CFAllocatorRef allocator, - CFArrayRef theArray, -); - -/// ! -/// @function CFArrayCreateMutable -/// Creates a new empty mutable array. -/// @param allocator The CFAllocator which should be used to allocate -/// memory for the array and its storage for values. This -/// parameter may be NULL in which case the current default -/// CFAllocator is used. If this reference is not a valid -/// CFAllocator, the behavior is undefined. -/// @param capacity A hint about the number of values that will be held -/// by the CFArray. Pass 0 for no hint. The implementation may -/// ignore this hint, or may use it to optimize various -/// operations. An array's actual capacity is only limited by -/// address space and available memory constraints). If this -/// parameter is negative, the behavior is undefined. -/// @param callBacks A pointer to a CFArrayCallBacks structure -/// initialized with the callbacks for the array to use on each -/// value in the array. A copy of the contents of the -/// callbacks structure is made, so that a pointer to a -/// structure on the stack can be passed in, or can be reused -/// for multiple array creations. If the version field of this -/// callbacks structure is not one of the defined ones for -/// CFArray, the behavior is undefined. The retain field may be -/// NULL, in which case the CFArray will do nothing to add a -/// retain to the contained values for the array. The release -/// field may be NULL, in which case the CFArray will do nothing -/// to remove the array's retain (if any) on the values when the -/// array is destroyed. If the copyDescription field is NULL, -/// the array will create a simple description for the value. If -/// the equal field is NULL, the array will use pointer equality -/// to test for equality of values. This callbacks parameter -/// itself may be NULL, which is treated as if a valid structure -/// of version 0 with all fields NULL had been passed in. -/// Otherwise, if any of the fields are not valid pointers to -/// functions of the correct type, or this parameter is not a -/// valid pointer to a CFArrayCallBacks callbacks structure, -/// the behavior is undefined. If any of the values put into the -/// array is not one understood by one of the callback functions -/// the behavior when that callback function is used is -/// undefined. -/// @result A reference to the new mutable CFArray. -@ffi.Native< - CFMutableArrayRef Function( - CFAllocatorRef, CFIndex, ffi.Pointer)>() -external CFMutableArrayRef CFArrayCreateMutable( - CFAllocatorRef allocator, - int capacity, - ffi.Pointer callBacks, -); - -/// ! -/// @function CFArrayCreateMutableCopy -/// Creates a new mutable array with the values from the given array. -/// @param allocator The CFAllocator which should be used to allocate -/// memory for the array and its storage for values. This -/// parameter may be NULL in which case the current default -/// CFAllocator is used. If this reference is not a valid -/// CFAllocator, the behavior is undefined. -/// @param capacity A hint about the number of values that will be held -/// by the CFArray. Pass 0 for no hint. The implementation may -/// ignore this hint, or may use it to optimize various -/// operations. An array's actual capacity is only limited by -/// address space and available memory constraints). -/// This parameter must be greater than or equal -/// to the count of the array which is to be copied, or the -/// behavior is undefined. If this parameter is negative, the -/// behavior is undefined. -/// @param theArray The array which is to be copied. The values from the -/// array are copied as pointers into the new array (that is, -/// the values themselves are copied, not that which the values -/// point to, if anything). However, the values are also -/// retained by the new array. The count of the new array will -/// be the same as the given array. The new array uses the same -/// callbacks as the array to be copied. If this parameter is -/// not a valid CFArray, the behavior is undefined. -/// @result A reference to the new mutable CFArray. -@ffi.Native() -external CFMutableArrayRef CFArrayCreateMutableCopy( - CFAllocatorRef allocator, - int capacity, - CFArrayRef theArray, -); - -/// ! -/// @function CFArrayGetCount -/// Returns the number of values currently in the array. -/// @param theArray The array to be queried. If this parameter is not a valid -/// CFArray, the behavior is undefined. -/// @result The number of values in the array. -@ffi.Native() -external int CFArrayGetCount( - CFArrayRef theArray, -); - -/// ! -/// @function CFArrayGetCountOfValue -/// Counts the number of times the given value occurs in the array. -/// @param theArray The array to be searched. If this parameter is not a -/// valid CFArray, the behavior is undefined. -/// @param range The range within the array to search. If the range -/// location or end point (defined by the location plus length -/// minus 1) is outside the index space of the array (0 to -/// N-1 inclusive, where N is the count of the array), the -/// behavior is undefined. If the range length is negative, the -/// behavior is undefined. The range may be empty (length 0). -/// @param value The value for which to find matches in the array. The -/// equal() callback provided when the array was created is -/// used to compare. If the equal() callback was NULL, pointer -/// equality (in C, ==) is used. If value, or any of the values -/// in the array, are not understood by the equal() callback, -/// the behavior is undefined. -/// @result The number of times the given value occurs in the array, -/// within the specified range. -@ffi.Native)>() -external int CFArrayGetCountOfValue( - CFArrayRef theArray, - CFRange range, - ffi.Pointer value, -); - -/// ! -/// @function CFArrayContainsValue -/// Reports whether or not the value is in the array. -/// @param theArray The array to be searched. If this parameter is not a -/// valid CFArray, the behavior is undefined. -/// @param range The range within the array to search. If the range -/// location or end point (defined by the location plus length -/// minus 1) is outside the index space of the array (0 to -/// N-1 inclusive, where N is the count of the array), the -/// behavior is undefined. If the range length is negative, the -/// behavior is undefined. The range may be empty (length 0). -/// @param value The value for which to find matches in the array. The -/// equal() callback provided when the array was created is -/// used to compare. If the equal() callback was NULL, pointer -/// equality (in C, ==) is used. If value, or any of the values -/// in the array, are not understood by the equal() callback, -/// the behavior is undefined. -/// @result true, if the value is in the specified range of the array, -/// otherwise false. -@ffi.Native< - ffi.UnsignedChar Function(CFArrayRef, CFRange, ffi.Pointer)>() -external int CFArrayContainsValue( - CFArrayRef theArray, - CFRange range, - ffi.Pointer value, -); - -/// ! -/// @function CFArrayGetValueAtIndex -/// Retrieves the value at the given index. -/// @param theArray The array to be queried. If this parameter is not a -/// valid CFArray, the behavior is undefined. -/// @param idx The index of the value to retrieve. If the index is -/// outside the index space of the array (0 to N-1 inclusive, -/// where N is the count of the array), the behavior is -/// undefined. -/// @result The value with the given index in the array. -@ffi.Native Function(CFArrayRef, CFIndex)>() -external ffi.Pointer CFArrayGetValueAtIndex( - CFArrayRef theArray, - int idx, -); - -/// ! -/// @function CFArrayGetValues -/// Fills the buffer with values from the array. -/// @param theArray The array to be queried. If this parameter is not a -/// valid CFArray, the behavior is undefined. -/// @param range The range of values within the array to retrieve. If -/// the range location or end point (defined by the location -/// plus length minus 1) is outside the index space of the -/// array (0 to N-1 inclusive, where N is the count of the -/// array), the behavior is undefined. If the range length is -/// negative, the behavior is undefined. The range may be empty -/// (length 0), in which case no values are put into the buffer. -/// @param values A C array of pointer-sized values to be filled with -/// values from the array. The values in the C array are ordered -/// in the same order in which they appear in the array. If this -/// parameter is not a valid pointer to a C array of at least -/// range.length pointers, the behavior is undefined. -@ffi.Native< - ffi.Void Function( - CFArrayRef, CFRange, ffi.Pointer>)>() -external void CFArrayGetValues( - CFArrayRef theArray, - CFRange range, - ffi.Pointer> values, -); - -/// ! -/// @function CFArrayApplyFunction -/// Calls a function once for each value in the array. -/// @param theArray The array to be operated upon. If this parameter is not -/// a valid CFArray, the behavior is undefined. -/// @param range The range of values within the array to which to apply -/// the function. If the range location or end point (defined by -/// the location plus length minus 1) is outside the index -/// space of the array (0 to N-1 inclusive, where N is the count -/// of the array), the behavior is undefined. If the range -/// length is negative, the behavior is undefined. The range may -/// be empty (length 0). -/// @param applier The callback function to call once for each value in -/// the given range in the array. If this parameter is not a -/// pointer to a function of the correct prototype, the behavior -/// is undefined. If there are values in the range which the -/// applier function does not expect or cannot properly apply -/// to, the behavior is undefined. -/// @param context A pointer-sized user-defined value, which is passed -/// as the second parameter to the applier function, but is -/// otherwise unused by this function. If the context is not -/// what is expected by the applier function, the behavior is -/// undefined. -@ffi.Native< - ffi.Void Function( - CFArrayRef, CFRange, CFArrayApplierFunction, ffi.Pointer)>() -external void CFArrayApplyFunction( - CFArrayRef theArray, - CFRange range, - CFArrayApplierFunction applier, - ffi.Pointer context, -); - -/// ! -/// @function CFArrayGetFirstIndexOfValue -/// Searches the array for the value. -/// @param theArray The array to be searched. If this parameter is not a -/// valid CFArray, the behavior is undefined. -/// @param range The range within the array to search. If the range -/// location or end point (defined by the location plus length -/// minus 1) is outside the index space of the array (0 to -/// N-1 inclusive, where N is the count of the array), the -/// behavior is undefined. If the range length is negative, the -/// behavior is undefined. The range may be empty (length 0). -/// The search progresses from the smallest index defined by -/// the range to the largest. -/// @param value The value for which to find a match in the array. The -/// equal() callback provided when the array was created is -/// used to compare. If the equal() callback was NULL, pointer -/// equality (in C, ==) is used. If value, or any of the values -/// in the array, are not understood by the equal() callback, -/// the behavior is undefined. -/// @result The lowest index of the matching values in the range, or -/// kCFNotFound if no value in the range matched. -@ffi.Native)>() -external int CFArrayGetFirstIndexOfValue( - CFArrayRef theArray, - CFRange range, - ffi.Pointer value, -); - -/// ! -/// @function CFArrayGetLastIndexOfValue -/// Searches the array for the value. -/// @param theArray The array to be searched. If this parameter is not a -/// valid CFArray, the behavior is undefined. -/// @param range The range within the array to search. If the range -/// location or end point (defined by the location plus length -/// minus 1) is outside the index space of the array (0 to -/// N-1 inclusive, where N is the count of the array), the -/// behavior is undefined. If the range length is negative, the -/// behavior is undefined. The range may be empty (length 0). -/// The search progresses from the largest index defined by the -/// range to the smallest. -/// @param value The value for which to find a match in the array. The -/// equal() callback provided when the array was created is -/// used to compare. If the equal() callback was NULL, pointer -/// equality (in C, ==) is used. If value, or any of the values -/// in the array, are not understood by the equal() callback, -/// the behavior is undefined. -/// @result The highest index of the matching values in the range, or -/// kCFNotFound if no value in the range matched. -@ffi.Native)>() -external int CFArrayGetLastIndexOfValue( - CFArrayRef theArray, - CFRange range, - ffi.Pointer value, -); - -/// ! -/// @function CFArrayBSearchValues -/// Searches the array for the value using a binary search algorithm. -/// @param theArray The array to be searched. If this parameter is not a -/// valid CFArray, the behavior is undefined. If the array is -/// not sorted from least to greatest according to the -/// comparator function, the behavior is undefined. -/// @param range The range within the array to search. If the range -/// location or end point (defined by the location plus length -/// minus 1) is outside the index space of the array (0 to -/// N-1 inclusive, where N is the count of the array), the -/// behavior is undefined. If the range length is negative, the -/// behavior is undefined. The range may be empty (length 0). -/// @param value The value for which to find a match in the array. If -/// value, or any of the values in the array, are not understood -/// by the comparator callback, the behavior is undefined. -/// @param comparator The function with the comparator function type -/// signature which is used in the binary search operation to -/// compare values in the array with the given value. If this -/// parameter is not a pointer to a function of the correct -/// prototype, the behavior is undefined. If there are values -/// in the range which the comparator function does not expect -/// or cannot properly compare, the behavior is undefined. -/// @param context A pointer-sized user-defined value, which is passed -/// as the third parameter to the comparator function, but is -/// otherwise unused by this function. If the context is not -/// what is expected by the comparator function, the behavior is -/// undefined. -/// @result The return value is either 1) the index of a value that -/// matched, if the target value matches one or more in the -/// range, 2) greater than or equal to the end point of the -/// range, if the value is greater than all the values in the -/// range, or 3) the index of the value greater than the target -/// value, if the value lies between two of (or less than all -/// of) the values in the range. -@ffi.Native< - CFIndex Function(CFArrayRef, CFRange, ffi.Pointer, - CFComparatorFunction, ffi.Pointer)>() -external int CFArrayBSearchValues( - CFArrayRef theArray, - CFRange range, - ffi.Pointer value, - CFComparatorFunction comparator, - ffi.Pointer context, -); - -/// ! -/// @function CFArrayAppendValue -/// Adds the value to the array giving it a new largest index. -/// @param theArray The array to which the value is to be added. If this -/// parameter is not a valid mutable CFArray, the behavior is -/// undefined. -/// @param value The value to add to the array. The value is retained by -/// the array using the retain callback provided when the array -/// was created. If the value is not of the sort expected by the -/// retain callback, the behavior is undefined. The value is -/// assigned to the index one larger than the previous largest -/// index, and the count of the array is increased by one. -@ffi.Native)>() -external void CFArrayAppendValue( - CFMutableArrayRef theArray, - ffi.Pointer value, -); - -/// ! -/// @function CFArrayInsertValueAtIndex -/// Adds the value to the array, giving it the given index. -/// @param theArray The array to which the value is to be added. If this -/// parameter is not a valid mutable CFArray, the behavior is -/// undefined. -/// @param idx The index to which to add the new value. If the index is -/// outside the index space of the array (0 to N inclusive, -/// where N is the count of the array before the operation), the -/// behavior is undefined. If the index is the same as N, this -/// function has the same effect as CFArrayAppendValue(). -/// @param value The value to add to the array. The value is retained by -/// the array using the retain callback provided when the array -/// was created. If the value is not of the sort expected by the -/// retain callback, the behavior is undefined. The value is -/// assigned to the given index, and all values with equal and -/// larger indices have their indexes increased by one. -@ffi.Native< - ffi.Void Function(CFMutableArrayRef, CFIndex, ffi.Pointer)>() -external void CFArrayInsertValueAtIndex( - CFMutableArrayRef theArray, - int idx, - ffi.Pointer value, -); - -/// ! -/// @function CFArraySetValueAtIndex -/// Changes the value with the given index in the array. -/// @param theArray The array in which the value is to be changed. If this -/// parameter is not a valid mutable CFArray, the behavior is -/// undefined. -/// @param idx The index to which to set the new value. If the index is -/// outside the index space of the array (0 to N inclusive, -/// where N is the count of the array before the operation), the -/// behavior is undefined. If the index is the same as N, this -/// function has the same effect as CFArrayAppendValue(). -/// @param value The value to set in the array. The value is retained by -/// the array using the retain callback provided when the array -/// was created, and the previous value with that index is -/// released. If the value is not of the sort expected by the -/// retain callback, the behavior is undefined. The indices of -/// other values is not affected. -@ffi.Native< - ffi.Void Function(CFMutableArrayRef, CFIndex, ffi.Pointer)>() -external void CFArraySetValueAtIndex( - CFMutableArrayRef theArray, - int idx, - ffi.Pointer value, -); - -/// ! -/// @function CFArrayRemoveValueAtIndex -/// Removes the value with the given index from the array. -/// @param theArray The array from which the value is to be removed. If -/// this parameter is not a valid mutable CFArray, the behavior -/// is undefined. -/// @param idx The index from which to remove the value. If the index is -/// outside the index space of the array (0 to N-1 inclusive, -/// where N is the count of the array before the operation), the -/// behavior is undefined. -@ffi.Native() -external void CFArrayRemoveValueAtIndex( - CFMutableArrayRef theArray, - int idx, -); - -/// ! -/// @function CFArrayRemoveAllValues -/// Removes all the values from the array, making it empty. -/// @param theArray The array from which all of the values are to be -/// removed. If this parameter is not a valid mutable CFArray, -/// the behavior is undefined. -@ffi.Native() -external void CFArrayRemoveAllValues( - CFMutableArrayRef theArray, -); - -/// ! -/// @function CFArrayReplaceValues -/// Replaces a range of values in the array. -/// @param theArray The array from which all of the values are to be -/// removed. If this parameter is not a valid mutable CFArray, -/// the behavior is undefined. -/// @param range The range of values within the array to replace. If the -/// range location or end point (defined by the location plus -/// length minus 1) is outside the index space of the array (0 -/// to N inclusive, where N is the count of the array), the -/// behavior is undefined. If the range length is negative, the -/// behavior is undefined. The range may be empty (length 0), -/// in which case the new values are merely inserted at the -/// range location. -/// @param newValues A C array of the pointer-sized values to be placed -/// into the array. The new values in the array are ordered in -/// the same order in which they appear in this C array. This -/// parameter may be NULL if the newCount parameter is 0. This -/// C array is not changed or freed by this function. If this -/// parameter is not a valid pointer to a C array of at least -/// newCount pointers, the behavior is undefined. -/// @param newCount The number of values to copy from the values C -/// array into the CFArray. If this parameter is different than -/// the range length, the excess newCount values will be -/// inserted after the range, or the excess range values will be -/// deleted. This parameter may be 0, in which case no new -/// values are replaced into the array and the values in the -/// range are simply removed. If this parameter is negative, or -/// greater than the number of values actually in the newValues -/// C array, the behavior is undefined. -@ffi.Native< - ffi.Void Function(CFMutableArrayRef, CFRange, - ffi.Pointer>, CFIndex)>() -external void CFArrayReplaceValues( - CFMutableArrayRef theArray, - CFRange range, - ffi.Pointer> newValues, - int newCount, -); - -/// ! -/// @function CFArrayExchangeValuesAtIndices -/// Exchanges the values at two indices of the array. -/// @param theArray The array of which the values are to be swapped. If -/// this parameter is not a valid mutable CFArray, the behavior -/// is undefined. -/// @param idx1 The first index whose values should be swapped. If the -/// index is outside the index space of the array (0 to N-1 -/// inclusive, where N is the count of the array before the -/// operation), the behavior is undefined. -/// @param idx2 The second index whose values should be swapped. If the -/// index is outside the index space of the array (0 to N-1 -/// inclusive, where N is the count of the array before the -/// operation), the behavior is undefined. -@ffi.Native() -external void CFArrayExchangeValuesAtIndices( - CFMutableArrayRef theArray, - int idx1, - int idx2, -); - -/// ! -/// @function CFArraySortValues -/// Sorts the values in the array using the given comparison function. -/// @param theArray The array whose values are to be sorted. If this -/// parameter is not a valid mutable CFArray, the behavior is -/// undefined. -/// @param range The range of values within the array to sort. If the -/// range location or end point (defined by the location plus -/// length minus 1) is outside the index space of the array (0 -/// to N-1 inclusive, where N is the count of the array), the -/// behavior is undefined. If the range length is negative, the -/// behavior is undefined. The range may be empty (length 0). -/// @param comparator The function with the comparator function type -/// signature which is used in the sort operation to compare -/// values in the array with the given value. If this parameter -/// is not a pointer to a function of the correct prototype, the -/// the behavior is undefined. If there are values in the array -/// which the comparator function does not expect or cannot -/// properly compare, the behavior is undefined. The values in -/// the range are sorted from least to greatest according to -/// this function. -/// @param context A pointer-sized user-defined value, which is passed -/// as the third parameter to the comparator function, but is -/// otherwise unused by this function. If the context is not -/// what is expected by the comparator function, the behavior is -/// undefined. -@ffi.Native< - ffi.Void Function(CFMutableArrayRef, CFRange, CFComparatorFunction, - ffi.Pointer)>() -external void CFArraySortValues( - CFMutableArrayRef theArray, - CFRange range, - CFComparatorFunction comparator, - ffi.Pointer context, -); - -/// ! -/// @function CFArrayAppendArray -/// Adds the values from an array to another array. -/// @param theArray The array to which values from the otherArray are to -/// be added. If this parameter is not a valid mutable CFArray, -/// the behavior is undefined. -/// @param otherArray The array providing the values to be added to the -/// array. If this parameter is not a valid CFArray, the -/// behavior is undefined. -/// @param otherRange The range within the otherArray from which to add -/// the values to the array. If the range location or end point -/// (defined by the location plus length minus 1) is outside -/// the index space of the otherArray (0 to N-1 inclusive, where -/// N is the count of the otherArray), the behavior is -/// undefined. The new values are retained by the array using -/// the retain callback provided when the array was created. If -/// the values are not of the sort expected by the retain -/// callback, the behavior is undefined. The values are assigned -/// to the indices one larger than the previous largest index -/// in the array, and beyond, and the count of the array is -/// increased by range.length. The values are assigned new -/// indices in the array from smallest to largest index in the -/// order in which they appear in the otherArray. -@ffi.Native() -external void CFArrayAppendArray( - CFMutableArrayRef theArray, - CFArrayRef otherArray, - CFRange otherRange, -); - -@ffi.Native() -external int CFDataGetTypeID(); - @ffi.Native< CFDataRef Function( CFAllocatorRef, ffi.Pointer, CFIndex)>() @@ -1300,18 +652,6 @@ external ffi.Pointer CFDataGetBytePtr( CFDataRef theData, ); -/// ! -/// @function CFCharacterSetGetTypeID -/// Returns the type identifier of all CFCharacterSet instances. -@ffi.Native() -external int CFCharacterSetGetTypeID(); - -@ffi.Native() -external int CFNotificationCenterGetTypeID(); - -@ffi.Native() -external int CFLocaleGetTypeID(); - /// Returns the display name for the given value. The key tells what /// the value is, and is one of the usual locale property keys, though /// not all locale property keys have values with display name values. @@ -1420,12 +760,6 @@ external final CFCalendarIdentifier kCFIslamicTabularCalendar; @ffi.Native() external final CFCalendarIdentifier kCFIslamicUmmAlQuraCalendar; -/// ! -/// @function CFErrorGetTypeID -/// Returns the type identifier of all CFError instances. -@ffi.Native() -external int CFErrorGetTypeID(); - /// Predefined domains; value of "code" will correspond to preexisting values in these domains. @ffi.Native() external final CFErrorDomain kCFErrorDomainPOSIX; @@ -1471,10 +805,6 @@ external final CFStringRef kCFErrorURLKey; @ffi.Native() external final CFStringRef kCFErrorFilePathKey; -/// CFString type ID -@ffi.Native() -external int CFStringGetTypeID(); - @ffi.Native< CFStringRef Function( CFAllocatorRef, ffi.Pointer, CFStringEncoding)>() @@ -1563,8 +893,6 @@ external final CFStringRef kCFStringTransformStripDiacritics; typedef CFIndex = ffi.Long; typedef DartCFIndex = int; -typedef CFTypeID = ffi.UnsignedLong; -typedef DartCFTypeID = int; /// Null representant typedef CFNullRef = ffi.Pointer<__CFNull>; @@ -1691,6 +1019,9 @@ final class CFDictionaryValueCallBacks extends ffi.Struct { external CFDictionaryEqualCallBack equal; } +typedef CFTypeID = ffi.UnsignedLong; +typedef DartCFTypeID = int; + /// ! /// @typedef CFDictionaryRef /// This is the type of a reference to immutable CFDictionarys. @@ -1776,56 +1107,6 @@ typedef CFArrayEqualCallBackFunction = ffi.UnsignedChar Function( ffi.Pointer value1, ffi.Pointer value2); typedef DartCFArrayEqualCallBackFunction = int Function( ffi.Pointer value1, ffi.Pointer value2); - -/// ! -/// @typedef CFArrayRef -/// This is the type of a reference to immutable CFArrays. -typedef CFArrayRef = ffi.Pointer; - -final class CFArray extends ffi.Opaque {} - -/// ! -/// @typedef CFMutableArrayRef -/// This is the type of a reference to mutable CFArrays. -typedef CFMutableArrayRef = ffi.Pointer; - -/// Range type -final class CFRange extends ffi.Struct { - @CFIndex() - external int location; - - @CFIndex() - external int length; -} - -/// ! -/// @typedef CFArrayApplierFunction -/// Type of the callback function used by the apply functions of -/// CFArrays. -/// @param value The current value from the array. -/// @param context The user-defined context parameter given to the apply -/// function. -typedef CFArrayApplierFunction - = ffi.Pointer>; -typedef CFArrayApplierFunctionFunction = ffi.Void Function( - ffi.Pointer value, ffi.Pointer context); -typedef DartCFArrayApplierFunctionFunction = void Function( - ffi.Pointer value, ffi.Pointer context); - -/// A standard comparison function -typedef CFComparatorFunction - = ffi.Pointer>; -typedef CFComparatorFunctionFunction = CFComparisonResult Function( - ffi.Pointer val1, - ffi.Pointer val2, - ffi.Pointer context); -typedef DartCFComparatorFunctionFunction = DartCFIndex Function( - ffi.Pointer val1, - ffi.Pointer val2, - ffi.Pointer context); - -/// Values returned from comparison functions -typedef CFComparisonResult = CFIndex; typedef CFDataRef = ffi.Pointer; final class CFData extends ffi.Opaque {} diff --git a/packages/celest_core/lib/src/native/darwin/darwin_ffi_helpers.dart b/packages/celest_core/lib/src/native/darwin/darwin_ffi_helpers.dart index 433c4024..0dba85e6 100644 --- a/packages/celest_core/lib/src/native/darwin/darwin_ffi_helpers.dart +++ b/packages/celest_core/lib/src/native/darwin/darwin_ffi_helpers.dart @@ -9,7 +9,7 @@ extension StringToCFString on String { Pointer toCFString(Arena arena) { final str = toNativeUtf8(allocator: arena); final cfStr = CFStringCreateWithCString( - nullptr, // default allocator + kCFAllocatorDefault, str.cast(), kCFStringEncodingUTF8, ); @@ -23,7 +23,7 @@ extension StringToCFString on String { Pointer toCFData(Arena arena) { final data = toNativeUtf8(allocator: arena); final cfData = CFDataCreate( - nullptr, // default allocator + kCFAllocatorDefault, data.cast(), data.length, ); @@ -112,22 +112,3 @@ extension CFStringRefToString on CFStringRef { } } } - -extension CFArrayToList on CFArrayRef { - /// Converts `this` to a [List]. - List toList() { - if (this == nullptr) { - return const []; - } - final length = CFArrayGetCount(this); - if (length == 0) { - return const []; - } - final list = []; - for (var i = 0; i < length; i++) { - final value = CFArrayGetValueAtIndex(this, i); - list.add(value); - } - return list; - } -} diff --git a/packages/celest_core/lib/src/native/darwin/security.ffi.dart b/packages/celest_core/lib/src/native/darwin/security.ffi.dart index 5693f1f3..745e0c8c 100644 --- a/packages/celest_core/lib/src/native/darwin/security.ffi.dart +++ b/packages/celest_core/lib/src/native/darwin/security.ffi.dart @@ -1745,8 +1745,6 @@ final class __CFNull extends ffi.Opaque {} final class __CFAllocator extends ffi.Opaque {} -final class SecKeychainItem extends ffi.Opaque {} - final class __CFBoolean extends ffi.Opaque {} final class __CFNumber extends ffi.Opaque {} @@ -1852,7 +1850,9 @@ final class CFDictionaryValueCallBacks extends ffi.Struct { /// ! /// @typedef SecKeychainItemRef /// @abstract Contains information about a keychain item. -typedef SecKeychainItemRef = ffi.Pointer; +typedef SecKeychainItemRef = ffi.Pointer<__SecKeychainItem>; + +final class __SecKeychainItem extends ffi.Opaque {} /// ! /// @typedef SecKeychainAttributeList From 37c0b104f267a8d37d695254d0575d72b01ce358 Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 13:51:12 -0800 Subject: [PATCH 06/14] clean up --- .github/workflows/celest_core.yaml | 55 ++++++++++++++++--- .vscode/settings.json | 6 -- packages/celest_core/CHANGELOG.md | 2 +- .../celest/celest_core/CelestSecureStorage.kt | 2 +- .../secure_storage_shared.dart | 32 +++++++++-- .../secure_storage.android.dart | 9 ++- .../secure_storage_darwin_test.dart | 42 -------------- .../secure_storage/secure_storage_test.dart | 4 +- 8 files changed, 84 insertions(+), 68 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index f931c818..419ffaa5 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -31,10 +31,27 @@ jobs: - name: Format working-directory: packages/celest_core run: dart format --set-exit-if-changed . - test: + test_dart: + needs: analyze_and_format + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Git Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # 4.1.1 + - name: Setup Flutter + uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # 2.13.0 + with: + cache: true + - name: Get Packages + working-directory: packages/celest_core + run: dart pub get + - name: Test + working-directory: packages/celest_core + run: dart test + test_flutter_darwin: needs: analyze_and_format runs-on: macos-13-large - timeout-minutes: 15 + timeout-minutes: 10 steps: - name: Git Checkout uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # 4.1.1 @@ -51,13 +68,35 @@ jobs: - name: Get Packages (Example) working-directory: packages/celest_core/example run: flutter pub get - - name: Test (Example) + - name: Setup iOS Simulator + uses: aws-amplify/amplify-flutter/.github/composite_actions/launch_ios_simulator@main + - name: Test (iOS) + working-directory: packages/celest_core/example + run: flutter test -d iPhone integration_test/secure_storage_test.dart + - name: Test (macOS) + working-directory: packages/celest_core/example + run: flutter test -d macos integration_test/secure_storage_test.dart + test_flutter_android: + needs: analyze_and_format + runs-on: linux + timeout-minutes: 15 + steps: + - name: Git Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # 4.1.1 + - name: Setup Flutter + uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # 2.13.0 + with: + cache: true + - name: Get Packages + working-directory: packages/celest_core/example + run: flutter pub get + - name: Test (Android) uses: aws-amplify/amplify-flutter/.github/composite_actions/launch_android_emulator@main with: - api-level: 34 + # Matches `package:jni` compileSdkVersion + # https://github.com/dart-lang/native/blob/001910c9f40d637cb25c19bb500fb89cebdf7450/pkgs/jni/android/build.gradle#L57C23-L57C25 + api-level: 31 + arch: x86_64 script: | cd packages/celest_core/example - for OS in sdk iPhone macos - do - flutter test -d $OS integration_test/secure_storage_test.dart - done + flutter test -d sdk integration_test/secure_storage_test.dart diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 290fa83f..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "files.associations": { - "__locale": "cpp", - "locale": "cpp" - } -} \ No newline at end of file diff --git a/packages/celest_core/CHANGELOG.md b/packages/celest_core/CHANGELOG.md index f1399e1f..11aef13b 100644 --- a/packages/celest_core/CHANGELOG.md +++ b/packages/celest_core/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.2.2-wip -- Adds `Keychain` interface for secure storage of sensitive data. +- Adds `SecureStorage` interface for storage of sensitive data in the platform keychain. ## 0.2.1 diff --git a/packages/celest_core/android/src/main/kotlin/dev/celest/celest_core/CelestSecureStorage.kt b/packages/celest_core/android/src/main/kotlin/dev/celest/celest_core/CelestSecureStorage.kt index 1aa4a3f4..cb95e425 100644 --- a/packages/celest_core/android/src/main/kotlin/dev/celest/celest_core/CelestSecureStorage.kt +++ b/packages/celest_core/android/src/main/kotlin/dev/celest/celest_core/CelestSecureStorage.kt @@ -38,7 +38,7 @@ class CelestSecureStorage(private val mainActivity: Activity, private val scope: } } - fun read(dataKey: String): String? = sharedPreferences.getString(dataKey, null) + fun read(dataKey: String): String? = sharedPreferences. fun delete(dataKey: String): String? { val current = read(dataKey) diff --git a/packages/celest_core/example/integration_test/secure_storage_shared.dart b/packages/celest_core/example/integration_test/secure_storage_shared.dart index fe7e8a49..cdf4f1b1 100644 --- a/packages/celest_core/example/integration_test/secure_storage_shared.dart +++ b/packages/celest_core/example/integration_test/secure_storage_shared.dart @@ -51,14 +51,36 @@ void sharedTests() { }); test('can delete a non-existent key', () { + expect(storage.read(key), isNull); expect(() => storage.delete(key), returnsNormally); - expect(() => storage.delete(key), returnsNormally); - expect(() => storage.delete(key), returnsNormally); }); }); - group('read/write/delete can handle key value pairs of varying length', () { - for (final (length, s) in largeKeyValuePairs) { + group('clear', () { + const key1 = 'key1'; + const key2 = 'key2'; + const value1 = 'value1'; + const value2 = 'value2'; + + test('removes all keys from storage', () { + storage.write(key1, value1); + storage.write(key2, value2); + expect(storage.read(key1), value1); + expect(storage.read(key2), value2); + + storage.clear(); + + expect(storage.read(key1), isNull, reason: 'Storage was cleared'); + expect(storage.read(key2), isNull, reason: 'Storage was cleared'); + }); + + test('does not throw when no items present', () { + expect(storage.clear, returnsNormally); + }); + }); + + group('large values', () { + for (final (length, s) in _largeKeyValuePairs) { test('can store key/value with length $length', () { storage.write(s, s); expect(storage.read(s), s, reason: 'Value was written'); @@ -72,7 +94,7 @@ void sharedTests() { } final _random = Random(); -Iterable<(int, String)> get largeKeyValuePairs sync* { +Iterable<(int, String)> get _largeKeyValuePairs sync* { for (final length in const [100, 1000, 10000]) { final string = String.fromCharCodes( List.generate(length, (_) => _random.nextInt(255) + 1), diff --git a/packages/celest_core/lib/src/secure_storage/secure_storage.android.dart b/packages/celest_core/lib/src/secure_storage/secure_storage.android.dart index a9b0c3df..7db250a4 100644 --- a/packages/celest_core/lib/src/secure_storage/secure_storage.android.dart +++ b/packages/celest_core/lib/src/secure_storage/secure_storage.android.dart @@ -28,8 +28,13 @@ final class SecureStoragePlatformAndroid extends SecureStoragePlatform { } @override - String? read(String key) => - _secureStorage.read(key.toJString()).toDartString(); + String? read(String key) { + final value = _secureStorage.read(key.toJString()); + if (value.isNull) { + return null; + } + return value.toDartString(); + } @override String write(String key, String value) { diff --git a/packages/celest_core/test/secure_storage/secure_storage_darwin_test.dart b/packages/celest_core/test/secure_storage/secure_storage_darwin_test.dart index 4137b3ea..0a3e1197 100644 --- a/packages/celest_core/test/secure_storage/secure_storage_darwin_test.dart +++ b/packages/celest_core/test/secure_storage/secure_storage_darwin_test.dart @@ -1,52 +1,10 @@ @TestOn('mac-os') import 'package:celest_core/src/native/darwin/security.ffi.dart'; -import 'package:celest_core/src/secure_storage/secure_storage.dart'; import 'package:celest_core/src/secure_storage/secure_storage.darwin.dart'; import 'package:test/test.dart'; -const key1 = 'key1'; -const key2 = 'key2'; -const value1 = 'value1'; -const value2 = 'value2'; - void main() { - group('SecureStorage', () { - group('macos', () { - group('clear', () { - final storage = SecureStorage(scope: 'clear'); - - setUp(() { - storage.clear(); - }); - - tearDown(() { - storage.clear(); - }); - - test('removes all keys from storage', () { - // seed storage and confirm values are present - storage - ..write(key1, value1) - ..write(key2, value2); - expect(storage.read(key1), value1); - expect(storage.read(key2), value2); - - // remove all - storage.clear(); - - // assert all data was removed - expect(storage.read(key1), isNull); - expect(storage.read(key2), isNull); - }); - - test('does not throw when no items present', () { - expect(storage.clear, returnsNormally); - }); - }); - }); - }); - group('SecurityFrameworkException', () { test('errSecInvalidOwnerEdit', () { final error = SecurityFrameworkException.fromStatus( diff --git a/packages/celest_core/test/secure_storage/secure_storage_test.dart b/packages/celest_core/test/secure_storage/secure_storage_test.dart index 3fc45291..581b6be9 100644 --- a/packages/celest_core/test/secure_storage/secure_storage_test.dart +++ b/packages/celest_core/test/secure_storage/secure_storage_test.dart @@ -1,5 +1,3 @@ import '../../example/integration_test/secure_storage_shared.dart'; -void main() { - sharedTests(); -} +void main() => sharedTests(); From 6b1af1d770cc35d3335e61c55fb9063a4950ec84 Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 13:56:28 -0800 Subject: [PATCH 07/14] fix workflow --- .github/workflows/celest_core.yaml | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index 419ffaa5..2e253db0 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -31,24 +31,8 @@ jobs: - name: Format working-directory: packages/celest_core run: dart format --set-exit-if-changed . - test_dart: - needs: analyze_and_format - runs-on: ubuntu-latest - timeout-minutes: 5 - steps: - - name: Git Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # 4.1.1 - - name: Setup Flutter - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # 2.13.0 - with: cache: true - - name: Get Packages - working-directory: packages/celest_core - run: dart pub get - - name: Test - working-directory: packages/celest_core - run: dart test - test_flutter_darwin: + test_darwin: needs: analyze_and_format runs-on: macos-13-large timeout-minutes: 10 @@ -70,15 +54,18 @@ jobs: run: flutter pub get - name: Setup iOS Simulator uses: aws-amplify/amplify-flutter/.github/composite_actions/launch_ios_simulator@main + with: + ios-version: 17 - name: Test (iOS) working-directory: packages/celest_core/example run: flutter test -d iPhone integration_test/secure_storage_test.dart - name: Test (macOS) working-directory: packages/celest_core/example run: flutter test -d macos integration_test/secure_storage_test.dart - test_flutter_android: + test_android: needs: analyze_and_format - runs-on: linux + runs-on: + labels: linux timeout-minutes: 15 steps: - name: Git Checkout From 43a99952ebd931f1222442208167ab7ab5126068 Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 13:57:31 -0800 Subject: [PATCH 08/14] fix workflow --- .github/workflows/celest_core.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index 2e253db0..9d465c78 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -31,7 +31,6 @@ jobs: - name: Format working-directory: packages/celest_core run: dart format --set-exit-if-changed . - cache: true test_darwin: needs: analyze_and_format runs-on: macos-13-large From f5916610facb79d89d165c37bc509cd1fead5dce Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 14:01:56 -0800 Subject: [PATCH 09/14] fix workflow --- .github/workflows/celest_core.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index 9d465c78..f8377096 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -57,13 +57,14 @@ jobs: ios-version: 17 - name: Test (iOS) working-directory: packages/celest_core/example - run: flutter test -d iPhone integration_test/secure_storage_test.dart + run: flutter test -d test integration_test/secure_storage_test.dart - name: Test (macOS) working-directory: packages/celest_core/example run: flutter test -d macos integration_test/secure_storage_test.dart test_android: needs: analyze_and_format runs-on: + group: public labels: linux timeout-minutes: 15 steps: From 3ae144ed67133ca24da479967351aa9419f61cbb Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 14:14:39 -0800 Subject: [PATCH 10/14] fix workflow --- .github/workflows/celest_core.yaml | 16 ++++++++++------ .../celest/celest_core/CelestSecureStorage.kt | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index f8377096..fe3aedfd 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -33,8 +33,8 @@ jobs: run: dart format --set-exit-if-changed . test_darwin: needs: analyze_and_format - runs-on: macos-13-large - timeout-minutes: 10 + runs-on: macos-latest-xlarge + timeout-minutes: 20 steps: - name: Git Checkout uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # 4.1.1 @@ -52,9 +52,13 @@ jobs: working-directory: packages/celest_core/example run: flutter pub get - name: Setup iOS Simulator - uses: aws-amplify/amplify-flutter/.github/composite_actions/launch_ios_simulator@main - with: - ios-version: 17 + run: | + RUNTIME=$(xcrun simctl list runtimes | grep 17 | tail -n 1 | cut -d' ' -f 7) + echo "Using runtime: $RUNTIME" + xcrun simctl create ios 'iPhone 15 Pro Max' $RUNTIME + echo "Booting simulator" + xcrun simctl boot ios + echo "Booted simulator" - name: Test (iOS) working-directory: packages/celest_core/example run: flutter test -d test integration_test/secure_storage_test.dart @@ -78,7 +82,7 @@ jobs: working-directory: packages/celest_core/example run: flutter pub get - name: Test (Android) - uses: aws-amplify/amplify-flutter/.github/composite_actions/launch_android_emulator@main + uses: ReactiveCircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 # 2.30.1 with: # Matches `package:jni` compileSdkVersion # https://github.com/dart-lang/native/blob/001910c9f40d637cb25c19bb500fb89cebdf7450/pkgs/jni/android/build.gradle#L57C23-L57C25 diff --git a/packages/celest_core/android/src/main/kotlin/dev/celest/celest_core/CelestSecureStorage.kt b/packages/celest_core/android/src/main/kotlin/dev/celest/celest_core/CelestSecureStorage.kt index cb95e425..1aa4a3f4 100644 --- a/packages/celest_core/android/src/main/kotlin/dev/celest/celest_core/CelestSecureStorage.kt +++ b/packages/celest_core/android/src/main/kotlin/dev/celest/celest_core/CelestSecureStorage.kt @@ -38,7 +38,7 @@ class CelestSecureStorage(private val mainActivity: Activity, private val scope: } } - fun read(dataKey: String): String? = sharedPreferences. + fun read(dataKey: String): String? = sharedPreferences.getString(dataKey, null) fun delete(dataKey: String): String? { val current = read(dataKey) From 038022c3f1df4c0c325e10920a6a51c3ff5379a6 Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 14:23:33 -0800 Subject: [PATCH 11/14] fix workflow --- .gitattributes | 57 +++++++++++++++++++ .github/workflows/celest_core.yaml | 7 ++- .../src/secure_storage/secure_storage.dart | 1 - .../secure_storage_platform.vm.dart | 3 - .../secure_storage_platform.web.dart | 3 - 5 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..c92f9b4f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,57 @@ +## GITATTRIBUTES +# +# Details per file setting: +# text These files should be normalized (i.e. convert CRLF to LF). +# binary These files are binary and should be left untouched. +# +# Reference: https://git-scm.com/docs/gitattributes +# GitHub Linguist: https://github.com/github-linguist/linguist/blob/master/docs/overrides.md +###################################################################### + +# Auto detect text files and perform LF normalization +* text=auto + +# Always perform LF normalization +*.dart text +*.gradle text +*.go text +*.html text +*.java text +*.js text +*.json text linguist-language=JSON-with-Comments +*.md text +*.sh text +*.ts text +*.txt text +*.xml text +*.yaml text + +# Make sure that these Windows files always have CRLF line endings at checkout +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf +*.rc text eol=crlf +*.sln text eol=crlf +*.props text eol=crlf +*.vcxproj text eol=crlf +*.vcxproj.filters text eol=crlf +# Including templates +*.sln.tmpl text eol=crlf +*.props.tmpl text eol=crlf +*.vcxproj.tmpl text eol=crlf + +## Platform files generated by Flutter during `flutter create` +**/example/android/** linguist-generated +**/example/ios/** linguist-generated +**/example/linux/** linguist-generated +**/example/macos/** linguist-generated +**/example/windows/** linguist-generated +## Exclude flutter generated web files without excluding web files from +## non-flutter dart example apps +**/example/web/icons/** linguist-generated +**/example/web/*.json linguist-generated +**/example/web/*.png linguist-generated + +## Generated Dart files +**/*.g.dart linguist-generated +**/*.ffi.dart linguist-generated diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index fe3aedfd..cc00bc06 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -53,7 +53,7 @@ jobs: run: flutter pub get - name: Setup iOS Simulator run: | - RUNTIME=$(xcrun simctl list runtimes | grep 17 | tail -n 1 | cut -d' ' -f 7) + RUNTIME=$(xcrun simctl list runtimes | grep 'iOS 17' | tail -n 1 | cut -d' ' -f 7) echo "Using runtime: $RUNTIME" xcrun simctl create ios 'iPhone 15 Pro Max' $RUNTIME echo "Booting simulator" @@ -81,6 +81,11 @@ jobs: - name: Get Packages working-directory: packages/celest_core/example run: flutter pub get + - name: Enable KVM + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm - name: Test (Android) uses: ReactiveCircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 # 2.30.1 with: diff --git a/packages/celest_core/lib/src/secure_storage/secure_storage.dart b/packages/celest_core/lib/src/secure_storage/secure_storage.dart index 55400f14..e90ac9bb 100644 --- a/packages/celest_core/lib/src/secure_storage/secure_storage.dart +++ b/packages/celest_core/lib/src/secure_storage/secure_storage.dart @@ -4,7 +4,6 @@ import 'package:celest_core/src/secure_storage/secure_storage_platform.vm.dart' abstract interface class SecureStorage { factory SecureStorage({String? scope}) = SecureStoragePlatform; - void init() {} String? read(String key); String write(String key, String value); String? delete(String key); diff --git a/packages/celest_core/lib/src/secure_storage/secure_storage_platform.vm.dart b/packages/celest_core/lib/src/secure_storage/secure_storage_platform.vm.dart index 3ad26930..5b5d63db 100644 --- a/packages/celest_core/lib/src/secure_storage/secure_storage_platform.vm.dart +++ b/packages/celest_core/lib/src/secure_storage/secure_storage_platform.vm.dart @@ -20,9 +20,6 @@ abstract base class SecureStoragePlatform implements SecureStorage { static const _defaultScope = 'dev.celest.celest'; - @override - void init() {} - @protected const SecureStoragePlatform.base(); } diff --git a/packages/celest_core/lib/src/secure_storage/secure_storage_platform.web.dart b/packages/celest_core/lib/src/secure_storage/secure_storage_platform.web.dart index 76773183..a657e936 100644 --- a/packages/celest_core/lib/src/secure_storage/secure_storage_platform.web.dart +++ b/packages/celest_core/lib/src/secure_storage/secure_storage_platform.web.dart @@ -10,9 +10,6 @@ abstract base class SecureStoragePlatform implements SecureStorage { static const _defaultScope = 'dev.celest.celest'; - @override - void init() {} - @protected const SecureStoragePlatform.base(); } From 46a8f178b978f52a8e9af34c5e14eaed98671f65 Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 14:26:17 -0800 Subject: [PATCH 12/14] fix workflow --- .github/workflows/celest_core.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index cc00bc06..c48bc30b 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -61,7 +61,7 @@ jobs: echo "Booted simulator" - name: Test (iOS) working-directory: packages/celest_core/example - run: flutter test -d test integration_test/secure_storage_test.dart + run: flutter test -d ios integration_test/secure_storage_test.dart - name: Test (macOS) working-directory: packages/celest_core/example run: flutter test -d macos integration_test/secure_storage_test.dart From 4e1f094bd65f12a4fbaef352a49df35b1112cc9d Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 14:32:54 -0800 Subject: [PATCH 13/14] fix workflow --- .github/workflows/celest_core.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index c48bc30b..dc9a8e61 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -93,6 +93,4 @@ jobs: # https://github.com/dart-lang/native/blob/001910c9f40d637cb25c19bb500fb89cebdf7450/pkgs/jni/android/build.gradle#L57C23-L57C25 api-level: 31 arch: x86_64 - script: | - cd packages/celest_core/example - flutter test -d sdk integration_test/secure_storage_test.dart + script: cd packages/celest_core/example && flutter test -d sdk integration_test/secure_storage_test.dart From 678e9973bb5caa6a3dcd7e9ea71b6394702d4761 Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Wed, 6 Mar 2024 14:36:50 -0800 Subject: [PATCH 14/14] fix workflow --- .github/workflows/celest_core.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/celest_core.yaml b/.github/workflows/celest_core.yaml index dc9a8e61..589ce335 100644 --- a/.github/workflows/celest_core.yaml +++ b/.github/workflows/celest_core.yaml @@ -93,4 +93,4 @@ jobs: # https://github.com/dart-lang/native/blob/001910c9f40d637cb25c19bb500fb89cebdf7450/pkgs/jni/android/build.gradle#L57C23-L57C25 api-level: 31 arch: x86_64 - script: cd packages/celest_core/example && flutter test -d sdk integration_test/secure_storage_test.dart + script: cd packages/celest_core/example && flutter test -d emulator integration_test/secure_storage_test.dart