From 11188c5a99223ace1bc9132d74c2b5c7af26313f Mon Sep 17 00:00:00 2001 From: ujizin Date: Sat, 14 Oct 2023 08:20:24 -0300 Subject: [PATCH] wip kmm --- .github/ISSUE_TEMPLATE/bug_report.md | 0 .github/ISSUE_TEMPLATE/feature_request.md | 0 .github/workflows/android_test.yml | 0 .github/workflows/build.yml | 0 .github/workflows/documentation.yml | 0 .gitignore | 0 License | 0 README.md | 0 build.gradle.kts | 7 +- buildSrc/build.gradle.kts | 0 .../src/main/kotlin/ujizin/camposer/Config.kt | 4 +- camposer/.gitignore | 0 camposer/build.gradle.kts | 99 ++++++--- camposer/consumer-rules.pro | 0 camposer/proguard-rules.pro | 0 .../{main => androidMain}/AndroidManifest.xml | 0 .../com/ujizin/camposer/CameraPreview.kt | 95 +++------ .../com/ujizin/camposer/LifecycleState.kt | 0 .../extensions/CameraStateExtensions.kt | 0 .../camposer/extensions/ContextExtensions.kt | 0 .../camposer/extensions/FloatExtensions.kt | 0 .../extensions/PreviewViewExtensions.kt | 0 .../com/ujizin/camposer/state/CamSelector.kt | 11 +- .../ujizin/camposer/state/CameraAsState.kt | 2 +- .../com/ujizin/camposer/state/CameraState.kt | 58 +++--- .../com/ujizin/camposer/state/CaptureMode.kt | 2 +- .../com/ujizin/camposer/state/FlashMode.kt | 11 +- .../ImageAnalysisBackpressureStrategy.kt | 2 +- .../ujizin/camposer/state/ImageAnalyzer.kt | 2 +- .../ujizin/camposer/state/ImageCaptureMode.kt | 2 +- .../camposer/state/ImageCaptureResult.kt | 0 .../ujizin/camposer/state/ImageTargetSize.kt | 2 +- .../camposer/state/ImplementationMode.kt | 14 ++ .../camposer/state/PinchToZoomGesture.kt | 2 +- .../com/ujizin/camposer/state/ScaleType.kt | 2 +- .../camposer/state/VideoCaptureResult.kt | 0 .../com/ujizin/camposer/CameraPreview.kt | 75 +++++++ .../com/ujizin/camposer/focus/CornerBorder.kt | 0 .../com/ujizin/camposer/focus/FocusTap.kt | 0 .../com/ujizin/camposer/state/CamSelector.kt | 15 ++ .../ujizin/camposer/state/CameraAsState.kt | 10 + .../com/ujizin/camposer/state/CameraState.kt | 69 +++++++ .../com/ujizin/camposer/state/CaptureMode.kt | 10 + .../ujizin/camposer/state/ConditionalState.kt | 0 .../com/ujizin/camposer/state/FlashMode.kt | 14 ++ .../ImageAnalysisBackpressureStrategy.kt | 3 + .../ujizin/camposer/state/ImageAnalyzer.kt | 3 + .../ujizin/camposer/state/ImageCaptureMode.kt | 7 + .../ujizin/camposer/state/ImageTargetSize.kt | 3 + .../camposer/state/ImplementationMode.kt | 15 ++ .../camposer/state/PinchToZoomGesture.kt | 3 + .../com/ujizin/camposer/state/ScaleType.kt | 13 ++ .../AndroidManifest.xml | 0 .../com/ujizin/camposer/CamSelectorTest.kt | 0 .../kotlin}/com/ujizin/camposer/CameraTest.kt | 0 .../com/ujizin/camposer/CaptureModeTest.kt | 0 .../camposer/ExposureCompensationTest.kt | 0 .../com/ujizin/camposer/FlashModeTest.kt | 0 .../com/ujizin/camposer/FocusOnTapTest.kt | 0 .../com/ujizin/camposer/ImageAnalyzerTest.kt | 0 .../ujizin/camposer/ImageCaptureModeTest.kt | 0 .../camposer/ImageCaptureTargetSizeTest.kt | 0 .../ujizin/camposer/ImplementationModeTest.kt | 0 .../com/ujizin/camposer/ScaleTypeTest.kt | 0 .../kotlin}/com/ujizin/camposer/TorchTest.kt | 0 .../com/ujizin/camposer/ZoomRatioTest.kt | 0 .../com/ujizin/camposer/CameraPreview.kt | 88 ++++++++ .../extensions/AVCaptureExtensions.kt | 19 ++ .../camposer/mapper/CameraFlashModeMapper.kt | 20 ++ .../camposer/mapper/CameraSelectorMapper.kt | 26 +++ .../com/ujizin/camposer/state/CamSelector.kt | 6 + .../ujizin/camposer/state/CameraAsState.kt | 9 + .../com/ujizin/camposer/state/CameraState.kt | 195 ++++++++++++++++++ .../com/ujizin/camposer/state/CaptureMode.kt | 10 + .../com/ujizin/camposer/state/FlashMode.kt | 5 + .../ImageAnalysisBackpressureStrategy.kt | 3 + .../ujizin/camposer/state/ImageAnalyzer.kt | 5 + .../ujizin/camposer/state/ImageCaptureMode.kt | 7 + .../ujizin/camposer/state/ImageTargetSize.kt | 3 + .../camposer/state/ImplementationMode.kt | 6 + .../camposer/state/PinchToZoomGesture.kt | 3 + .../com/ujizin/camposer/state/ScaleType.kt | 14 ++ .../camposer/state/ImplementationMode.kt | 23 --- gradle.properties | 16 +- gradle/libs.versions.toml | 11 +- gradle/wrapper/gradle-wrapper.jar | Bin gradle/wrapper/gradle-wrapper.properties | 0 gradlew | 0 gradlew.bat | 0 iosArm64Main | 1 + multiplatformSample/build.gradle.kts | 69 +++++++ .../src/androidMain/AndroidManifest.xml | 25 +++ .../ujizin/multiplatform_sample/Permission.kt | 40 ++++ .../multiplatform_sample/CameraScreen.kt | 21 ++ .../MainViewController.kt | 9 + .../ujizin/multiplatform_sample/Permission.kt | 23 +++ sample/.gitignore | 0 sample/README.md | 0 sample/build.gradle.kts | 9 +- sample/proguard-rules.pro | 0 sample/src/main/AndroidManifest.xml | 0 sample/src/main/ic_launcher-playstore.png | Bin .../java/com/ujizin/sample/CamposerTheme.kt | 0 .../java/com/ujizin/sample/MainActivity.kt | 10 +- .../com/ujizin/sample/SampleApplication.kt | 0 .../com/ujizin/sample/components/Section.kt | 0 .../java/com/ujizin/sample/data/local/User.kt | 0 .../com/ujizin/sample/data/local/UserStore.kt | 0 .../data/local/datasource/FileDataSource.kt | 0 .../data/local/datasource/UserDataSource.kt | 0 .../ujizin/sample/data/mapper/UserMapper.kt | 0 .../main/java/com/ujizin/sample/di/Modules.kt | 0 .../java/com/ujizin/sample/domain/User.kt | 0 .../sample/extensions/FileExtensions.kt | 0 .../sample/extensions/FloatExtensions.kt | 0 .../ujizin/sample/extensions/IntExtensions.kt | 0 .../sample/extensions/LifecycleExtensions.kt | 0 .../sample/extensions/ModifierExtensions.kt | 0 .../sample/extensions/ReaderExtensions.kt | 0 .../sample/extensions/StringExtensions.kt | 0 .../sample/feature/camera/CameraScreen.kt | 5 +- .../sample/feature/camera/CameraViewModel.kt | 0 .../feature/camera/components/ActionsBox.kt | 0 .../camera/components/BlinkPictureBox.kt | 0 .../feature/camera/components/Button.kt | 0 .../camera/components/ConfigurationSection.kt | 0 .../feature/camera/components/FlashSection.kt | 0 .../camera/components/OptionSection.kt | 0 .../camera/components/PictureActions.kt | 0 .../feature/camera/components/QrCodeBox.kt | 0 .../feature/camera/components/SettingsBox.kt | 0 .../feature/camera/components/VideoBox.kt | 0 .../feature/camera/mapper/FlashMapper.kt | 0 .../feature/camera/model/CameraOption.kt | 0 .../sample/feature/camera/model/Flash.kt | 0 .../configuration/ConfigurationScreen.kt | 0 .../configuration/ConfigurationViewModel.kt | 0 .../sample/feature/gallery/GalleryScreen.kt | 0 .../feature/gallery/GalleryViewModel.kt | 0 .../feature/permission/AppPermission.kt | 0 .../sample/feature/preview/PreviewScreen.kt | 0 .../feature/preview/PreviewViewModel.kt | 0 .../java/com/ujizin/sample/router/Args.kt | 0 .../java/com/ujizin/sample/router/Router.kt | 0 .../ujizin/sample/router/RouterExtensions.kt | 0 .../src/main/res/drawable/configuration.xml | 0 sample/src/main/res/drawable/flash_always.xml | 0 sample/src/main/res/drawable/flash_auto.xml | 0 sample/src/main/res/drawable/flash_off.xml | 0 sample/src/main/res/drawable/flash_on.xml | 0 sample/src/main/res/drawable/refresh.xml | 0 .../res/mipmap-anydpi-v26/ic_launcher.xml | 0 .../mipmap-anydpi-v26/ic_launcher_round.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin .../mipmap-hdpi/ic_launcher_foreground.png | Bin .../res/mipmap-hdpi/ic_launcher_round.png | Bin .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin .../mipmap-mdpi/ic_launcher_foreground.png | Bin .../res/mipmap-mdpi/ic_launcher_round.png | Bin .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin .../mipmap-xhdpi/ic_launcher_foreground.png | Bin .../res/mipmap-xhdpi/ic_launcher_round.png | Bin .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin sample/src/main/res/values-night/themes.xml | 0 sample/src/main/res/values/colors.xml | 0 .../res/values/ic_launcher_background.xml | 0 sample/src/main/res/values/strings.xml | 0 sample/src/main/res/values/themes.xml | 0 sample/src/main/res/xml/backup_rules.xml | 0 .../main/res/xml/data_extraction_rules.xml | 0 .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 13 ++ .../sampleIos/Assets.xcassets/Contents.json | 6 + .../Preview Assets.xcassets/Contents.json | 6 + scripts/publish-module.gradle | 0 scripts/publish-root.gradle | 0 settings.gradle.kts | 33 ++- 182 files changed, 1111 insertions(+), 194 deletions(-) mode change 100644 => 100755 .github/ISSUE_TEMPLATE/bug_report.md mode change 100644 => 100755 .github/ISSUE_TEMPLATE/feature_request.md mode change 100644 => 100755 .github/workflows/android_test.yml mode change 100644 => 100755 .github/workflows/build.yml mode change 100644 => 100755 .github/workflows/documentation.yml mode change 100644 => 100755 .gitignore mode change 100644 => 100755 License mode change 100644 => 100755 README.md mode change 100644 => 100755 build.gradle.kts mode change 100644 => 100755 buildSrc/build.gradle.kts mode change 100644 => 100755 buildSrc/src/main/kotlin/ujizin/camposer/Config.kt mode change 100644 => 100755 camposer/.gitignore mode change 100644 => 100755 camposer/build.gradle.kts mode change 100644 => 100755 camposer/consumer-rules.pro mode change 100644 => 100755 camposer/proguard-rules.pro rename camposer/src/{main => androidMain}/AndroidManifest.xml (100%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/CameraPreview.kt (65%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/LifecycleState.kt (100%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/extensions/CameraStateExtensions.kt (100%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/extensions/ContextExtensions.kt (100%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/extensions/FloatExtensions.kt (100%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/extensions/PreviewViewExtensions.kt (100%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/CamSelector.kt (80%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/CameraAsState.kt (97%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/CameraState.kt (90%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/CaptureMode.kt (88%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/FlashMode.kt (63%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt (90%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/ImageAnalyzer.kt (98%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/ImageCaptureMode.kt (86%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/ImageCaptureResult.kt (100%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/ImageTargetSize.kt (97%) mode change 100644 => 100755 create mode 100755 camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImplementationMode.kt rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/PinchToZoomGesture.kt (88%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/ScaleType.kt (86%) mode change 100644 => 100755 rename camposer/src/{main/java => androidMain/kotlin}/com/ujizin/camposer/state/VideoCaptureResult.kt (100%) mode change 100644 => 100755 create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/CameraPreview.kt rename camposer/src/{main/java => commonMain/kotlin}/com/ujizin/camposer/focus/CornerBorder.kt (100%) mode change 100644 => 100755 rename camposer/src/{main/java => commonMain/kotlin}/com/ujizin/camposer/focus/FocusTap.kt (100%) mode change 100644 => 100755 create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CamSelector.kt create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CameraAsState.kt create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CameraState.kt create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CaptureMode.kt rename camposer/src/{main/java => commonMain/kotlin}/com/ujizin/camposer/state/ConditionalState.kt (100%) mode change 100644 => 100755 create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/state/FlashMode.kt create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageAnalyzer.kt create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageCaptureMode.kt create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageTargetSize.kt create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImplementationMode.kt create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/state/PinchToZoomGesture.kt create mode 100755 camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ScaleType.kt rename camposer/src/{androidTest => commonTest}/AndroidManifest.xml (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/CamSelectorTest.kt (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/CameraTest.kt (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/CaptureModeTest.kt (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/ExposureCompensationTest.kt (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/FlashModeTest.kt (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/FocusOnTapTest.kt (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/ImageAnalyzerTest.kt (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/ImageCaptureModeTest.kt (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/ImageCaptureTargetSizeTest.kt (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/ImplementationModeTest.kt (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/ScaleTypeTest.kt (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/TorchTest.kt (100%) mode change 100644 => 100755 rename camposer/src/{androidTest/java => commonTest/kotlin}/com/ujizin/camposer/ZoomRatioTest.kt (100%) mode change 100644 => 100755 create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/CameraPreview.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/extensions/AVCaptureExtensions.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/mapper/CameraFlashModeMapper.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/mapper/CameraSelectorMapper.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CamSelector.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CameraAsState.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CameraState.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CaptureMode.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/state/FlashMode.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageAnalyzer.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageCaptureMode.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageTargetSize.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImplementationMode.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/state/PinchToZoomGesture.kt create mode 100755 camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ScaleType.kt delete mode 100644 camposer/src/main/java/com/ujizin/camposer/state/ImplementationMode.kt mode change 100644 => 100755 gradle.properties mode change 100644 => 100755 gradle/libs.versions.toml mode change 100644 => 100755 gradle/wrapper/gradle-wrapper.jar mode change 100644 => 100755 gradle/wrapper/gradle-wrapper.properties mode change 100644 => 100755 gradlew mode change 100644 => 100755 gradlew.bat create mode 120000 iosArm64Main create mode 100755 multiplatformSample/build.gradle.kts create mode 100755 multiplatformSample/src/androidMain/AndroidManifest.xml create mode 100755 multiplatformSample/src/androidMain/kotlin/com/ujizin/multiplatform_sample/Permission.kt create mode 100755 multiplatformSample/src/commonMain/kotlin/com/ujizin/multiplatform_sample/CameraScreen.kt create mode 100755 multiplatformSample/src/iosMain/kotlin/com/ujizin/multiplatform_sample/MainViewController.kt create mode 100755 multiplatformSample/src/iosMain/kotlin/com/ujizin/multiplatform_sample/Permission.kt mode change 100644 => 100755 sample/.gitignore mode change 100644 => 100755 sample/README.md mode change 100644 => 100755 sample/build.gradle.kts mode change 100644 => 100755 sample/proguard-rules.pro mode change 100644 => 100755 sample/src/main/AndroidManifest.xml mode change 100644 => 100755 sample/src/main/ic_launcher-playstore.png mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/CamposerTheme.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/MainActivity.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/SampleApplication.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/components/Section.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/data/local/User.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/data/local/UserStore.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/data/local/datasource/FileDataSource.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/data/local/datasource/UserDataSource.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/data/mapper/UserMapper.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/di/Modules.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/domain/User.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/extensions/FileExtensions.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/extensions/FloatExtensions.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/extensions/IntExtensions.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/extensions/LifecycleExtensions.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/extensions/ModifierExtensions.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/extensions/ReaderExtensions.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/extensions/StringExtensions.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/CameraScreen.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/CameraViewModel.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/components/ActionsBox.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/components/BlinkPictureBox.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/components/Button.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/components/ConfigurationSection.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/components/FlashSection.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/components/OptionSection.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/components/PictureActions.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/components/QrCodeBox.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/components/SettingsBox.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/components/VideoBox.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/mapper/FlashMapper.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/model/CameraOption.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/camera/model/Flash.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/configuration/ConfigurationScreen.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/configuration/ConfigurationViewModel.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/gallery/GalleryScreen.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/gallery/GalleryViewModel.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/permission/AppPermission.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/preview/PreviewScreen.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/feature/preview/PreviewViewModel.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/router/Args.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/router/Router.kt mode change 100644 => 100755 sample/src/main/java/com/ujizin/sample/router/RouterExtensions.kt mode change 100644 => 100755 sample/src/main/res/drawable/configuration.xml mode change 100644 => 100755 sample/src/main/res/drawable/flash_always.xml mode change 100644 => 100755 sample/src/main/res/drawable/flash_auto.xml mode change 100644 => 100755 sample/src/main/res/drawable/flash_off.xml mode change 100644 => 100755 sample/src/main/res/drawable/flash_on.xml mode change 100644 => 100755 sample/src/main/res/drawable/refresh.xml mode change 100644 => 100755 sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml mode change 100644 => 100755 sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml mode change 100644 => 100755 sample/src/main/res/mipmap-hdpi/ic_launcher.png mode change 100644 => 100755 sample/src/main/res/mipmap-hdpi/ic_launcher_foreground.png mode change 100644 => 100755 sample/src/main/res/mipmap-hdpi/ic_launcher_round.png mode change 100644 => 100755 sample/src/main/res/mipmap-mdpi/ic_launcher.png mode change 100644 => 100755 sample/src/main/res/mipmap-mdpi/ic_launcher_foreground.png mode change 100644 => 100755 sample/src/main/res/mipmap-mdpi/ic_launcher_round.png mode change 100644 => 100755 sample/src/main/res/mipmap-xhdpi/ic_launcher.png mode change 100644 => 100755 sample/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png mode change 100644 => 100755 sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png mode change 100644 => 100755 sample/src/main/res/mipmap-xxhdpi/ic_launcher.png mode change 100644 => 100755 sample/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png mode change 100644 => 100755 sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png mode change 100644 => 100755 sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png mode change 100644 => 100755 sample/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png mode change 100644 => 100755 sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png mode change 100644 => 100755 sample/src/main/res/values-night/themes.xml mode change 100644 => 100755 sample/src/main/res/values/colors.xml mode change 100644 => 100755 sample/src/main/res/values/ic_launcher_background.xml mode change 100644 => 100755 sample/src/main/res/values/strings.xml mode change 100644 => 100755 sample/src/main/res/values/themes.xml mode change 100644 => 100755 sample/src/main/res/xml/backup_rules.xml mode change 100644 => 100755 sample/src/main/res/xml/data_extraction_rules.xml create mode 100755 sampleIos/sampleIos/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100755 sampleIos/sampleIos/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100755 sampleIos/sampleIos/Assets.xcassets/Contents.json create mode 100755 sampleIos/sampleIos/Preview Content/Preview Assets.xcassets/Contents.json mode change 100644 => 100755 scripts/publish-module.gradle mode change 100644 => 100755 scripts/publish-root.gradle mode change 100644 => 100755 settings.gradle.kts diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md old mode 100644 new mode 100755 diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md old mode 100644 new mode 100755 diff --git a/.github/workflows/android_test.yml b/.github/workflows/android_test.yml old mode 100644 new mode 100755 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml old mode 100644 new mode 100755 diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml old mode 100644 new mode 100755 diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/License b/License old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/build.gradle.kts b/build.gradle.kts old mode 100644 new mode 100755 index 6ab3638..65c1231 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,9 +3,12 @@ plugins { alias(libs.plugins.application) apply false alias(libs.plugins.library) apply false alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.multiplatform) apply false alias(libs.plugins.gradle.nexus) alias(libs.plugins.kotlin.serialization) - alias(libs.plugins.dokka) +// alias(libs.plugins.dokka) + alias(libs.plugins.multiplatform.compose) } -apply(from = "${rootDir}/scripts/publish-root.gradle") \ No newline at end of file +apply(from = "${rootDir}/scripts/publish-root.gradle") + diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts old mode 100644 new mode 100755 diff --git a/buildSrc/src/main/kotlin/ujizin/camposer/Config.kt b/buildSrc/src/main/kotlin/ujizin/camposer/Config.kt old mode 100644 new mode 100755 index 7b5a018..a49a5b0 --- a/buildSrc/src/main/kotlin/ujizin/camposer/Config.kt +++ b/buildSrc/src/main/kotlin/ujizin/camposer/Config.kt @@ -1,8 +1,8 @@ package com.ujizin.camposer object Config { - const val compileSdk = 33 - const val targetSdk = 33 + const val compileSdk = 34 + const val targetSdk = 34 const val minSdk = 21 const val versionCode = 6 const val versionName = "0.3.0" diff --git a/camposer/.gitignore b/camposer/.gitignore old mode 100644 new mode 100755 diff --git a/camposer/build.gradle.kts b/camposer/build.gradle.kts old mode 100644 new mode 100755 index 53fc35e..3290334 --- a/camposer/build.gradle.kts +++ b/camposer/build.gradle.kts @@ -1,9 +1,10 @@ import com.ujizin.camposer.Config plugins { + kotlin("multiplatform") +// id("org.jetbrains.dokka") id("com.android.library") - id("org.jetbrains.kotlin.android") - id("org.jetbrains.dokka") + id("org.jetbrains.compose") } extra.apply { @@ -12,51 +13,85 @@ extra.apply { set("PUBLISH_VERSION", Config.versionName) } -apply(from = "${rootDir}/scripts/publish-module.gradle") +// apply(from = "${rootDir}/scripts/publish-module.gradle") android { namespace = "com.ujizin.camposer" compileSdk = Config.compileSdk defaultConfig { minSdk = Config.minSdk - targetSdk = Config.targetSdk - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } + compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = "1.8" - } - buildFeatures { - compose = true - } - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get() + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - freeCompilerArgs += "-Xexplicit-api=strict" - } } -tasks.dokkaHtml.configure { - dokkaSourceSets { - named("main") { - noAndroidSdkLink.set(false) +kotlin { + targetHierarchy.default() + + + androidTarget { + compilations.all { + kotlinOptions { + freeCompilerArgs += "-Xexplicit-api=strict" + } } } -} -dependencies { - implementation(platform(libs.compose.bom)) - implementation(libs.bundles.compose) - implementation(libs.lifecycle) + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { + it.compilations.all { + kotlinOptions { + freeCompilerArgs += "-Xexplicit-api=strict" + } + } + it.binaries.framework { baseName = "camposer" } + } - api(libs.bundles.internal.camerax) + sourceSets { + val commonMain by getting { + dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + } + } + val commonTest by getting { + dependencies { + implementation(kotlin("test-junit")) + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) +// implementation(compose.desktop.uiTestJUnit4) + } + } - androidTestImplementation(libs.androidx.test.rules) - androidTestImplementation(platform(libs.compose.bom)) - androidTestImplementation(libs.compose.junit) + val androidMain by getting { + dependencies { + implementation(libs.lifecycle) + api(libs.bundles.internal.camerax) + } + } + +// val iosX64Main by getting +// val iosArm64Main by getting +// val iosSimulatorArm64Main by getting +// val iosMain by creating { +// dependsOn(commonMain) +// iosX64Main.dependsOn(this) +// iosArm64Main.dependsOn(this) +// iosSimulatorArm64Main.dependsOn(this) +// } + } } +//tasks.dokkaHtml.configure { +// dokkaSourceSets { +// named("main") { +// noAndroidSdkLink.set(false) +// } +// } +//} \ No newline at end of file diff --git a/camposer/consumer-rules.pro b/camposer/consumer-rules.pro old mode 100644 new mode 100755 diff --git a/camposer/proguard-rules.pro b/camposer/proguard-rules.pro old mode 100644 new mode 100755 diff --git a/camposer/src/main/AndroidManifest.xml b/camposer/src/androidMain/AndroidManifest.xml old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/main/AndroidManifest.xml rename to camposer/src/androidMain/AndroidManifest.xml diff --git a/camposer/src/main/java/com/ujizin/camposer/CameraPreview.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/CameraPreview.kt old mode 100644 new mode 100755 similarity index 65% rename from camposer/src/main/java/com/ujizin/camposer/CameraPreview.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/CameraPreview.kt index 2eb9a22..5084611 --- a/camposer/src/main/java/com/ujizin/camposer/CameraPreview.kt +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/CameraPreview.kt @@ -13,13 +13,14 @@ import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.viewinterop.AndroidView import androidx.lifecycle.Lifecycle import com.ujizin.camposer.extensions.clamped import com.ujizin.camposer.extensions.onCameraTouchEvent import com.ujizin.camposer.focus.FocusTap -import com.ujizin.camposer.focus.SquareCornerFocus import com.ujizin.camposer.state.CamSelector import com.ujizin.camposer.state.CameraState import com.ujizin.camposer.state.CaptureMode @@ -29,66 +30,33 @@ import com.ujizin.camposer.state.ImageCaptureMode import com.ujizin.camposer.state.ImageTargetSize import com.ujizin.camposer.state.ImplementationMode import com.ujizin.camposer.state.ScaleType -import com.ujizin.camposer.state.rememberCameraState -import kotlinx.coroutines.delay import androidx.camera.core.CameraSelector as CameraXSelector -/** - * Creates a Camera Preview's composable. - * - * @param cameraState camera state hold some states and camera's controller, it can be useful to given action like [CameraState.takePicture] - * @param camSelector camera selector to be added, default is back - * @param captureMode camera capture mode, default is image - * @param imageCaptureMode camera image capture mode, default is minimum latency for better performance - * @param imageCaptureTargetSize suggested target size for image camera capture, default is camera's preferred size - * @param flashMode flash mode to be added, default is off - * @param scaleType scale type to be added, default is fill center - * @param enableTorch enable torch from camera, default is false. - * @param exposureCompensation camera exposure compensation to be added - * @param zoomRatio zoom ratio to be added, default is 1.0 - * @param imageAnalyzer image analyzer from camera, see [ImageAnalyzer] - * @param implementationMode implementation mode to be added, default is performance - * @param isImageAnalysisEnabled enable or disable image analysis - * @param isFocusOnTapEnabled turn on feature focus on tap if true - * @param isPinchToZoomEnabled turn on feature pinch to zoom if true - * @param onPreviewStreamChanged dispatch when preview is switching to front or back - * @param onSwitchToFront composable preview when change camera to front and it's not been streaming yet - * @param onSwitchToBack composable preview when change camera to back and it's not been streaming yet - * @param onZoomRatioChanged dispatch when zoom is changed by pinch to zoom - * @param focusTapContent content of focus tap, default is [SquareCornerFocus] - * @param onFocus callback to use when on focus tap is triggered, call onComplete to [focusTapContent] gone. - * @param content content composable within of camera preview. - * @see ImageAnalyzer - * @see CameraState - * */ @Composable -public fun CameraPreview( - modifier: Modifier = Modifier, - cameraState: CameraState = rememberCameraState(), - camSelector: CamSelector = cameraState.camSelector, - captureMode: CaptureMode = cameraState.captureMode, - imageCaptureMode: ImageCaptureMode = cameraState.imageCaptureMode, - imageCaptureTargetSize: ImageTargetSize? = cameraState.imageCaptureTargetSize, - flashMode: FlashMode = cameraState.flashMode, - scaleType: ScaleType = cameraState.scaleType, - enableTorch: Boolean = cameraState.enableTorch, - exposureCompensation: Int = cameraState.initialExposure, - zoomRatio: Float = 1F, - imageAnalyzer: ImageAnalyzer? = null, - implementationMode: ImplementationMode = cameraState.implementationMode, - isImageAnalysisEnabled: Boolean = cameraState.isImageAnalysisEnabled, - isFocusOnTapEnabled: Boolean = cameraState.isFocusOnTapEnabled, - isPinchToZoomEnabled: Boolean = cameraState.isZoomSupported, - onPreviewStreamChanged: () -> Unit = {}, - onSwitchToFront: @Composable (Bitmap) -> Unit = {}, - onSwitchToBack: @Composable (Bitmap) -> Unit = {}, - onFocus: suspend (onComplete: () -> Unit) -> Unit = { onComplete -> - delay(1000L) - onComplete() - }, - onZoomRatioChanged: (Float) -> Unit = {}, - focusTapContent: @Composable () -> Unit = { SquareCornerFocus() }, - content: @Composable () -> Unit = {}, +public actual fun CameraPreview( + modifier: Modifier, + cameraState: CameraState, + camSelector: CamSelector, + captureMode: CaptureMode, + imageCaptureMode: ImageCaptureMode, + imageCaptureTargetSize: ImageTargetSize?, + flashMode: FlashMode, + scaleType: ScaleType, + enableTorch: Boolean, + exposureCompensation: Int, + zoomRatio: Float, + imageAnalyzer: ImageAnalyzer?, + implementationMode: ImplementationMode, + isImageAnalysisEnabled: Boolean, + isFocusOnTapEnabled: Boolean, + isPinchToZoomEnabled: Boolean, + onPreviewStreamChanged: () -> Unit, + onSwitchToFront: @Composable (ImageBitmap) -> Unit, + onSwitchToBack: @Composable (ImageBitmap) -> Unit, + onFocus: suspend (onComplete: () -> Unit) -> Unit, + onZoomRatioChanged: (Float) -> Unit, + focusTapContent: @Composable () -> Unit, + content: @Composable () -> Unit, ) { CameraPreviewImpl( modifier = modifier, @@ -139,8 +107,8 @@ internal fun CameraPreviewImpl( onZoomRatioChanged: (Float) -> Unit, onPreviewStreamChanged: () -> Unit, onFocus: suspend (() -> Unit) -> Unit, - onSwipeToFront: @Composable (Bitmap) -> Unit, - onSwipeToBack: @Composable (Bitmap) -> Unit, + onSwipeToFront: @Composable (ImageBitmap) -> Unit, + onSwipeToBack: @Composable (ImageBitmap) -> Unit, focusTapContent: @Composable () -> Unit, content: @Composable () -> Unit ) { @@ -214,9 +182,10 @@ internal fun CameraPreviewImpl( if (isCameraIdle) { latestBitmap?.let { + val imageBitmap = it.asImageBitmap() when (camSelector.selector.lensFacing) { - CameraXSelector.LENS_FACING_FRONT -> onSwipeToFront(it) - CameraXSelector.LENS_FACING_BACK -> onSwipeToBack(it) + CameraXSelector.LENS_FACING_FRONT -> onSwipeToFront(imageBitmap) + CameraXSelector.LENS_FACING_BACK -> onSwipeToBack(imageBitmap) else -> Unit } LaunchedEffect(latestBitmap) { @@ -227,4 +196,4 @@ internal fun CameraPreviewImpl( } content() -} +} \ No newline at end of file diff --git a/camposer/src/main/java/com/ujizin/camposer/LifecycleState.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/LifecycleState.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/main/java/com/ujizin/camposer/LifecycleState.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/LifecycleState.kt diff --git a/camposer/src/main/java/com/ujizin/camposer/extensions/CameraStateExtensions.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/extensions/CameraStateExtensions.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/main/java/com/ujizin/camposer/extensions/CameraStateExtensions.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/extensions/CameraStateExtensions.kt diff --git a/camposer/src/main/java/com/ujizin/camposer/extensions/ContextExtensions.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/extensions/ContextExtensions.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/main/java/com/ujizin/camposer/extensions/ContextExtensions.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/extensions/ContextExtensions.kt diff --git a/camposer/src/main/java/com/ujizin/camposer/extensions/FloatExtensions.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/extensions/FloatExtensions.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/main/java/com/ujizin/camposer/extensions/FloatExtensions.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/extensions/FloatExtensions.kt diff --git a/camposer/src/main/java/com/ujizin/camposer/extensions/PreviewViewExtensions.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/extensions/PreviewViewExtensions.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/main/java/com/ujizin/camposer/extensions/PreviewViewExtensions.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/extensions/PreviewViewExtensions.kt diff --git a/camposer/src/main/java/com/ujizin/camposer/state/CamSelector.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/CamSelector.kt old mode 100644 new mode 100755 similarity index 80% rename from camposer/src/main/java/com/ujizin/camposer/state/CamSelector.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/CamSelector.kt index 8c4f8ad..7fa62b8 --- a/camposer/src/main/java/com/ujizin/camposer/state/CamSelector.kt +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/CamSelector.kt @@ -13,21 +13,12 @@ import androidx.compose.runtime.saveable.listSaver * @param selector internal camera selector from CameraX * @see CameraSelector * */ -public enum class CamSelector( +public actual enum class CamSelector( internal val selector: CameraSelector ) { Front(CameraSelector.DEFAULT_FRONT_CAMERA), Back(CameraSelector.DEFAULT_BACK_CAMERA); - /** - * Inverse camera selector. Works only with default Front & Back Selector. - * */ - public val inverse: CamSelector - get() = when (this) { - Front -> Back - Back -> Front - } - internal companion object { @SuppressLint("RestrictedApi") diff --git a/camposer/src/main/java/com/ujizin/camposer/state/CameraAsState.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/CameraAsState.kt old mode 100644 new mode 100755 similarity index 97% rename from camposer/src/main/java/com/ujizin/camposer/state/CameraAsState.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/CameraAsState.kt index 24d9857..88c62a2 --- a/camposer/src/main/java/com/ujizin/camposer/state/CameraAsState.kt +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/CameraAsState.kt @@ -13,7 +13,7 @@ import com.ujizin.camposer.CameraPreview * Camera State from [CameraPreview] Composable. * */ @Composable -public fun rememberCameraState(): CameraState { +public actual fun rememberCameraState(): CameraState { val context = LocalContext.current return remember { CameraState(context) } } diff --git a/camposer/src/main/java/com/ujizin/camposer/state/CameraState.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/CameraState.kt old mode 100644 new mode 100755 similarity index 90% rename from camposer/src/main/java/com/ujizin/camposer/state/CameraState.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/CameraState.kt index cd8795e..e69533f --- a/camposer/src/main/java/com/ujizin/camposer/state/CameraState.kt +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/CameraState.kt @@ -34,7 +34,7 @@ import java.util.concurrent.Executor * * To be created use [rememberCameraState]. * */ -public class CameraState(context: Context) { +public actual class CameraState(context: Context) { /** * Main Executor to action as take picture or record. @@ -62,18 +62,18 @@ public class CameraState(context: Context) { /** * Get max zoom from camera. * */ - public var maxZoom: Float by mutableStateOf( + public actual var maxZoom: Float by mutableStateOf( controller.zoomState.value?.maxZoomRatio ?: INITIAL_ZOOM_VALUE ) - internal set + private set /** * Get min zoom from camera. * */ - public var minZoom: Float by mutableStateOf( + public actual var minZoom: Float by mutableStateOf( controller.zoomState.value?.minZoomRatio ?: INITIAL_ZOOM_VALUE ) - internal set + private set /** @@ -85,60 +85,62 @@ public class CameraState(context: Context) { /** * Get min exposure from camera. * */ - public var minExposure: Int by mutableStateOf( + public actual var minExposure: Int by mutableStateOf( exposureCompensationRange?.lower ?: INITIAL_EXPOSURE_VALUE ) - internal set + private set /** * Get max exposure from camera. * */ - public var maxExposure: Int by mutableStateOf( + public actual var maxExposure: Int by mutableStateOf( exposureCompensationRange?.upper ?: INITIAL_EXPOSURE_VALUE ) - internal set + private set - public val initialExposure: Int = INITIAL_EXPOSURE_VALUE + public actual val initialExposure: Int = INITIAL_EXPOSURE_VALUE get() = controller.cameraInfo?.exposureState?.exposureCompensationIndex ?: field /** * Check if compensation exposure is supported. * */ - public val isExposureSupported: Boolean by derivedStateOf { maxExposure != INITIAL_EXPOSURE_VALUE } + public actual val isExposureSupported: Boolean by derivedStateOf { maxExposure != INITIAL_EXPOSURE_VALUE } /** * Check if camera is streaming or not. * */ - public var isStreaming: Boolean by mutableStateOf(false) + public actual var isStreaming: Boolean by mutableStateOf(false) internal set /** * Check if zoom is supported. * */ - public val isZoomSupported: Boolean by derivedStateOf { maxZoom != 1F } + public actual val isZoomSupported: Boolean by derivedStateOf { maxZoom != 1F } /** * Check if focus on tap supported * */ - public var isFocusOnTapSupported: Boolean by mutableStateOf(true) + public actual var isFocusOnTapSupported: Boolean by mutableStateOf(true) + private set /** * Check if camera state is initialized or not. * */ - public var isInitialized: Boolean by mutableStateOf(false) - internal set + public actual var isInitialized: Boolean by mutableStateOf(false) + private set /** * Verify if camera has flash or not. * */ - public var hasFlashUnit: Boolean by mutableStateOf( + public actual var hasFlashUnit: Boolean by mutableStateOf( controller.cameraInfo?.hasFlashUnit() ?: true ) + private set /** * Capture mode to be added on camera. * */ - internal var captureMode: CaptureMode = CaptureMode.Image + internal actual var captureMode: CaptureMode = CaptureMode.Image set(value) { if (field != value) { field = value @@ -149,7 +151,7 @@ public class CameraState(context: Context) { /** * Image capture mode to be added on camera. * */ - internal var imageCaptureMode: ImageCaptureMode = ImageCaptureMode.MinLatency + internal actual var imageCaptureMode: ImageCaptureMode = ImageCaptureMode.MinLatency set(value) { if (field != value) { field = value @@ -160,18 +162,18 @@ public class CameraState(context: Context) { /** * Get scale type from the camera. * */ - internal var scaleType: ScaleType = ScaleType.FillCenter + internal actual var scaleType: ScaleType = ScaleType.FillCenter /** * Get implementation mode from the camera. * */ - internal var implementationMode: ImplementationMode = ImplementationMode.Performance + internal actual var implementationMode: ImplementationMode = ImplementationMode.Performance /** * Camera mode, it can be front or back. * @see CamSelector * */ - internal var camSelector: CamSelector = CamSelector.Back + internal actual var camSelector: CamSelector = CamSelector.Back set(value) { when { value == field -> Unit @@ -191,7 +193,7 @@ public class CameraState(context: Context) { /** * Set image capture target size on camera * */ - internal var imageCaptureTargetSize: ImageTargetSize? + internal actual var imageCaptureTargetSize: ImageTargetSize? get() = controller.imageCaptureTargetSize.toImageTargetSize() set(value) { if (value != imageCaptureTargetSize) { @@ -219,7 +221,7 @@ public class CameraState(context: Context) { /** * Enable/Disable Image analysis from the camera. * */ - internal var isImageAnalysisEnabled: Boolean = true + internal actual var isImageAnalysisEnabled: Boolean = true set(value) { if (value != field) { if (value) useCases += IMAGE_ANALYSIS else useCases -= IMAGE_ANALYSIS @@ -271,7 +273,7 @@ public class CameraState(context: Context) { /** * Get if focus on tap is enabled from cameraX. * */ - internal var isFocusOnTapEnabled: Boolean + internal actual var isFocusOnTapEnabled: Boolean get() = controller.isTapToFocusEnabled set(value) { controller.isTapToFocusEnabled = value @@ -281,7 +283,7 @@ public class CameraState(context: Context) { * Flash Mode from the camera. * @see FlashMode * */ - internal var flashMode: FlashMode + internal actual var flashMode: FlashMode get() = FlashMode.find(controller.imageCaptureFlashMode) set(value) { if (hasFlashUnit && flashMode != value) { @@ -292,7 +294,7 @@ public class CameraState(context: Context) { /** * Enabled/Disable torch from camera. * */ - internal var enableTorch: Boolean + internal actual var enableTorch: Boolean get() = controller.torchState.value == TorchState.ON set(value) { if (enableTorch != value) { @@ -303,7 +305,7 @@ public class CameraState(context: Context) { /** * Return true if it's recording. * */ - public var isRecording: Boolean by mutableStateOf(controller.isRecording) + public actual var isRecording: Boolean by mutableStateOf(controller.isRecording) private set init { diff --git a/camposer/src/main/java/com/ujizin/camposer/state/CaptureMode.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/CaptureMode.kt old mode 100644 new mode 100755 similarity index 88% rename from camposer/src/main/java/com/ujizin/camposer/state/CaptureMode.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/CaptureMode.kt index 5e3e136..d463c87 --- a/camposer/src/main/java/com/ujizin/camposer/state/CaptureMode.kt +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/CaptureMode.kt @@ -13,7 +13,7 @@ import androidx.camera.view.video.ExperimentalVideo * @see VIDEO_CAPTURE * */ @OptIn(markerClass = [ExperimentalVideo::class]) -public enum class CaptureMode(internal val value: Int) { +public actual enum class CaptureMode(internal val value: Int) { Image(IMAGE_CAPTURE), Video(VIDEO_CAPTURE), } diff --git a/camposer/src/main/java/com/ujizin/camposer/state/FlashMode.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/FlashMode.kt old mode 100644 new mode 100755 similarity index 63% rename from camposer/src/main/java/com/ujizin/camposer/state/FlashMode.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/FlashMode.kt index 4691857..7a93a92 --- a/camposer/src/main/java/com/ujizin/camposer/state/FlashMode.kt +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/FlashMode.kt @@ -8,20 +8,11 @@ import androidx.camera.core.ImageCapture * @param mode internal flash mode from cameraX * @see ImageCapture.FlashMode * */ -public enum class FlashMode(internal val mode: Int) { +public actual enum class FlashMode(internal val mode: Int) { On(ImageCapture.FLASH_MODE_ON), Auto(ImageCapture.FLASH_MODE_AUTO), Off(ImageCapture.FLASH_MODE_OFF); - /** - * Inverse flash mode. Works only with default Off & On flash modes. - * */ - public val inverse: FlashMode - get() = when(this) { - On -> Off - else -> On - } - internal companion object { internal fun find(mode: Int) = values().firstOrNull { it.mode == mode } ?: Off } diff --git a/camposer/src/main/java/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt old mode 100644 new mode 100755 similarity index 90% rename from camposer/src/main/java/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt index c536f1d..aad3a25 --- a/camposer/src/main/java/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt @@ -7,7 +7,7 @@ import androidx.camera.core.ImageAnalysis * * For more information, check it out [CameraX ImageAnalysis operating modes](https://developer.android.com/training/camerax/analyze#operating-modes) * */ -public enum class ImageAnalysisBackpressureStrategy(internal val strategy: Int) { +public actual enum class ImageAnalysisBackpressureStrategy(internal val strategy: Int) { /** * always caches the latest image, used for non-blocking operation. * */ diff --git a/camposer/src/main/java/com/ujizin/camposer/state/ImageAnalyzer.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageAnalyzer.kt old mode 100644 new mode 100755 similarity index 98% rename from camposer/src/main/java/com/ujizin/camposer/state/ImageAnalyzer.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageAnalyzer.kt index 1a5da80..be8af64 --- a/camposer/src/main/java/com/ujizin/camposer/state/ImageAnalyzer.kt +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageAnalyzer.kt @@ -14,7 +14,7 @@ import androidx.compose.runtime.Immutable * @see rememberImageAnalyzer * */ @Immutable -public class ImageAnalyzer( +public actual class ImageAnalyzer( private val cameraState: CameraState, imageAnalysisBackpressureStrategy: ImageAnalysisBackpressureStrategy, imageAnalysisTargetSize: ImageTargetSize?, diff --git a/camposer/src/main/java/com/ujizin/camposer/state/ImageCaptureMode.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageCaptureMode.kt old mode 100644 new mode 100755 similarity index 86% rename from camposer/src/main/java/com/ujizin/camposer/state/ImageCaptureMode.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageCaptureMode.kt index 4973c04..c3b738e --- a/camposer/src/main/java/com/ujizin/camposer/state/ImageCaptureMode.kt +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageCaptureMode.kt @@ -11,7 +11,7 @@ import androidx.camera.core.ImageCapture * @see ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY * @see ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY * */ -public enum class ImageCaptureMode(@ImageCapture.CaptureMode internal val mode: Int) { +public actual enum class ImageCaptureMode(@ImageCapture.CaptureMode internal val mode: Int) { @ExperimentalZeroShutterLag ZeroShutterLag(ImageCapture.CAPTURE_MODE_ZERO_SHUTTER_LAG), MaxQuality(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY), diff --git a/camposer/src/main/java/com/ujizin/camposer/state/ImageCaptureResult.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageCaptureResult.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/main/java/com/ujizin/camposer/state/ImageCaptureResult.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageCaptureResult.kt diff --git a/camposer/src/main/java/com/ujizin/camposer/state/ImageTargetSize.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageTargetSize.kt old mode 100644 new mode 100755 similarity index 97% rename from camposer/src/main/java/com/ujizin/camposer/state/ImageTargetSize.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageTargetSize.kt index 1dd4030..c0cbdce --- a/camposer/src/main/java/com/ujizin/camposer/state/ImageTargetSize.kt +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImageTargetSize.kt @@ -8,7 +8,7 @@ import androidx.camera.view.CameraController.OutputSize * Image Analysis target size is used to target the size of image analysis, accepting [AspectRatio] * or [Size]. * */ -public data class ImageTargetSize( +public actual class ImageTargetSize( private var aspectRatio: Int? = null, private var size: Size? = null, private var outputSize: OutputSize? = null diff --git a/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImplementationMode.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImplementationMode.kt new file mode 100755 index 0000000..21bd619 --- /dev/null +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ImplementationMode.kt @@ -0,0 +1,14 @@ +package com.ujizin.camposer.state + +import androidx.camera.view.PreviewView + +/** + * Camera implementation mode. + * + * @param value internal implementation mode from cameraX + * @see PreviewView.ImplementationMode + * */ +public actual enum class ImplementationMode(internal val value: PreviewView.ImplementationMode) { + Compatible(PreviewView.ImplementationMode.COMPATIBLE), + Performance(PreviewView.ImplementationMode.PERFORMANCE), +} \ No newline at end of file diff --git a/camposer/src/main/java/com/ujizin/camposer/state/PinchToZoomGesture.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/PinchToZoomGesture.kt old mode 100644 new mode 100755 similarity index 88% rename from camposer/src/main/java/com/ujizin/camposer/state/PinchToZoomGesture.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/PinchToZoomGesture.kt index ce7f68a..c1ea7c3 --- a/camposer/src/main/java/com/ujizin/camposer/state/PinchToZoomGesture.kt +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/PinchToZoomGesture.kt @@ -2,7 +2,7 @@ package com.ujizin.camposer.state import android.view.ScaleGestureDetector -internal class PinchToZoomGesture( +internal actual class PinchToZoomGesture( private val onZoomChanged: (Float) -> Unit ) : ScaleGestureDetector.SimpleOnScaleGestureListener() { override fun onScale(detector: ScaleGestureDetector): Boolean { diff --git a/camposer/src/main/java/com/ujizin/camposer/state/ScaleType.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ScaleType.kt old mode 100644 new mode 100755 similarity index 86% rename from camposer/src/main/java/com/ujizin/camposer/state/ScaleType.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ScaleType.kt index 138fbab..ae2d0cd --- a/camposer/src/main/java/com/ujizin/camposer/state/ScaleType.kt +++ b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/ScaleType.kt @@ -8,7 +8,7 @@ import androidx.camera.view.PreviewView.ScaleType as CameraScaleType * @param type internal scale type from cameraX * @see CameraScaleType * */ -public enum class ScaleType(public val type: CameraScaleType) { +public actual enum class ScaleType(public val type: CameraScaleType) { FitStart(CameraScaleType.FIT_START), FitCenter(CameraScaleType.FIT_CENTER), FitEnd(CameraScaleType.FIT_END), diff --git a/camposer/src/main/java/com/ujizin/camposer/state/VideoCaptureResult.kt b/camposer/src/androidMain/kotlin/com/ujizin/camposer/state/VideoCaptureResult.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/main/java/com/ujizin/camposer/state/VideoCaptureResult.kt rename to camposer/src/androidMain/kotlin/com/ujizin/camposer/state/VideoCaptureResult.kt diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/CameraPreview.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/CameraPreview.kt new file mode 100755 index 0000000..1918016 --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/CameraPreview.kt @@ -0,0 +1,75 @@ +package com.ujizin.camposer + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ImageBitmap +import com.ujizin.camposer.focus.SquareCornerFocus +import com.ujizin.camposer.state.CamSelector +import com.ujizin.camposer.state.CameraState +import com.ujizin.camposer.state.CaptureMode +import com.ujizin.camposer.state.FlashMode +import com.ujizin.camposer.state.ImageAnalyzer +import com.ujizin.camposer.state.ImageCaptureMode +import com.ujizin.camposer.state.ImageTargetSize +import com.ujizin.camposer.state.ImplementationMode +import com.ujizin.camposer.state.ScaleType +import com.ujizin.camposer.state.rememberCameraState +import kotlinx.coroutines.delay + +/** + * Creates a Camera Preview's composable. + * + * @param cameraState camera state hold some states and camera's controller, it can be useful to given action like [CameraState.takePicture] + * @param camSelector camera selector to be added, default is back + * @param captureMode camera capture mode, default is image + * @param imageCaptureMode camera image capture mode, default is minimum latency for better performance + * @param imageCaptureTargetSize suggested target size for image camera capture, default is camera's preferred size + * @param flashMode flash mode to be added, default is off + * @param scaleType scale type to be added, default is fill center + * @param enableTorch enable torch from camera, default is false. + * @param exposureCompensation camera exposure compensation to be added + * @param zoomRatio zoom ratio to be added, default is 1.0 + * @param imageAnalyzer image analyzer from camera, see [ImageAnalyzer] + * @param implementationMode implementation mode to be added, default is performance + * @param isImageAnalysisEnabled enable or disable image analysis + * @param isFocusOnTapEnabled turn on feature focus on tap if true + * @param isPinchToZoomEnabled turn on feature pinch to zoom if true + * @param onPreviewStreamChanged dispatch when preview is switching to front or back + * @param onSwitchToFront composable preview when change camera to front and it's not been streaming yet + * @param onSwitchToBack composable preview when change camera to back and it's not been streaming yet + * @param onZoomRatioChanged dispatch when zoom is changed by pinch to zoom + * @param focusTapContent content of focus tap, default is [SquareCornerFocus] + * @param onFocus callback to use when on focus tap is triggered, call onComplete to [focusTapContent] gone. + * @param content content composable within of camera preview. + * @see ImageAnalyzer + * @see CameraState + * */ +@Composable +public expect fun CameraPreview( + modifier: Modifier = Modifier, + cameraState: CameraState, + camSelector: CamSelector = cameraState.camSelector, + captureMode: CaptureMode = cameraState.captureMode, + imageCaptureMode: ImageCaptureMode = cameraState.imageCaptureMode, + imageCaptureTargetSize: ImageTargetSize? = cameraState.imageCaptureTargetSize, + flashMode: FlashMode = cameraState.flashMode, + scaleType: ScaleType = cameraState.scaleType, + enableTorch: Boolean = cameraState.enableTorch, + exposureCompensation: Int = cameraState.initialExposure, + zoomRatio: Float = 1F, + imageAnalyzer: ImageAnalyzer? = null, + implementationMode: ImplementationMode = cameraState.implementationMode, + isImageAnalysisEnabled: Boolean = cameraState.isImageAnalysisEnabled, + isFocusOnTapEnabled: Boolean = cameraState.isFocusOnTapEnabled, + isPinchToZoomEnabled: Boolean = cameraState.isZoomSupported, + onPreviewStreamChanged: () -> Unit = {}, + onSwitchToFront: @Composable (ImageBitmap) -> Unit = {}, + onSwitchToBack: @Composable (ImageBitmap) -> Unit = {}, + onFocus: suspend (onComplete: () -> Unit) -> Unit = { onComplete -> + delay(1000L) + onComplete() + }, + onZoomRatioChanged: (Float) -> Unit = {}, + focusTapContent: @Composable () -> Unit = { SquareCornerFocus() }, + content: @Composable () -> Unit = {}, +) \ No newline at end of file diff --git a/camposer/src/main/java/com/ujizin/camposer/focus/CornerBorder.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/focus/CornerBorder.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/main/java/com/ujizin/camposer/focus/CornerBorder.kt rename to camposer/src/commonMain/kotlin/com/ujizin/camposer/focus/CornerBorder.kt diff --git a/camposer/src/main/java/com/ujizin/camposer/focus/FocusTap.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/focus/FocusTap.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/main/java/com/ujizin/camposer/focus/FocusTap.kt rename to camposer/src/commonMain/kotlin/com/ujizin/camposer/focus/FocusTap.kt diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CamSelector.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CamSelector.kt new file mode 100755 index 0000000..2672fa9 --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CamSelector.kt @@ -0,0 +1,15 @@ +package com.ujizin.camposer.state + +public expect enum class CamSelector { + Front, + Back, +} + +/** + * Inverse camera selector. Works only with default Front & Back Selector. + * */ +public val CamSelector.inverse: CamSelector + get() = when (this) { + CamSelector.Front -> CamSelector.Back + CamSelector.Back -> CamSelector.Front + } diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CameraAsState.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CameraAsState.kt new file mode 100755 index 0000000..2c98417 --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CameraAsState.kt @@ -0,0 +1,10 @@ +package com.ujizin.camposer.state + +import androidx.compose.runtime.Composable +import com.ujizin.camposer.CameraPreview + +/** + * Camera State from [CameraPreview] Composable. + * */ +@Composable +public expect fun rememberCameraState(): CameraState diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CameraState.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CameraState.kt new file mode 100755 index 0000000..6277a2f --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CameraState.kt @@ -0,0 +1,69 @@ +package com.ujizin.camposer.state + +public expect class CameraState { + internal var camSelector: CamSelector + internal var captureMode: CaptureMode + internal var imageCaptureMode: ImageCaptureMode + internal var imageCaptureTargetSize: ImageTargetSize? + internal var flashMode: FlashMode + internal var scaleType: ScaleType + internal var implementationMode: ImplementationMode + internal var isImageAnalysisEnabled: Boolean + internal var isFocusOnTapEnabled: Boolean + internal var enableTorch: Boolean + public val initialExposure: Int + public val isZoomSupported: Boolean + + /** + * Get max zoom from camera. + * */ + public var maxZoom: Float + private set + + /** + * Get min zoom from camera. + * */ + public var minZoom: Float + private set + + /** + * Get min exposure from camera. + * */ + public var minExposure: Int + private set + /** + * Get max exposure from camera. + * */ + public var maxExposure: Int + private set + /** + * Check if compensation exposure is supported. + * */ + public val isExposureSupported: Boolean + + /** + * Check if camera is streaming or not. + * */ + public var isStreaming: Boolean + internal set + /** + * Check if focus on tap supported + * */ + public var isFocusOnTapSupported: Boolean + private set + /** + * Check if camera state is initialized or not. + * */ + public var isInitialized: Boolean + private set + /** + * Verify if camera has flash or not. + * */ + public var hasFlashUnit: Boolean + private set + /** + * Return true if it's recording. + * */ + public var isRecording: Boolean + private set +} \ No newline at end of file diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CaptureMode.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CaptureMode.kt new file mode 100755 index 0000000..fb47941 --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/CaptureMode.kt @@ -0,0 +1,10 @@ +package com.ujizin.camposer.state + +/** + * Camera Capture mode. + * + * */ +public expect enum class CaptureMode { + Image, + Video, +} diff --git a/camposer/src/main/java/com/ujizin/camposer/state/ConditionalState.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ConditionalState.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/main/java/com/ujizin/camposer/state/ConditionalState.kt rename to camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ConditionalState.kt diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/FlashMode.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/FlashMode.kt new file mode 100755 index 0000000..ee8cc3a --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/FlashMode.kt @@ -0,0 +1,14 @@ +package com.ujizin.camposer.state + +public expect enum class FlashMode { + On, Auto, Off; +} + +/** + * Inverse flash mode. Works only with default Off & On flash modes. + * */ +public val FlashMode.inverse: FlashMode + get() = when(this) { + FlashMode.On -> FlashMode.Off + else -> FlashMode.On + } \ No newline at end of file diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt new file mode 100755 index 0000000..b99a8b7 --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt @@ -0,0 +1,3 @@ +package com.ujizin.camposer.state + +public expect enum class ImageAnalysisBackpressureStrategy \ No newline at end of file diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageAnalyzer.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageAnalyzer.kt new file mode 100755 index 0000000..094275b --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageAnalyzer.kt @@ -0,0 +1,3 @@ +package com.ujizin.camposer.state + +public expect class ImageAnalyzer \ No newline at end of file diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageCaptureMode.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageCaptureMode.kt new file mode 100755 index 0000000..bc52dbe --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageCaptureMode.kt @@ -0,0 +1,7 @@ +package com.ujizin.camposer.state + +public expect enum class ImageCaptureMode { + ZeroShutterLag, + MaxQuality, + MinLatency +} \ No newline at end of file diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageTargetSize.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageTargetSize.kt new file mode 100755 index 0000000..a135718 --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImageTargetSize.kt @@ -0,0 +1,3 @@ +package com.ujizin.camposer.state + +public expect class ImageTargetSize \ No newline at end of file diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImplementationMode.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImplementationMode.kt new file mode 100755 index 0000000..ae9c250 --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ImplementationMode.kt @@ -0,0 +1,15 @@ +package com.ujizin.camposer.state + +public expect enum class ImplementationMode { + Compatible, + Performance, +} + +/** + * Inverse currently implementation mode. + * */ +public val ImplementationMode.inverse: ImplementationMode + get() = when (this) { + ImplementationMode.Compatible -> ImplementationMode.Performance + else -> ImplementationMode.Compatible + } \ No newline at end of file diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/PinchToZoomGesture.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/PinchToZoomGesture.kt new file mode 100755 index 0000000..b0cfd7d --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/PinchToZoomGesture.kt @@ -0,0 +1,3 @@ +package com.ujizin.camposer.state + +internal expect class PinchToZoomGesture \ No newline at end of file diff --git a/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ScaleType.kt b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ScaleType.kt new file mode 100755 index 0000000..877a9af --- /dev/null +++ b/camposer/src/commonMain/kotlin/com/ujizin/camposer/state/ScaleType.kt @@ -0,0 +1,13 @@ +package com.ujizin.camposer.state + +/** + * Camera scale type. + * */ +public expect enum class ScaleType { + FitStart, + FitCenter, + FitEnd, + FillStart, + FillCenter, + FillEnd, +} \ No newline at end of file diff --git a/camposer/src/androidTest/AndroidManifest.xml b/camposer/src/commonTest/AndroidManifest.xml old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/AndroidManifest.xml rename to camposer/src/commonTest/AndroidManifest.xml diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/CamSelectorTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/CamSelectorTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/CamSelectorTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/CamSelectorTest.kt diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/CameraTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/CameraTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/CameraTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/CameraTest.kt diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/CaptureModeTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/CaptureModeTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/CaptureModeTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/CaptureModeTest.kt diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/ExposureCompensationTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/ExposureCompensationTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/ExposureCompensationTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/ExposureCompensationTest.kt diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/FlashModeTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/FlashModeTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/FlashModeTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/FlashModeTest.kt diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/FocusOnTapTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/FocusOnTapTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/FocusOnTapTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/FocusOnTapTest.kt diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/ImageAnalyzerTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/ImageAnalyzerTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/ImageAnalyzerTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/ImageAnalyzerTest.kt diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/ImageCaptureModeTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/ImageCaptureModeTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/ImageCaptureModeTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/ImageCaptureModeTest.kt diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/ImageCaptureTargetSizeTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/ImageCaptureTargetSizeTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/ImageCaptureTargetSizeTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/ImageCaptureTargetSizeTest.kt diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/ImplementationModeTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/ImplementationModeTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/ImplementationModeTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/ImplementationModeTest.kt diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/ScaleTypeTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/ScaleTypeTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/ScaleTypeTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/ScaleTypeTest.kt diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/TorchTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/TorchTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/TorchTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/TorchTest.kt diff --git a/camposer/src/androidTest/java/com/ujizin/camposer/ZoomRatioTest.kt b/camposer/src/commonTest/kotlin/com/ujizin/camposer/ZoomRatioTest.kt old mode 100644 new mode 100755 similarity index 100% rename from camposer/src/androidTest/java/com/ujizin/camposer/ZoomRatioTest.kt rename to camposer/src/commonTest/kotlin/com/ujizin/camposer/ZoomRatioTest.kt diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/CameraPreview.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/CameraPreview.kt new file mode 100755 index 0000000..48c533a --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/CameraPreview.kt @@ -0,0 +1,88 @@ +package com.ujizin.camposer + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.interop.UIKitView +import com.ujizin.camposer.state.CamSelector +import com.ujizin.camposer.state.CameraState +import com.ujizin.camposer.state.CaptureMode +import com.ujizin.camposer.state.FlashMode +import com.ujizin.camposer.state.ImageAnalyzer +import com.ujizin.camposer.state.ImageCaptureMode +import com.ujizin.camposer.state.ImageTargetSize +import com.ujizin.camposer.state.ImplementationMode +import com.ujizin.camposer.state.ScaleType +import kotlinx.cinterop.ExperimentalForeignApi +import platform.AVFoundation.AVCaptureVideoPreviewLayer +import platform.UIKit.UIScreen +import platform.UIKit.UIView + +@OptIn(ExperimentalForeignApi::class) +@Composable +public actual fun CameraPreview( + modifier: Modifier, + cameraState: CameraState, + camSelector: CamSelector, + captureMode: CaptureMode, + imageCaptureMode: ImageCaptureMode, + imageCaptureTargetSize: ImageTargetSize?, + flashMode: FlashMode, + scaleType: ScaleType, + enableTorch: Boolean, + exposureCompensation: Int, + zoomRatio: Float, + imageAnalyzer: ImageAnalyzer?, + implementationMode: ImplementationMode, + isImageAnalysisEnabled: Boolean, + isFocusOnTapEnabled: Boolean, + isPinchToZoomEnabled: Boolean, + onPreviewStreamChanged: () -> Unit, + onSwitchToFront: @Composable (ImageBitmap) -> Unit, + onSwitchToBack: @Composable (ImageBitmap) -> Unit, + onFocus: suspend (onComplete: () -> Unit) -> Unit, + onZoomRatioChanged: (Float) -> Unit, + focusTapContent: @Composable () -> Unit, + content: @Composable () -> Unit, +) { +// val previewLayer = remember(cameraState) { +// AVCaptureVideoPreviewLayer(session = cameraState.session) +// } + +// UIKitView( +// modifier = modifier, +// update = { +// previewLayer.videoGravity = scaleType.gravity +// cameraState.update( +// camSelector = camSelector, +// captureMode = captureMode, +// scaleType = scaleType, +// imageCaptureTargetSize = imageCaptureTargetSize, +// isImageAnalysisEnabled = isImageAnalysisEnabled, +// imageAnalyzer = imageAnalyzer, +// implementationMode = implementationMode, +// isFocusOnTapEnabled = isFocusOnTapEnabled, +// flashMode = flashMode, +// zoomRatio = zoomRatio, +// imageCaptureMode = imageCaptureMode, +// enableTorch = enableTorch, +// exposureCompensation = exposureCompensation +// ) +// }, +// factory = { +// UIView().apply { +// layer.addSublayer(previewLayer) +// previewLayer.frame = bounds +// } +// } +// ) + + content() + +// DisposableEffect(cameraState) { +// cameraState.session.startRunning() +// onDispose { /*cameraState.session.stopRunning()*/ } +// } +} \ No newline at end of file diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/extensions/AVCaptureExtensions.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/extensions/AVCaptureExtensions.kt new file mode 100755 index 0000000..681c579 --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/extensions/AVCaptureExtensions.kt @@ -0,0 +1,19 @@ +package com.ujizin.camposer.extensions + +import platform.AVFoundation.AVCaptureDevice +import platform.AVFoundation.AVCaptureDeviceInput +import platform.AVFoundation.AVCaptureDevicePosition +import platform.AVFoundation.AVCaptureSession +import platform.AVFoundation.position + +internal val AVCaptureSession.captureDeviceInput: AVCaptureDeviceInput? + get() = inputs.firstOrNull() as? AVCaptureDeviceInput + +internal val AVCaptureDevicePosition.captureDevice: AVCaptureDevice? + get() = platform.AVFoundation.AVCaptureDeviceDiscoverySession.discoverySessionWithDeviceTypes( + listOf(platform.AVFoundation.AVCaptureDeviceTypeBuiltInWideAngleCamera), + platform.AVFoundation.AVMediaTypeVideo, + platform.AVFoundation.AVCaptureDevicePositionUnspecified + ).devices.firstOrNull { + (it as? AVCaptureDevice)?.position == this + } as? AVCaptureDevice diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/mapper/CameraFlashModeMapper.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/mapper/CameraFlashModeMapper.kt new file mode 100755 index 0000000..08a2d5e --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/mapper/CameraFlashModeMapper.kt @@ -0,0 +1,20 @@ +package com.ujizin.camposer.mapper + +import com.ujizin.camposer.state.FlashMode +import platform.AVFoundation.AVCaptureFlashMode +import platform.AVFoundation.AVCaptureFlashModeAuto +import platform.AVFoundation.AVCaptureFlashModeOff +import platform.AVFoundation.AVCaptureFlashModeOn + +public fun AVCaptureFlashMode.toFlashMode(): FlashMode = when (this) { + AVCaptureFlashModeOn -> FlashMode.On + AVCaptureFlashModeOff -> FlashMode.Off + AVCaptureFlashModeAuto -> FlashMode.Auto + else -> throw RuntimeException("Flash Mode not found in AVCaptureFlashMode") +} + +public fun FlashMode.toAVCaptureFlashMode(): Long = when (this) { + FlashMode.On -> AVCaptureFlashModeOn + FlashMode.Auto -> AVCaptureFlashModeAuto + FlashMode.Off -> AVCaptureFlashModeOff +} diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/mapper/CameraSelectorMapper.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/mapper/CameraSelectorMapper.kt new file mode 100755 index 0000000..59ff28b --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/mapper/CameraSelectorMapper.kt @@ -0,0 +1,26 @@ +package com.ujizin.camposer.mapper + +import com.ujizin.camposer.extensions.captureDevice +import com.ujizin.camposer.state.CamSelector +import kotlinx.cinterop.ExperimentalForeignApi +import platform.AVFoundation.AVCaptureDeviceInput +import platform.AVFoundation.AVCaptureDevicePositionBack +import platform.AVFoundation.AVCaptureDevicePositionFront +import platform.AVFoundation.position + +@OptIn(ExperimentalForeignApi::class) +internal fun CamSelector.toAVCaptureDeviceInput(): AVCaptureDeviceInput? { + val captureDevice = when (this) { + CamSelector.Front -> AVCaptureDevicePositionFront + CamSelector.Back -> AVCaptureDevicePositionBack + }.captureDevice + + // TODO handle error + return captureDevice?.let { AVCaptureDeviceInput(it, null) } +} + +internal fun AVCaptureDeviceInput?.toCamSelector(): CamSelector = when (this?.device?.position) { + AVCaptureDevicePositionBack -> CamSelector.Back + AVCaptureDevicePositionFront -> CamSelector.Front + else -> throw RuntimeException("Cam selector not found in AVCaptureDeviceInput") +} \ No newline at end of file diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CamSelector.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CamSelector.kt new file mode 100755 index 0000000..3310136 --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CamSelector.kt @@ -0,0 +1,6 @@ +package com.ujizin.camposer.state + +public actual enum class CamSelector { + Front, + Back; +} \ No newline at end of file diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CameraAsState.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CameraAsState.kt new file mode 100755 index 0000000..1ac7540 --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CameraAsState.kt @@ -0,0 +1,9 @@ +package com.ujizin.camposer.state + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember + +@Composable +public actual fun rememberCameraState(): CameraState { + return remember { CameraState() } +} \ No newline at end of file diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CameraState.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CameraState.kt new file mode 100755 index 0000000..744ad74 --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CameraState.kt @@ -0,0 +1,195 @@ +package com.ujizin.camposer.state + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import com.ujizin.camposer.extensions.captureDeviceInput +import com.ujizin.camposer.mapper.toAVCaptureDeviceInput +import com.ujizin.camposer.mapper.toAVCaptureFlashMode +import com.ujizin.camposer.mapper.toCamSelector +import com.ujizin.camposer.mapper.toFlashMode +import platform.AVFoundation.AVCaptureDevice +import platform.AVFoundation.AVCaptureSession +import platform.AVFoundation.AVCaptureTorchModeOff +import platform.AVFoundation.AVCaptureTorchModeOn +import platform.AVFoundation.exposureTargetOffset +import platform.AVFoundation.flashMode +import platform.AVFoundation.hasFlash +import platform.AVFoundation.isExposureModeSupported +import platform.AVFoundation.isExposurePointOfInterestSupported +import platform.AVFoundation.maxAvailableVideoZoomFactor +import platform.AVFoundation.minAvailableVideoZoomFactor +import platform.AVFoundation.minExposureTargetBias +import platform.AVFoundation.torchMode +import platform.AVFoundation.videoZoomFactor +import kotlin.math.roundToInt + +public actual class CameraState { + +// internal val session by lazy { AVCaptureSession() } + +// private val device: AVCaptureDevice? +// get() = session.captureDeviceInput?.device + + internal actual var camSelector: CamSelector + get() = CamSelector.Back //session.captureDeviceInput.toCamSelector() + set(value) { +// configureSession { +// captureDeviceInput?.let(::removeInput) +// value.toAVCaptureDeviceInput()?.let(session::addInput) +// } + } + + internal actual var captureMode: CaptureMode + get() = TODO("Not yet implemented") + set(value) {} + + internal actual var imageCaptureMode: ImageCaptureMode = ImageCaptureMode.MinLatency + + internal actual var imageCaptureTargetSize: ImageTargetSize? + get() = TODO("Not yet implemented") + set(value) {} + + internal actual var flashMode: FlashMode + get() = FlashMode.Off //device?.flashMode?.toFlashMode() ?: FlashMode.Off + set(value) { +// device?.flashMode = value.toAVCaptureFlashMode() + } + + internal actual var scaleType: ScaleType = ScaleType.FillCenter + + internal actual var implementationMode: ImplementationMode = ImplementationMode.Performance + + internal actual var isImageAnalysisEnabled: Boolean + get() = TODO("Not yet implemented") + set(value) {} + + internal actual var isFocusOnTapEnabled: Boolean + get() = TODO("Not yet implemented") + set(value) {} + + internal actual var enableTorch: Boolean + get() = false // device?.torchMode == AVCaptureTorchModeOn + set(value) { +// device?.torchMode = when { +// value -> AVCaptureTorchModeOn +// else -> AVCaptureTorchModeOff +// } + } + + private var zoomRatio: Float + get() = 1F // device?.videoZoomFactor?.toFloat() ?: 1F + set(value) { +// device?.videoZoomFactor = value.toDouble() + } + + private var exposureCompensation: Int + get() = 1 // device?.exposureTargetOffset?.roundToInt() ?: initialExposure + set(value) { + } + + public actual val initialExposure: Int = 1 // device?.exposureTargetOffset?.roundToInt() ?: 1 + + public actual val isZoomSupported: Boolean + get() = true + + /** + * Get max zoom from camera. + * */ + public actual var maxZoom: Float = 1F /*by mutableStateOf(device?.maxAvailableVideoZoomFactor?.toFloat() ?: 1F)*/ + private set + + /** + * Get min zoom from camera. + * */ + public actual var minZoom: Float = 1F // by mutableStateOf(device?.minAvailableVideoZoomFactor?.toFloat() ?: 1F) + private set + + /** + * Get min exposure from camera. + * */ + public actual var minExposure: Int = 1 // by mutableStateOf(device?.minExposureTargetBias?.roundToInt() ?: 1) + private set + + /** + * Get max exposure from camera. + * */ + public actual var maxExposure: Int = 1 //by mutableStateOf(device?.minExposureTargetBias?.roundToInt() ?: 1) + private set + + /** + * Check if compensation exposure is supported. + * */ + public actual val isExposureSupported: Boolean + get() = true + + /** + * Check if camera is streaming or not. + * */ + public actual var isStreaming: Boolean = false + internal set + + /** + * Check if focus on tap supported + * */ + public actual var isFocusOnTapSupported: Boolean = true + private set + + /** + * Check if camera state is initialized or not. + * */ + public actual var isInitialized: Boolean = false // by mutableStateOf(device?.isConnected() ?: false) + private set + + /** + * Verify if camera has flash or not. + * */ + public actual var hasFlashUnit: Boolean = true // device?.hasFlash ?: false + get() = false // device?.hasFlash ?: false + private set + + /** + * Return true if it's recording. + * */ + public actual var isRecording: Boolean + get() = TODO("Not yet implemented") + set(value) {} + +// private fun configureSession(block: AVCaptureSession.() -> Unit) = session.apply { +// beginConfiguration() +// block() +// commitConfiguration() +// } + + /** + * Update all values from camera state. + * */ + internal fun update( + camSelector: CamSelector, + captureMode: CaptureMode, + scaleType: ScaleType, + imageCaptureTargetSize: ImageTargetSize?, + isImageAnalysisEnabled: Boolean, + imageAnalyzer: ImageAnalyzer?, + implementationMode: ImplementationMode, + isFocusOnTapEnabled: Boolean, + flashMode: FlashMode, + zoomRatio: Float, + imageCaptureMode: ImageCaptureMode, + enableTorch: Boolean, + exposureCompensation: Int + ) { + this.camSelector = camSelector + this.captureMode = captureMode + this.scaleType = scaleType + this.imageCaptureTargetSize = imageCaptureTargetSize + this.isImageAnalysisEnabled = isImageAnalysisEnabled + this.implementationMode = implementationMode + this.isFocusOnTapEnabled = isFocusOnTapEnabled + this.flashMode = flashMode + this.enableTorch = enableTorch + this.imageCaptureMode = imageCaptureMode + this.zoomRatio = zoomRatio + this.exposureCompensation = exposureCompensation + } +} diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CaptureMode.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CaptureMode.kt new file mode 100755 index 0000000..1d02a4a --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/CaptureMode.kt @@ -0,0 +1,10 @@ +package com.ujizin.camposer.state + +/** + * Camera Capture mode. + * */ +public actual enum class CaptureMode { + Image, + Video, +} + diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/FlashMode.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/FlashMode.kt new file mode 100755 index 0000000..cc6a746 --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/FlashMode.kt @@ -0,0 +1,5 @@ +package com.ujizin.camposer.state + +public actual enum class FlashMode { + On, Auto, Off +} \ No newline at end of file diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt new file mode 100755 index 0000000..14732ff --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageAnalysisBackpressureStrategy.kt @@ -0,0 +1,3 @@ +package com.ujizin.camposer.state + +public actual enum class ImageAnalysisBackpressureStrategy \ No newline at end of file diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageAnalyzer.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageAnalyzer.kt new file mode 100755 index 0000000..fa84525 --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageAnalyzer.kt @@ -0,0 +1,5 @@ +package com.ujizin.camposer.state + +public actual class ImageAnalyzer { + +} \ No newline at end of file diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageCaptureMode.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageCaptureMode.kt new file mode 100755 index 0000000..bd5d50b --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageCaptureMode.kt @@ -0,0 +1,7 @@ +package com.ujizin.camposer.state + +public actual enum class ImageCaptureMode { + ZeroShutterLag, + MaxQuality, + MinLatency +} \ No newline at end of file diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageTargetSize.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageTargetSize.kt new file mode 100755 index 0000000..435da3f --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImageTargetSize.kt @@ -0,0 +1,3 @@ +package com.ujizin.camposer.state + +public actual class ImageTargetSize \ No newline at end of file diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImplementationMode.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImplementationMode.kt new file mode 100755 index 0000000..06f8ddd --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ImplementationMode.kt @@ -0,0 +1,6 @@ +package com.ujizin.camposer.state + +public actual enum class ImplementationMode { + Compatible, + Performance +} \ No newline at end of file diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/PinchToZoomGesture.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/PinchToZoomGesture.kt new file mode 100755 index 0000000..f238ab2 --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/PinchToZoomGesture.kt @@ -0,0 +1,3 @@ +package com.ujizin.camposer.state + +internal actual class PinchToZoomGesture \ No newline at end of file diff --git a/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ScaleType.kt b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ScaleType.kt new file mode 100755 index 0000000..d369d8e --- /dev/null +++ b/camposer/src/iosMain/kotlin/com/ujizin/camposer/state/ScaleType.kt @@ -0,0 +1,14 @@ +package com.ujizin.camposer.state + +import platform.AVFoundation.AVLayerVideoGravity +import platform.AVFoundation.AVLayerVideoGravityResize +import platform.AVFoundation.AVLayerVideoGravityResizeAspectFill + +public actual enum class ScaleType(internal val gravity: AVLayerVideoGravity) { + FitStart(AVLayerVideoGravityResize), + FitCenter(AVLayerVideoGravityResize), + FitEnd(AVLayerVideoGravityResize), + FillStart(AVLayerVideoGravityResizeAspectFill), + FillCenter(AVLayerVideoGravityResizeAspectFill), + FillEnd(AVLayerVideoGravityResizeAspectFill), +} \ No newline at end of file diff --git a/camposer/src/main/java/com/ujizin/camposer/state/ImplementationMode.kt b/camposer/src/main/java/com/ujizin/camposer/state/ImplementationMode.kt deleted file mode 100644 index 6d4c916..0000000 --- a/camposer/src/main/java/com/ujizin/camposer/state/ImplementationMode.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.ujizin.camposer.state - -import androidx.camera.view.PreviewView - -/** - * Camera implementation mode. - * - * @param value internal implementation mode from cameraX - * @see PreviewView.ImplementationMode - * */ -public enum class ImplementationMode(internal val value: PreviewView.ImplementationMode) { - Compatible(PreviewView.ImplementationMode.COMPATIBLE), - Performance(PreviewView.ImplementationMode.PERFORMANCE); - - /** - * Inverse currently implementation mode. - * */ - public val inverse: ImplementationMode - get() = when (this) { - Compatible -> Performance - else -> Compatible - } -} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties old mode 100644 new mode 100755 index 3c5031e..3b1f672 --- a/gradle.properties +++ b/gradle.properties @@ -20,4 +20,18 @@ kotlin.code.style=official # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +#android.nonTransitiveRClass=true + +#MPP +kotlin.mpp.stability.nowarn=true +kotlin.mpp.enableCInteropCommonization=true +kotlin.mpp.androidSourceSetLayoutVersion=2 + +# Compose + +org.jetbrains.compose.experimental.uikit.enabled=true + +# Versions +kotlin.version=1.9.10 +agp.version=8.0.0 +compose.version=1.5.3 \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml old mode 100644 new mode 100755 index fcc8f96..a1a83fb --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,13 +1,14 @@ [versions] -kotlin = "1.8.10" +kotlin = "1.9.10" gradle = "8.0.0" gradle-nexus = "1.1.0" androidx-core = "1.9.0" androidx-test-rules = "1.4.0" camerax = "1.2.3" compose-bom = "2023.04.01" -compose-compiler = "1.4.4" +compose-compiler = "1.4.7" +compose-multiplatform = "1.5.1" appcompat = "1.7.1" material = "1.6.1" lifecycle = "2.6.1" @@ -70,7 +71,7 @@ dokka = { module = "org.jetbrains.dokka:kotlin-as-java-plugin", version.ref = "k cloudy = { module = "com.github.skydoves:cloudy", version.ref = "cloudy" } -androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidx-test-rules"} +androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidx-test-rules" } [bundles] @@ -95,4 +96,6 @@ library = { id = "com.android.library", version.ref = "gradle" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } dokka = { id = "org.jetbrains.dokka", version.ref = "kotlin" } -gradle-nexus = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "gradle-nexus"} +gradle-nexus = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "gradle-nexus" } +multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +multiplatform-compose = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar old mode 100644 new mode 100755 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties old mode 100644 new mode 100755 diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/gradlew.bat b/gradlew.bat old mode 100644 new mode 100755 diff --git a/iosArm64Main b/iosArm64Main new file mode 120000 index 0000000..46be4b8 --- /dev/null +++ b/iosArm64Main @@ -0,0 +1 @@ +iosX64Main \ No newline at end of file diff --git a/multiplatformSample/build.gradle.kts b/multiplatformSample/build.gradle.kts new file mode 100755 index 0000000..aa4add9 --- /dev/null +++ b/multiplatformSample/build.gradle.kts @@ -0,0 +1,69 @@ +import com.ujizin.camposer.Config + +plugins { + kotlin("multiplatform") + id("com.android.library") + id("org.jetbrains.compose") +} + +@OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class) +kotlin { + targetHierarchy.default() + + androidTarget { + compilations.all { + kotlinOptions { + jvmTarget = "1.8" + } + } + } + + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { + it.binaries.framework { + baseName = "multiplatformSample" + } + } + + sourceSets { + val commonMain by getting { + dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + implementation(project(":camposer")) + //put your multiplatform dependencies here + } + } + val commonTest by getting { + dependencies { + implementation(kotlin("test")) + } + } + val androidMain by getting { + dependencies { + implementation(libs.accompanist.permissions) + } + } + +// val iosX64Main by getting +// val iosArm64Main by getting +// val iosSimulatorArm64Main by getting +// val iosMain by creating { +// dependsOn(commonMain) +// iosX64Main.dependsOn(this) +// iosArm64Main.dependsOn(this) +// iosSimulatorArm64Main.dependsOn(this) +// } + } +} + +android { + namespace = "com.ujizin.multiplatform_sample" + compileSdk = Config.compileSdk + defaultConfig { + minSdk = Config.minSdk + } +} \ No newline at end of file diff --git a/multiplatformSample/src/androidMain/AndroidManifest.xml b/multiplatformSample/src/androidMain/AndroidManifest.xml new file mode 100755 index 0000000..4dc5b34 --- /dev/null +++ b/multiplatformSample/src/androidMain/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/multiplatformSample/src/androidMain/kotlin/com/ujizin/multiplatform_sample/Permission.kt b/multiplatformSample/src/androidMain/kotlin/com/ujizin/multiplatform_sample/Permission.kt new file mode 100755 index 0000000..2c85222 --- /dev/null +++ b/multiplatformSample/src/androidMain/kotlin/com/ujizin/multiplatform_sample/Permission.kt @@ -0,0 +1,40 @@ +package com.ujizin.multiplatform_sample + +import android.Manifest +import android.os.Build +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import com.google.accompanist.permissions.ExperimentalPermissionsApi +import com.google.accompanist.permissions.rememberMultiplePermissionsState + +@OptIn(ExperimentalPermissionsApi::class) +@Composable +actual fun Permission(content: @Composable () -> Unit) { + val permissionsState = rememberMultiplePermissionsState( + mutableListOf( + Manifest.permission.CAMERA, + Manifest.permission.RECORD_AUDIO, + ).apply { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + add(Manifest.permission.POST_NOTIFICATIONS) + add(Manifest.permission.READ_MEDIA_AUDIO) + add(Manifest.permission.READ_MEDIA_VIDEO) + add(Manifest.permission.READ_MEDIA_IMAGES) + } else { + add(Manifest.permission.READ_EXTERNAL_STORAGE) + } + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + add(Manifest.permission.WRITE_EXTERNAL_STORAGE) + } + } + ) + + if (permissionsState.allPermissionsGranted) { + content() + } + + LaunchedEffect(Unit) { + permissionsState.launchMultiplePermissionRequest() + } +} \ No newline at end of file diff --git a/multiplatformSample/src/commonMain/kotlin/com/ujizin/multiplatform_sample/CameraScreen.kt b/multiplatformSample/src/commonMain/kotlin/com/ujizin/multiplatform_sample/CameraScreen.kt new file mode 100755 index 0000000..61e2bc2 --- /dev/null +++ b/multiplatformSample/src/commonMain/kotlin/com/ujizin/multiplatform_sample/CameraScreen.kt @@ -0,0 +1,21 @@ +package com.ujizin.multiplatform_sample + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.ujizin.camposer.CameraPreview +import com.ujizin.camposer.state.rememberCameraState + +@Composable +fun MultiplatformCameraScreen() { + Permission { + val cameraState = rememberCameraState() + CameraPreview( + modifier = Modifier.fillMaxSize(), + cameraState = cameraState + ) { } + } +} + +@Composable +expect fun Permission(content: @Composable () -> Unit) \ No newline at end of file diff --git a/multiplatformSample/src/iosMain/kotlin/com/ujizin/multiplatform_sample/MainViewController.kt b/multiplatformSample/src/iosMain/kotlin/com/ujizin/multiplatform_sample/MainViewController.kt new file mode 100755 index 0000000..8ccef88 --- /dev/null +++ b/multiplatformSample/src/iosMain/kotlin/com/ujizin/multiplatform_sample/MainViewController.kt @@ -0,0 +1,9 @@ +package com.ujizin.multiplatform_sample + +import androidx.compose.foundation.text.BasicText +import androidx.compose.ui.window.ComposeUIViewController + +fun MainViewController() = ComposeUIViewController { + BasicText("Hello") +// MultiplatformCameraScreen() +} \ No newline at end of file diff --git a/multiplatformSample/src/iosMain/kotlin/com/ujizin/multiplatform_sample/Permission.kt b/multiplatformSample/src/iosMain/kotlin/com/ujizin/multiplatform_sample/Permission.kt new file mode 100755 index 0000000..1014d12 --- /dev/null +++ b/multiplatformSample/src/iosMain/kotlin/com/ujizin/multiplatform_sample/Permission.kt @@ -0,0 +1,23 @@ +package com.ujizin.multiplatform_sample + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import platform.AVFoundation.AVCaptureDevice +import platform.AVFoundation.AVMediaTypeVideo +import platform.AVFoundation.requestAccessForMediaType + +@Composable +actual fun Permission(content: @Composable () -> Unit) { + var granted by remember { mutableStateOf(false) } + LaunchedEffect(Unit) { + AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo) { response -> + granted = response + } + } + + if (granted) content() +} \ No newline at end of file diff --git a/sample/.gitignore b/sample/.gitignore old mode 100644 new mode 100755 diff --git a/sample/README.md b/sample/README.md old mode 100644 new mode 100755 diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts old mode 100644 new mode 100755 index 161cad4..dea69e4 --- a/sample/build.gradle.kts +++ b/sample/build.gradle.kts @@ -17,11 +17,11 @@ android { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "17" } buildFeatures { compose = true @@ -62,4 +62,7 @@ dependencies { implementation(libs.cloudy) implementation(project(":camposer")) + + // Multiplatform Sample + implementation(project(":multiplatformSample")) } diff --git a/sample/proguard-rules.pro b/sample/proguard-rules.pro old mode 100644 new mode 100755 diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/ic_launcher-playstore.png b/sample/src/main/ic_launcher-playstore.png old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/CamposerTheme.kt b/sample/src/main/java/com/ujizin/sample/CamposerTheme.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/MainActivity.kt b/sample/src/main/java/com/ujizin/sample/MainActivity.kt old mode 100644 new mode 100755 index 0f3676d..f7eb3f3 --- a/sample/src/main/java/com/ujizin/sample/MainActivity.kt +++ b/sample/src/main/java/com/ujizin/sample/MainActivity.kt @@ -10,6 +10,7 @@ import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument +import com.ujizin.multiplatform_sample.MultiplatformCameraScreen import com.ujizin.sample.feature.camera.CameraScreen import com.ujizin.sample.feature.configuration.ConfigurationScreen import com.ujizin.sample.feature.gallery.GalleryScreen @@ -39,10 +40,11 @@ class MainActivity : ComponentActivity() { fun NavGraph(navHost: NavHostController) { NavHost(navHost, startDestination = Router.Camera.route) { route(Router.Camera) { - CameraScreen( - onGalleryClick = { navHost.navigate(Router.Gallery) }, - onConfigurationClick = { navHost.navigate(Router.Configuration) } - ) + MultiplatformCameraScreen() +// CameraScreen( +// onGalleryClick = { navHost.navigate(Router.Gallery) }, +// onConfigurationClick = { navHost.navigate(Router.Configuration) } +// ) } route(Router.Gallery) { GalleryScreen( diff --git a/sample/src/main/java/com/ujizin/sample/SampleApplication.kt b/sample/src/main/java/com/ujizin/sample/SampleApplication.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/components/Section.kt b/sample/src/main/java/com/ujizin/sample/components/Section.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/data/local/User.kt b/sample/src/main/java/com/ujizin/sample/data/local/User.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/data/local/UserStore.kt b/sample/src/main/java/com/ujizin/sample/data/local/UserStore.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/data/local/datasource/FileDataSource.kt b/sample/src/main/java/com/ujizin/sample/data/local/datasource/FileDataSource.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/data/local/datasource/UserDataSource.kt b/sample/src/main/java/com/ujizin/sample/data/local/datasource/UserDataSource.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/data/mapper/UserMapper.kt b/sample/src/main/java/com/ujizin/sample/data/mapper/UserMapper.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/di/Modules.kt b/sample/src/main/java/com/ujizin/sample/di/Modules.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/domain/User.kt b/sample/src/main/java/com/ujizin/sample/domain/User.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/extensions/FileExtensions.kt b/sample/src/main/java/com/ujizin/sample/extensions/FileExtensions.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/extensions/FloatExtensions.kt b/sample/src/main/java/com/ujizin/sample/extensions/FloatExtensions.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/extensions/IntExtensions.kt b/sample/src/main/java/com/ujizin/sample/extensions/IntExtensions.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/extensions/LifecycleExtensions.kt b/sample/src/main/java/com/ujizin/sample/extensions/LifecycleExtensions.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/extensions/ModifierExtensions.kt b/sample/src/main/java/com/ujizin/sample/extensions/ModifierExtensions.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/extensions/ReaderExtensions.kt b/sample/src/main/java/com/ujizin/sample/extensions/ReaderExtensions.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/extensions/StringExtensions.kt b/sample/src/main/java/com/ujizin/sample/extensions/StringExtensions.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/CameraScreen.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/CameraScreen.kt old mode 100644 new mode 100755 index a558bd5..ad148dd --- a/sample/src/main/java/com/ujizin/sample/feature/camera/CameraScreen.kt +++ b/sample/src/main/java/com/ujizin/sample/feature/camera/CameraScreen.kt @@ -24,6 +24,7 @@ import com.skydoves.cloudy.Cloudy import com.ujizin.camposer.CameraPreview import com.ujizin.camposer.state.CamSelector import com.ujizin.camposer.state.CameraState +import com.ujizin.camposer.state.inverse import com.ujizin.camposer.state.rememberCamSelector import com.ujizin.camposer.state.rememberCameraState import com.ujizin.camposer.state.rememberFlashMode @@ -114,10 +115,10 @@ fun CameraSection( zoomRatio = it }, onSwitchToFront = { bitmap -> - Cloudy(radius = 20) { Image(bitmap.asImageBitmap(), contentDescription = null) } + Cloudy(radius = 20) { Image(bitmap, contentDescription = null) } }, onSwitchToBack = { bitmap -> - Cloudy(radius = 20) { Image(bitmap.asImageBitmap(), contentDescription = null) } + Cloudy(radius = 20) { Image(bitmap, contentDescription = null) } } ) { BlinkPictureBox(lastPicture, cameraOption == CameraOption.Video) diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/CameraViewModel.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/CameraViewModel.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/components/ActionsBox.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/components/ActionsBox.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/components/BlinkPictureBox.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/components/BlinkPictureBox.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/components/Button.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/components/Button.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/components/ConfigurationSection.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/components/ConfigurationSection.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/components/FlashSection.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/components/FlashSection.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/components/OptionSection.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/components/OptionSection.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/components/PictureActions.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/components/PictureActions.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/components/QrCodeBox.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/components/QrCodeBox.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/components/SettingsBox.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/components/SettingsBox.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/components/VideoBox.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/components/VideoBox.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/mapper/FlashMapper.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/mapper/FlashMapper.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/model/CameraOption.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/model/CameraOption.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/camera/model/Flash.kt b/sample/src/main/java/com/ujizin/sample/feature/camera/model/Flash.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/configuration/ConfigurationScreen.kt b/sample/src/main/java/com/ujizin/sample/feature/configuration/ConfigurationScreen.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/configuration/ConfigurationViewModel.kt b/sample/src/main/java/com/ujizin/sample/feature/configuration/ConfigurationViewModel.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/gallery/GalleryScreen.kt b/sample/src/main/java/com/ujizin/sample/feature/gallery/GalleryScreen.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/gallery/GalleryViewModel.kt b/sample/src/main/java/com/ujizin/sample/feature/gallery/GalleryViewModel.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/permission/AppPermission.kt b/sample/src/main/java/com/ujizin/sample/feature/permission/AppPermission.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/preview/PreviewScreen.kt b/sample/src/main/java/com/ujizin/sample/feature/preview/PreviewScreen.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/feature/preview/PreviewViewModel.kt b/sample/src/main/java/com/ujizin/sample/feature/preview/PreviewViewModel.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/router/Args.kt b/sample/src/main/java/com/ujizin/sample/router/Args.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/router/Router.kt b/sample/src/main/java/com/ujizin/sample/router/Router.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/java/com/ujizin/sample/router/RouterExtensions.kt b/sample/src/main/java/com/ujizin/sample/router/RouterExtensions.kt old mode 100644 new mode 100755 diff --git a/sample/src/main/res/drawable/configuration.xml b/sample/src/main/res/drawable/configuration.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/drawable/flash_always.xml b/sample/src/main/res/drawable/flash_always.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/drawable/flash_auto.xml b/sample/src/main/res/drawable/flash_auto.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/drawable/flash_off.xml b/sample/src/main/res/drawable/flash_off.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/drawable/flash_on.xml b/sample/src/main/res/drawable/flash_on.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/drawable/refresh.xml b/sample/src/main/res/drawable/refresh.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-hdpi/ic_launcher.png b/sample/src/main/res/mipmap-hdpi/ic_launcher.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/sample/src/main/res/mipmap-hdpi/ic_launcher_foreground.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-mdpi/ic_launcher.png b/sample/src/main/res/mipmap-mdpi/ic_launcher.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/sample/src/main/res/mipmap-mdpi/ic_launcher_foreground.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-xhdpi/ic_launcher.png b/sample/src/main/res/mipmap-xhdpi/ic_launcher.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/sample/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png b/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/sample/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png old mode 100644 new mode 100755 diff --git a/sample/src/main/res/values-night/themes.xml b/sample/src/main/res/values-night/themes.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/values/colors.xml b/sample/src/main/res/values/colors.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/values/ic_launcher_background.xml b/sample/src/main/res/values/ic_launcher_background.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/values/themes.xml b/sample/src/main/res/values/themes.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/xml/backup_rules.xml b/sample/src/main/res/xml/backup_rules.xml old mode 100644 new mode 100755 diff --git a/sample/src/main/res/xml/data_extraction_rules.xml b/sample/src/main/res/xml/data_extraction_rules.xml old mode 100644 new mode 100755 diff --git a/sampleIos/sampleIos/Assets.xcassets/AccentColor.colorset/Contents.json b/sampleIos/sampleIos/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100755 index 0000000..eb87897 --- /dev/null +++ b/sampleIos/sampleIos/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/sampleIos/sampleIos/Assets.xcassets/AppIcon.appiconset/Contents.json b/sampleIos/sampleIos/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 0000000..13613e3 --- /dev/null +++ b/sampleIos/sampleIos/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/sampleIos/sampleIos/Assets.xcassets/Contents.json b/sampleIos/sampleIos/Assets.xcassets/Contents.json new file mode 100755 index 0000000..73c0059 --- /dev/null +++ b/sampleIos/sampleIos/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/sampleIos/sampleIos/Preview Content/Preview Assets.xcassets/Contents.json b/sampleIos/sampleIos/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100755 index 0000000..73c0059 --- /dev/null +++ b/sampleIos/sampleIos/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/scripts/publish-module.gradle b/scripts/publish-module.gradle old mode 100644 new mode 100755 diff --git a/scripts/publish-root.gradle b/scripts/publish-root.gradle old mode 100644 new mode 100755 diff --git a/settings.gradle.kts b/settings.gradle.kts old mode 100644 new mode 100755 index 61a1385..24082af --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,14 +6,43 @@ pluginManagement { } } dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) repositories { google() mavenCentral() - mavenLocal() + // workaround for https://youtrack.jetbrains.com/issue/KT-51379 + exclusiveContent { + forRepository { + ivy("https://download.jetbrains.com/kotlin/native/builds") { + name = "Kotlin Native" + patternLayout { + + // example download URLs: + // https://download.jetbrains.com/kotlin/native/builds/releases/1.7.20/linux-x86_64/kotlin-native-prebuilt-linux-x86_64-1.7.20.tar.gz + // https://download.jetbrains.com/kotlin/native/builds/releases/1.7.20/windows-x86_64/kotlin-native-prebuilt-windows-x86_64-1.7.20.zip + // https://download.jetbrains.com/kotlin/native/builds/releases/1.7.20/macos-x86_64/kotlin-native-prebuilt-macos-x86_64-1.7.20.tar.gz + listOf( + "macos-x86_64", + "macos-aarch64", + "osx-x86_64", + "osx-aarch64", + "linux-x86_64", + "windows-x86_64", + ).forEach { os -> + listOf("dev", "releases").forEach { stage -> + artifact("$stage/[revision]/$os/[artifact]-[revision].[ext]") + } + } + } + metadataSources { artifact() } + } + } + filter { includeModuleByRegex(".*", ".*kotlin-native-prebuilt.*") } + } } } rootProject.name = "Camposer" include(":sample") include(":camposer") +include(":multiplatformSample")