From 96f341614f7d32476ecda9b48c482930d13cce04 Mon Sep 17 00:00:00 2001 From: Yahia Date: Wed, 30 Oct 2024 13:25:50 +0300 Subject: [PATCH 1/7] Update Gradle version to support the latest Android Studio. --- gradle/wrapper/gradle-wrapper.properties | 2 +- iosApp/Pods/Pods.xcodeproj/project.pbxproj | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c29397f..c7fa2b7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Fri Feb 23 16:09:51 EET 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/iosApp/Pods/Pods.xcodeproj/project.pbxproj b/iosApp/Pods/Pods.xcodeproj/project.pbxproj index 79b2f1d..9929bee 100644 --- a/iosApp/Pods/Pods.xcodeproj/project.pbxproj +++ b/iosApp/Pods/Pods.xcodeproj/project.pbxproj @@ -308,6 +308,7 @@ en, ); mainGroup = CF1408CF629C7361332E53B88F7BD30C; + minimizedProjectReferenceProxies = 0; productRefGroup = 1F86AA6785DF34AFD5A71790761717DE /* Products */; projectDirPath = ""; projectRoot = ""; From f76e0281f73b8f14684f04c9cac0ef92c568cb92 Mon Sep 17 00:00:00 2001 From: Yahia Date: Wed, 30 Oct 2024 13:39:24 +0300 Subject: [PATCH 2/7] Make the whole image card clickable. --- .../yahiaangelo/filmsimulator/screens/home/HomeScreen.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt index 68c17b3..2c7ad10 100644 --- a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt +++ b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt @@ -161,12 +161,13 @@ data class HomeScreen( colors = CardDefaults.cardColors( containerColor = MaterialTheme.colorScheme.surface, ), - border = CardDefaults.outlinedCardBorder() + border = CardDefaults.outlinedCardBorder(), + onClick = onImageChooseClick ) { Box(modifier = Modifier.fillMaxSize()) { imageBitmap?.let { Image(modifier = Modifier.fillMaxSize(), bitmap = imageBitmap, contentDescription = null) - } ?: IconButton(modifier = Modifier.align(Alignment.Center).size(150.dp), onClick = onImageChooseClick) { + } ?: IconButton(modifier = Modifier.align(Alignment.Center).size(150.dp), onClick = onImageChooseClick ) { Column { Icon(painter = painterResource(Res.drawable.ic_image_add_24), null, From 9203d702d4a6e8d8504f4de4c92fb6aeed86159b Mon Sep 17 00:00:00 2001 From: Yahia Date: Sat, 9 Nov 2024 22:45:26 +0200 Subject: [PATCH 3/7] Fix Luts bottom sheet text color and keyboard visibility. --- .../filmsimulator/screens/home/HomeScreen.kt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt index 2c7ad10..37d32b9 100644 --- a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt +++ b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt @@ -7,9 +7,11 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.ime import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -45,11 +47,13 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.koin.getScreenModel import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow +import com.example.compose.AppTheme import com.preat.peekaboo.image.picker.ResizeOptions import com.preat.peekaboo.image.picker.SelectionMode import com.preat.peekaboo.image.picker.rememberImagePickerLauncher @@ -232,7 +236,8 @@ data class HomeScreen( if (showBottomSheet) { ModalBottomSheet( onDismissRequest = onDismissRequest, - sheetState = sheetState + sheetState = sheetState, + windowInsets = WindowInsets.ime ) { FilmLutsList(filmLuts = filmLuts, onItemClick = onItemClick) } @@ -266,8 +271,9 @@ data class HomeScreen( leadingIcon = { Icon(Icons.Filled.Search, contentDescription = "Search") }, - singleLine = true - ) + textStyle = TextStyle(color = MaterialTheme.colorScheme.onSurface), + singleLine = true, + ) // List LazyColumn { From 19cd4027a5f43065f596ff81b1ef52e99b893f3e Mon Sep 17 00:00:00 2001 From: Yahia Date: Wed, 13 Nov 2024 21:17:36 +0200 Subject: [PATCH 4/7] Upgrade Kotlin, Compose, and other libs. --- .gitignore | 3 +- androidApp/build.gradle.kts | 4 +- build.gradle.kts | 1 + gradle/libs.versions.toml | 21 +++--- iosApp/Podfile.lock | 2 +- .../Pods/Local Podspecs/shared.podspec.json | 5 +- iosApp/Pods/Manifest.lock | 2 +- iosApp/Pods/Pods.xcodeproj/project.pbxproj | 69 +++++++++---------- ...App-resources-Debug-input-files.xcfilelist | 2 +- ...p-resources-Release-input-files.xcfilelist | 2 +- .../Pods-iosApp/Pods-iosApp-resources.sh | 4 +- .../Pods-iosApp/Pods-iosApp.debug.xcconfig | 1 + .../Pods-iosApp/Pods-iosApp.release.xcconfig | 1 + .../shared/shared.debug.xcconfig | 1 + .../shared/shared.release.xcconfig | 1 + iosApp/iosApp.xcodeproj/project.pbxproj | 32 ++++----- shared/build.gradle.kts | 16 +++-- shared/shared.podspec | 8 ++- .../source/local/DriverFactory.android.kt | 7 +- .../data/source/local/AppDatabase.kt | 3 +- .../data/source/local/DriverFactory.kt | 5 +- .../filmsimulator/screens/home/HomeScreen.kt | 2 +- .../data/source/local/DriverFactory.ios.kt | 3 +- 23 files changed, 106 insertions(+), 89 deletions(-) diff --git a/.gitignore b/.gitignore index e510fa9..9872784 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ captures .externalNativeBuild .cxx local.properties -xcuserdata \ No newline at end of file +xcuserdata +.kotlin \ No newline at end of file diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 4d84b59..e037b64 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -1,6 +1,7 @@ plugins { alias(libs.plugins.androidApplication) alias(libs.plugins.kotlinAndroid) + alias(libs.plugins.compose.compiler) } android { @@ -16,9 +17,6 @@ android { buildFeatures { compose = true } - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get() - } packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" diff --git a/build.gradle.kts b/build.gradle.kts index 31816b2..1810cba 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,4 +5,5 @@ plugins { alias(libs.plugins.kotlinAndroid).apply(false) alias(libs.plugins.kotlinMultiplatform).apply(false) alias(libs.plugins.kotlinCocoapods).apply(false) + alias(libs.plugins.compose.compiler).apply(false) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ef738ed..d1033cf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,27 +1,25 @@ [versions] agp = "8.2.2" imageLoader = "1.7.6" -kotlin = "1.9.23" -compose = "1.6.4" -compose-compiler = "1.5.11" -compose-material3 = "1.2.1" -androidx-activityCompose = "1.8.2" +kotlin = "2.0.21" +compose = "1.7.5" +compose-material3 = "1.3.1" +androidx-activityCompose = "1.9.3" logging = "1.4.2" materialKolor = "1.4.0-rc03" multiplatformSettings = "1.1.1" nativeDriver = "2.0.1" -runtime = "2.0.1" +runtime = "2.0.2" statelyCommon = "2.0.5" voyager = "1.0.0" -koin = "3.6.0-alpha1" +koin = "4.0.0" peekaboo = "0.5.2" -datastoreCore = "1.0.0" +datastoreCore = "1.1.1" okio = "3.8.0" -ktorVersion = "2.3.7" +ktorVersion = "3.0.1" ffmpegKitMin = "6.0-2" -compose-plugin = "1.5.12" kotlinxCoroutinesCore = "1.8.0" -lifecycleViewmodelKtx = "2.7.0" +lifecycleViewmodelKtx = "2.8.7" ui-tooling-preview = "1.6.0-rc01" @@ -83,3 +81,4 @@ kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } kotlinCocoapods = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref = "kotlin" } jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose" } +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } diff --git a/iosApp/Podfile.lock b/iosApp/Podfile.lock index 3dd2808..9a5b269 100644 --- a/iosApp/Podfile.lock +++ b/iosApp/Podfile.lock @@ -16,7 +16,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: ffmpeg-kit-ios-min: 4e9a088f4ee9629435960b9d68e54848975f1931 - shared: 1dc9166a317ad22197cf7761852e101ba289f3f3 + shared: 6419e7c8fb21241ba0c49addcb31dda09030478e PODFILE CHECKSUM: 78d6cc1b71b232202c48a29d4e6c34972c534c73 diff --git a/iosApp/Pods/Local Podspecs/shared.podspec.json b/iosApp/Pods/Local Podspecs/shared.podspec.json index 0213421..b03f605 100644 --- a/iosApp/Pods/Local Podspecs/shared.podspec.json +++ b/iosApp/Pods/Local Podspecs/shared.podspec.json @@ -18,6 +18,9 @@ "6.0" ] }, + "xcconfig": { + "ENABLE_USER_SCRIPT_SANDBOXING": "NO" + }, "pod_target_xcconfig": { "KOTLIN_PROJECT_PATH": ":shared", "PRODUCT_MODULE_NAME": "shared" @@ -31,6 +34,6 @@ } ], "resources": [ - "build/compose/ios/shared/compose-resources" + "build/compose/cocoapods/compose-resources" ] } diff --git a/iosApp/Pods/Manifest.lock b/iosApp/Pods/Manifest.lock index 3dd2808..9a5b269 100644 --- a/iosApp/Pods/Manifest.lock +++ b/iosApp/Pods/Manifest.lock @@ -16,7 +16,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: ffmpeg-kit-ios-min: 4e9a088f4ee9629435960b9d68e54848975f1931 - shared: 1dc9166a317ad22197cf7761852e101ba289f3f3 + shared: 6419e7c8fb21241ba0c49addcb31dda09030478e PODFILE CHECKSUM: 78d6cc1b71b232202c48a29d4e6c34972c534c73 diff --git a/iosApp/Pods/Pods.xcodeproj/project.pbxproj b/iosApp/Pods/Pods.xcodeproj/project.pbxproj index 9929bee..f4d2649 100644 --- a/iosApp/Pods/Pods.xcodeproj/project.pbxproj +++ b/iosApp/Pods/Pods.xcodeproj/project.pbxproj @@ -61,21 +61,19 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 008A9DE816B822B93AFB1BC05161EE9F /* shared.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = shared.debug.xcconfig; sourceTree = ""; }; 013F2B0FB161E3CACA48926B22452383 /* ffmpeg-kit-ios-min.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "ffmpeg-kit-ios-min.release.xcconfig"; sourceTree = ""; }; 015E0D7EA7331961AB63E5AFECA86BB5 /* Pods-iosApp-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iosApp-umbrella.h"; sourceTree = ""; }; 0C26DE34362E7855FE135F3A259F7034 /* libswresample.xcframework */ = {isa = PBXFileReference; includeInIndex = 1; path = libswresample.xcframework; sourceTree = ""; }; 11C9B998CE0869936AE6BE69270DAAC9 /* Pods-iosApp.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iosApp.modulemap"; sourceTree = ""; }; - 203F11D202CA1846ED6084F2F3A2CCD4 /* compose-resources */ = {isa = PBXFileReference; includeInIndex = 1; name = "compose-resources"; path = "build/compose/ios/shared/compose-resources"; sourceTree = ""; }; 244FC2DAA936A0B07ACEFDC74E2D54B8 /* Pods-iosApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iosApp.release.xcconfig"; sourceTree = ""; }; 2C046CF45FFB7177FE9F5831D09EB5B3 /* ffmpeg-kit-ios-min-xcframeworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "ffmpeg-kit-ios-min-xcframeworks.sh"; sourceTree = ""; }; 3178D6A3F0BF6A7E42EDF36FF66FE277 /* libavdevice.xcframework */ = {isa = PBXFileReference; includeInIndex = 1; path = libavdevice.xcframework; sourceTree = ""; }; 4C555135229E162F55768A39C83DECD7 /* libavfilter.xcframework */ = {isa = PBXFileReference; includeInIndex = 1; path = libavfilter.xcframework; sourceTree = ""; }; + 4DAD13487B641E6B9D7476999E775A45 /* shared.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = shared.debug.xcconfig; sourceTree = ""; }; 55ABB06C8A1800962A74E007E7733796 /* Pods-iosApp-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-iosApp-frameworks.sh"; sourceTree = ""; }; 6F3B5FED07117E377CFAC3D49B490F17 /* Pods-iosApp-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-iosApp-resources.sh"; sourceTree = ""; }; 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 76A263267985B0185D85E24D40FCEE9A /* Pods-iosApp-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iosApp-Info.plist"; sourceTree = ""; }; - 76A970C5768DEF9352C145D1637136A3 /* shared.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = shared.release.xcconfig; sourceTree = ""; }; 76D28488EA8CF5C697DFF07967A9960E /* Pods-iosApp-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iosApp-acknowledgements.plist"; sourceTree = ""; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; A2A7C54F60039AF4ECDECB9306E9CEA4 /* libavcodec.xcframework */ = {isa = PBXFileReference; includeInIndex = 1; path = libavcodec.xcframework; sourceTree = ""; }; @@ -83,13 +81,15 @@ B097DD7534E741D5C41838011D755842 /* Pods-iosApp */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-iosApp"; path = Pods_iosApp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B7836F98159946618ADC2ADE4ADD2C85 /* ffmpeg-kit-ios-min.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "ffmpeg-kit-ios-min.debug.xcconfig"; sourceTree = ""; }; BF11CEFAA4E133866DAED1022F9A9CC5 /* ffmpegkit.xcframework */ = {isa = PBXFileReference; includeInIndex = 1; path = ffmpegkit.xcframework; sourceTree = ""; }; - CB3DDB432A4FDC06767575C61C8ADA0A /* shared.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = shared.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; CDA3FAE3B65714C2124A3871DA13B1D8 /* libavutil.xcframework */ = {isa = PBXFileReference; includeInIndex = 1; path = libavutil.xcframework; sourceTree = ""; }; - CEF5FB4EEEFBEA291F9DDEDDDF0BE0C4 /* shared.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = shared.framework; path = build/cocoapods/framework/shared.framework; sourceTree = ""; }; + CE6991E448B5709365FFBCAB5EF9A9B4 /* shared.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = shared.framework; path = build/cocoapods/framework/shared.framework; sourceTree = ""; }; + E2E6BF268E792329201BC2BF5DE0B8DB /* shared.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = shared.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + E39BE12967CFA5BCDF680F7E8376943C /* shared.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = shared.release.xcconfig; sourceTree = ""; }; E462E23B3674BF94EAB1504D506F2803 /* Pods-iosApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iosApp.debug.xcconfig"; sourceTree = ""; }; E4C923318724794E3CC670804C2D6A6B /* Pods-iosApp-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iosApp-acknowledgements.markdown"; sourceTree = ""; }; E6DB2A5F5DADA1DDE45F36B1A2D6AC16 /* Pods-iosApp-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iosApp-dummy.m"; sourceTree = ""; }; EE88B256A456992CD9FD4F64354D4398 /* libavformat.xcframework */ = {isa = PBXFileReference; includeInIndex = 1; path = libavformat.xcframework; sourceTree = ""; }; + F064C0D7CE795102A652A82AEBBA7514 /* compose-resources */ = {isa = PBXFileReference; includeInIndex = 1; name = "compose-resources"; path = "build/compose/cocoapods/compose-resources"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -135,40 +135,52 @@ name = Frameworks; sourceTree = ""; }; - 39F973608F645D55C358F8551EDDE8C5 /* Frameworks */ = { + 244B481B25AE39ED2811E8ED93C90033 /* Frameworks */ = { isa = PBXGroup; children = ( - CEF5FB4EEEFBEA291F9DDEDDDF0BE0C4 /* shared.framework */, + CE6991E448B5709365FFBCAB5EF9A9B4 /* shared.framework */, ); name = Frameworks; sourceTree = ""; }; - 4DBDADB176ABA72B7926BAC46D471E26 /* ffmpeg-kit-ios-min */ = { + 2E499C4A5F1591C71B6F87A09468D6A7 /* Support Files */ = { isa = PBXGroup; children = ( - 2087C46290E4F92C4191DE0F17F0E022 /* Frameworks */, - FC2E35F1E44487B58F03631DC1704362 /* Support Files */, + 4DAD13487B641E6B9D7476999E775A45 /* shared.debug.xcconfig */, + E39BE12967CFA5BCDF680F7E8376943C /* shared.release.xcconfig */, ); - name = "ffmpeg-kit-ios-min"; - path = "ffmpeg-kit-ios-min"; + name = "Support Files"; + path = "../iosApp/Pods/Target Support Files/shared"; + sourceTree = ""; + }; + 40443BD2A1BD6FFE32B582A00ABBCF31 /* shared */ = { + isa = PBXGroup; + children = ( + F064C0D7CE795102A652A82AEBBA7514 /* compose-resources */, + 244B481B25AE39ED2811E8ED93C90033 /* Frameworks */, + 4A34E35645B6AB5ADA95001E5FA8730B /* Pod */, + 2E499C4A5F1591C71B6F87A09468D6A7 /* Support Files */, + ); + name = shared; + path = ../../shared; sourceTree = ""; }; - 4F9652C7FDB8CFF118333C17A5A41C8F /* Pod */ = { + 4A34E35645B6AB5ADA95001E5FA8730B /* Pod */ = { isa = PBXGroup; children = ( - CB3DDB432A4FDC06767575C61C8ADA0A /* shared.podspec */, + E2E6BF268E792329201BC2BF5DE0B8DB /* shared.podspec */, ); name = Pod; sourceTree = ""; }; - 5010BA8DC1346A70C49ED90E48C98857 /* Support Files */ = { + 4DBDADB176ABA72B7926BAC46D471E26 /* ffmpeg-kit-ios-min */ = { isa = PBXGroup; children = ( - 008A9DE816B822B93AFB1BC05161EE9F /* shared.debug.xcconfig */, - 76A970C5768DEF9352C145D1637136A3 /* shared.release.xcconfig */, + 2087C46290E4F92C4191DE0F17F0E022 /* Frameworks */, + FC2E35F1E44487B58F03631DC1704362 /* Support Files */, ); - name = "Support Files"; - path = "../iosApp/Pods/Target Support Files/shared"; + name = "ffmpeg-kit-ios-min"; + path = "ffmpeg-kit-ios-min"; sourceTree = ""; }; 578452D2E740E91742655AC8F1636D1F /* iOS */ = { @@ -182,23 +194,11 @@ 58AAD176B64323B9974E5B70EC8B12DC /* Development Pods */ = { isa = PBXGroup; children = ( - 8BADB6F22C77C34444BC9D80F04C298D /* shared */, + 40443BD2A1BD6FFE32B582A00ABBCF31 /* shared */, ); name = "Development Pods"; sourceTree = ""; }; - 8BADB6F22C77C34444BC9D80F04C298D /* shared */ = { - isa = PBXGroup; - children = ( - 203F11D202CA1846ED6084F2F3A2CCD4 /* compose-resources */, - 39F973608F645D55C358F8551EDDE8C5 /* Frameworks */, - 4F9652C7FDB8CFF118333C17A5A41C8F /* Pod */, - 5010BA8DC1346A70C49ED90E48C98857 /* Support Files */, - ); - name = shared; - path = ../../shared; - sourceTree = ""; - }; BA6B7BC2729F657E9D3682E55CA6E980 /* Pods-iosApp */ = { isa = PBXGroup; children = ( @@ -308,7 +308,6 @@ en, ); mainGroup = CF1408CF629C7361332E53B88F7BD30C; - minimizedProjectReferenceProxies = 0; productRefGroup = 1F86AA6785DF34AFD5A71790761717DE /* Products */; projectDirPath = ""; projectRoot = ""; @@ -530,7 +529,7 @@ }; 8321CE5EFDE3FE010676D577F1C37DD7 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 76A970C5768DEF9352C145D1637136A3 /* shared.release.xcconfig */; + baseConfigurationReference = E39BE12967CFA5BCDF680F7E8376943C /* shared.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -548,7 +547,7 @@ }; DA1AC91C21B064AE122CD541A5F8A190 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 008A9DE816B822B93AFB1BC05161EE9F /* shared.debug.xcconfig */; + baseConfigurationReference = 4DAD13487B641E6B9D7476999E775A45 /* shared.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; diff --git a/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources-Debug-input-files.xcfilelist b/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources-Debug-input-files.xcfilelist index 098eea2..bab80cf 100644 --- a/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources-Debug-input-files.xcfilelist +++ b/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources-Debug-input-files.xcfilelist @@ -1,2 +1,2 @@ ${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh -${PODS_ROOT}/../../shared/build/compose/ios/shared/compose-resources \ No newline at end of file +${PODS_ROOT}/../../shared/build/compose/cocoapods/compose-resources \ No newline at end of file diff --git a/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources-Release-input-files.xcfilelist b/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources-Release-input-files.xcfilelist index 098eea2..bab80cf 100644 --- a/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources-Release-input-files.xcfilelist +++ b/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources-Release-input-files.xcfilelist @@ -1,2 +1,2 @@ ${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh -${PODS_ROOT}/../../shared/build/compose/ios/shared/compose-resources \ No newline at end of file +${PODS_ROOT}/../../shared/build/compose/cocoapods/compose-resources \ No newline at end of file diff --git a/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh b/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh index d005a25..c932364 100755 --- a/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh +++ b/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh @@ -97,10 +97,10 @@ EOM esac } if [[ "$CONFIGURATION" == "Debug" ]]; then - install_resource "${PODS_ROOT}/../../shared/build/compose/ios/shared/compose-resources" + install_resource "${PODS_ROOT}/../../shared/build/compose/cocoapods/compose-resources" fi if [[ "$CONFIGURATION" == "Release" ]]; then - install_resource "${PODS_ROOT}/../../shared/build/compose/ios/shared/compose-resources" + install_resource "${PODS_ROOT}/../../shared/build/compose/cocoapods/compose-resources" fi mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" diff --git a/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp.debug.xcconfig b/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp.debug.xcconfig index ee4545c..c4056ec 100644 --- a/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp.debug.xcconfig +++ b/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp.debug.xcconfig @@ -1,4 +1,5 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +ENABLE_USER_SCRIPT_SANDBOXING = NO FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../shared/build/cocoapods/framework" "${PODS_ROOT}/ffmpeg-kit-ios-min" "${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg-kit-ios-min" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' diff --git a/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp.release.xcconfig b/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp.release.xcconfig index ee4545c..c4056ec 100644 --- a/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp.release.xcconfig +++ b/iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp.release.xcconfig @@ -1,4 +1,5 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +ENABLE_USER_SCRIPT_SANDBOXING = NO FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../shared/build/cocoapods/framework" "${PODS_ROOT}/ffmpeg-kit-ios-min" "${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg-kit-ios-min" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' diff --git a/iosApp/Pods/Target Support Files/shared/shared.debug.xcconfig b/iosApp/Pods/Target Support Files/shared/shared.debug.xcconfig index 76eec09..e3b2e6a 100644 --- a/iosApp/Pods/Target Support Files/shared/shared.debug.xcconfig +++ b/iosApp/Pods/Target Support Files/shared/shared.debug.xcconfig @@ -1,5 +1,6 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/shared +ENABLE_USER_SCRIPT_SANDBOXING = NO FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../shared/build/cocoapods/framework" "${PODS_ROOT}/ffmpeg-kit-ios-min" "${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg-kit-ios-min" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 KOTLIN_PROJECT_PATH = :shared diff --git a/iosApp/Pods/Target Support Files/shared/shared.release.xcconfig b/iosApp/Pods/Target Support Files/shared/shared.release.xcconfig index 76eec09..e3b2e6a 100644 --- a/iosApp/Pods/Target Support Files/shared/shared.release.xcconfig +++ b/iosApp/Pods/Target Support Files/shared/shared.release.xcconfig @@ -1,5 +1,6 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/shared +ENABLE_USER_SCRIPT_SANDBOXING = NO FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../shared/build/cocoapods/framework" "${PODS_ROOT}/ffmpeg-kit-ios-min" "${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg-kit-ios-min" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 KOTLIN_PROJECT_PATH = :shared diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj index 3a6fd7b..ea28c96 100644 --- a/iosApp/iosApp.xcodeproj/project.pbxproj +++ b/iosApp/iosApp.xcodeproj/project.pbxproj @@ -104,8 +104,8 @@ 7555FF77242A565900829871 /* Sources */, 7555FF79242A565900829871 /* Resources */, 5C38A09EF912860CDD16CE06 /* Frameworks */, - 83F35A7099D5B9CA4BC011BD /* [CP] Copy Pods Resources */, EA41BBBB47C5534D16BB20D2 /* [CP] Embed Pods Frameworks */, + 0736E6C19C6FAC410C4913D8 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -163,43 +163,43 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 663557A2DE9F54AD03A6E762 /* [CP] Check Pods Manifest.lock */ = { + 0736E6C19C6FAC410C4913D8 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Copy Pods Resources"; outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-iosApp-checkManifestLockResult.txt", + "${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 83F35A7099D5B9CA4BC011BD /* [CP] Copy Pods Resources */ = { + 663557A2DE9F54AD03A6E762 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources-${CONFIGURATION}-input-files.xcfilelist", ); - name = "[CP] Copy Pods Resources"; + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-iosApp-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; EA41BBBB47C5534D16BB20D2 /* [CP] Embed Pods Frameworks */ = { diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index b287926..abfde36 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -1,11 +1,13 @@ import org.jetbrains.compose.ExperimentalComposeLibrary +import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.kotlinCocoapods) alias(libs.plugins.androidLibrary) - alias(libs.plugins.jetbrainsCompose) version "1.6.2" - id("org.jetbrains.kotlin.plugin.serialization") version "1.9.22" + alias(libs.plugins.jetbrainsCompose) version "1.7.1" + alias(libs.plugins.compose.compiler) + id("org.jetbrains.kotlin.plugin.serialization") version "2.0.21" id("app.cash.sqldelight") version "2.0.1" } @@ -20,12 +22,13 @@ sqldelight { kotlin { androidTarget { - compilations.all { - kotlinOptions { - jvmTarget = "1.8" - } + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) } } + compilerOptions { + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) + } iosX64() iosArm64() iosSimulatorArm64() @@ -97,6 +100,7 @@ kotlin { nativeMain.dependencies { implementation(libs.native.driver) + implementation(libs.ktor.client.darwin) } commonTest.dependencies { implementation(libs.kotlin.test) diff --git a/shared/shared.podspec b/shared/shared.podspec index 76d980d..7dafa2d 100644 --- a/shared/shared.podspec +++ b/shared/shared.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |spec| spec.summary = 'Some description for the Shared Module' spec.vendored_frameworks = 'build/cocoapods/framework/shared.framework' spec.libraries = 'c++' - spec.ios.deployment_target = '16.0' + spec.ios.deployment_target = '16.0' spec.dependency 'ffmpeg-kit-ios-min', '6.0' if !Dir.exist?('build/cocoapods/framework/shared.framework') || Dir.empty?('build/cocoapods/framework/shared.framework') @@ -22,6 +22,10 @@ Pod::Spec.new do |spec| Alternatively, proper pod installation is performed during Gradle sync in the IDE (if Podfile location is set)" end + spec.xcconfig = { + 'ENABLE_USER_SCRIPT_SANDBOXING' => 'NO', + } + spec.pod_target_xcconfig = { 'KOTLIN_PROJECT_PATH' => ':shared', 'PRODUCT_MODULE_NAME' => 'shared', @@ -46,5 +50,5 @@ Pod::Spec.new do |spec| SCRIPT } ] - spec.resources = ['build/compose/ios/shared/compose-resources'] + spec.resources = ['build/compose/cocoapods/compose-resources'] end \ No newline at end of file diff --git a/shared/src/androidMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/DriverFactory.android.kt b/shared/src/androidMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/DriverFactory.android.kt index 7e75ed9..816e2fb 100644 --- a/shared/src/androidMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/DriverFactory.android.kt +++ b/shared/src/androidMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/DriverFactory.android.kt @@ -4,9 +4,10 @@ import android.content.Context import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.android.AndroidSqliteDriver import io.github.yahiaangelo.filmsimulator.Database +import io.github.yahiaangelo.filmsimulator.util.AppContext -actual class DriverFactory(private val context: Context) { - actual fun createDriver(): SqlDriver { - return AndroidSqliteDriver(Database.Schema, context, "film.db") +actual class DriverFactory { + actual fun createDriver(appContext: AppContext): SqlDriver { + return AndroidSqliteDriver(Database.Schema, appContext.get()!!, "film.db") } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/AppDatabase.kt b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/AppDatabase.kt index ba927ab..ab5c756 100644 --- a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/AppDatabase.kt +++ b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/AppDatabase.kt @@ -1,6 +1,7 @@ package io.github.yahiaangelo.filmsimulator.data.source.local import io.github.yahiaangelo.filmsimulator.Database +import io.github.yahiaangelo.filmsimulator.util.AppContext import org.koin.core.module.dsl.singleOf import org.koin.dsl.module @@ -13,5 +14,5 @@ val appDBModule = module { * Main endpoint for the app's local database */ internal class AppDatabase(driverFactory: DriverFactory) { - val database = Database(driverFactory.createDriver()) + val database = Database(driverFactory.createDriver(appContext = AppContext)) } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/DriverFactory.kt b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/DriverFactory.kt index 86790dd..094c435 100644 --- a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/DriverFactory.kt +++ b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/DriverFactory.kt @@ -1,10 +1,11 @@ package io.github.yahiaangelo.filmsimulator.data.source.local import app.cash.sqldelight.db.SqlDriver +import io.github.yahiaangelo.filmsimulator.util.AppContext /** * A db driver interface to create a db driver suited for every platform */ -expect class DriverFactory { - fun createDriver(): SqlDriver +expect class DriverFactory() { + fun createDriver(appContext: AppContext): SqlDriver } diff --git a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt index 37d32b9..ee859db 100644 --- a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt +++ b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt @@ -237,7 +237,7 @@ data class HomeScreen( ModalBottomSheet( onDismissRequest = onDismissRequest, sheetState = sheetState, - windowInsets = WindowInsets.ime + contentWindowInsets = { WindowInsets.ime } ) { FilmLutsList(filmLuts = filmLuts, onItemClick = onItemClick) } diff --git a/shared/src/iosMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/DriverFactory.ios.kt b/shared/src/iosMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/DriverFactory.ios.kt index 0f31247..2d6e19e 100644 --- a/shared/src/iosMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/DriverFactory.ios.kt +++ b/shared/src/iosMain/kotlin/io/github/yahiaangelo/filmsimulator/data/source/local/DriverFactory.ios.kt @@ -3,9 +3,10 @@ package io.github.yahiaangelo.filmsimulator.data.source.local import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.native.NativeSqliteDriver import io.github.yahiaangelo.filmsimulator.Database +import io.github.yahiaangelo.filmsimulator.util.AppContext actual class DriverFactory { - actual fun createDriver(): SqlDriver { + actual fun createDriver(appContext: AppContext): SqlDriver { return NativeSqliteDriver(Database.Schema, "film.db") } } \ No newline at end of file From b530424e085cf22e5daa41784da3b655937a2a99 Mon Sep 17 00:00:00 2001 From: Yahia Date: Wed, 13 Nov 2024 23:02:11 +0200 Subject: [PATCH 5/7] Refactor HomeScreenModel and improve it's uiState --- .../filmsimulator/screens/home/HomeScreen.kt | 1 + .../screens/home/HomeScreenModel.kt | 170 ++++++------------ .../filmsimulator/view/ProgressDialog.kt | 3 +- 3 files changed, 58 insertions(+), 116 deletions(-) diff --git a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt index ee859db..21f6e24 100644 --- a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt +++ b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt @@ -136,6 +136,7 @@ data class HomeScreen( } uiState.isLoading.let { loading -> + print("I got new loading $loading") if (loading) ProgressDialog(loadingMessage = uiState.loadingMessage) } diff --git a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreenModel.kt b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreenModel.kt index 9114781..4f584ae 100644 --- a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreenModel.kt +++ b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreenModel.kt @@ -7,23 +7,16 @@ import com.preat.peekaboo.image.picker.toImageBitmap import io.github.yahiaangelo.filmsimulator.FilmLut import io.github.yahiaangelo.filmsimulator.data.source.FilmRepository import io.github.yahiaangelo.filmsimulator.util.AppContext -import io.github.yahiaangelo.filmsimulator.util.Async -import io.github.yahiaangelo.filmsimulator.util.WhileUiSubscribed -import io.github.yahiaangelo.filmsimulator.util.combine -import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.flatMapConcat -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.koin.dsl.module import util.saveImageToGallery - val homeScreenModule = module { factory { HomeScreenModel(get()) } } @@ -46,156 +39,103 @@ data class HomeUiState( */ data class HomeScreenModel(val repository: FilmRepository) : ScreenModel { - private val _image: MutableStateFlow = MutableStateFlow(null) - private val _originalImage: MutableStateFlow = MutableStateFlow(null) - private val _editedImage: MutableStateFlow = MutableStateFlow(null) - private val _filmLut: MutableStateFlow = MutableStateFlow(null) - private val _userMessage: MutableStateFlow = MutableStateFlow(null) - private val _isLoading = MutableStateFlow(false) - private val _loadingMessage: MutableStateFlow = MutableStateFlow("") - private val _showBottomSheet = MutableStateFlow(false) - @OptIn(ExperimentalCoroutinesApi::class) - private val _filmLutsList = repository.getFilmsStream() - .flatMapConcat { filmList -> - if (filmList.isEmpty()) { - // If the list is empty, attempt to download new Film Luts and then retry fetching the list - flow>> { - _loadingMessage.emit("Updating Luts List") - emit(Async.Loading) - try { - repository.downloadFilmLuts() // Download new Film Luts. - val newFilmList = repository.getFilmsStream().first() // Retry fetching the list - emit(Async.Success(newFilmList)) // Emit the new list - } catch (e: Exception) { - emit(Async.Error("Error while downloading or loading Film Luts: ${e.message}")) - } - } - } else { - // If the list is not empty, proceed as normal - flowOf(Async.Success(filmList)) - } - } - .catch { emit(Async.Error("Error while loading Film Luts")) } - - - val uiState: StateFlow = combine( - _image, _filmLut, _userMessage, _isLoading, _loadingMessage, _showBottomSheet, _filmLutsList - ) { image, filmLut, userMessage, isLoading, loadingMessage, showBottomSheet, filmLutsList -> + private val _uiState: MutableStateFlow = MutableStateFlow(HomeUiState()) + val uiState: StateFlow = _uiState - when (filmLutsList) { - Async.Loading -> { - HomeUiState(isLoading = true, loadingMessage = loadingMessage) - } - - is Async.Error -> { - HomeUiState(userMessage = filmLutsList.errorMessage) - } - - is Async.Success -> { - HomeUiState( - image = image, - lut = filmLut, - filmLutsList = filmLutsList.data, - isLoading = false, - userMessage = userMessage, - showBottomSheet = showBottomSheet - ) - } - } + init { + refresh() + } + private fun updateUiState(update: (HomeUiState) -> HomeUiState) { + _uiState.value = update(_uiState.value) } - .stateIn( - scope = screenModelScope, - started = WhileUiSubscribed, - initialValue = HomeUiState(isLoading = true) - ) + private val _originalImage: MutableStateFlow = MutableStateFlow(null) + private val _editedImage: MutableStateFlow = MutableStateFlow(null) fun refresh() { screenModelScope.launch { - repository.refresh() + try { + updateUiState { it.copy(isLoading = true, loadingMessage = "Refreshing data...") } + repository.refresh() + val newFilmList = repository.getFilmsStream().first() + updateUiState { it.copy(filmLutsList = newFilmList, userMessage = "Data refreshed successfully.") } + } catch (e: Exception) { + updateUiState { it.copy(userMessage = "Error refreshing data: ${e.message}") } + } finally { + updateUiState { it.copy(isLoading = false) } + } } } - fun selectFilmLut(filmLut: FilmLut) { - screenModelScope.launch { - _originalImage.value?.let { - _loadingMessage.emit("Applying Film Lut") - _isLoading.emit(true) - repository.applyFilmLut(scope = screenModelScope, filmLut = filmLut, imageBitmap = it) { - screenModelScope.launch { - _isLoading.emit(false) - _image.emit(it) - _editedImage.emit(it) + _originalImage.value?.let { image -> + screenModelScope.launch { + try { + updateUiState { it.copy(isLoading = true, loadingMessage = "Applying Film LUT...") } + withContext(Dispatchers.IO) { + repository.applyFilmLut(scope = screenModelScope, filmLut = filmLut, imageBitmap = image) {resultImage -> + screenModelScope.launch { _editedImage.emit(resultImage) } + updateUiState { it.copy(image = resultImage, lut = filmLut) } + } } + } catch (e: Exception) { + updateUiState { it.copy(userMessage = "Error applying LUT: ${e.message}") } + } finally { + updateUiState { it.copy(isLoading = false, showBottomSheet = false) } } } - _filmLut.emit(filmLut) - _showBottomSheet.emit(false) } - } fun onImagePickerResult(byteArrays: List) { byteArrays.firstOrNull()?.let { screenModelScope.launch { val image = it.toImageBitmap() - _image.emit(image) _originalImage.emit(image) - _filmLut.value?.let { selectFilmLut(it) } + _editedImage.emit(image) + updateUiState { it.copy(image = image) } } } } fun showFilmLutsBottomSheet() { - screenModelScope.launch { - _showBottomSheet.emit(true) - } + updateUiState { it.copy(showBottomSheet = true) } } fun dismissFilmLutBottomSheet() { - screenModelScope.launch { _showBottomSheet.emit(false) } + updateUiState { it.copy(showBottomSheet = false) } } fun snackbarMessageShown() { - _userMessage.value = null + updateUiState { it.copy(userMessage = null) } } fun showOriginalImage(show: Boolean) { screenModelScope.launch { - _originalImage.value?.let { originalImage -> - if (show) - _image.emit(originalImage) - else _editedImage.value.let { editedImage -> - _image.emit(editedImage) - } - } + val targetImage = if (show) _originalImage.value else _editedImage.value + targetImage?.let { updateUiState { it.copy(image = targetImage) } } } } fun resetImage() { - screenModelScope.launch { - _originalImage.value?.let { - _image.emit(it) - } - _filmLut.emit(null) + _originalImage.value?.let {originalImage -> + updateUiState { it.copy(image = originalImage, lut = null) } } } fun exportImage() { _editedImage.value?.let { screenModelScope.launch { - _loadingMessage.emit("Exporting...") - _isLoading.emit(true) - saveImageToGallery(it, appContext = AppContext) - _isLoading.emit(false) - _userMessage.emit("Image has been exported successfully") + try { + updateUiState { it.copy(isLoading = true, loadingMessage = "Exporting image...") } + saveImageToGallery(it, appContext = AppContext) + updateUiState { it.copy(userMessage = "Image exported successfully.") } + } catch (e: Exception) { + updateUiState { it.copy(userMessage = "Error exporting image: ${e.message}") } + } finally { + updateUiState { it.copy(isLoading = false) } + } } - } ?: screenModelScope.launch { - _userMessage.emit("Please choose an image first.") - } + } ?: updateUiState { it.copy(userMessage = "Please choose an image first.") } } -} - - - +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/view/ProgressDialog.kt b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/view/ProgressDialog.kt index 9d7d9ae..167ff01 100644 --- a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/view/ProgressDialog.kt +++ b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/view/ProgressDialog.kt @@ -36,7 +36,8 @@ fun ProgressDialog( Text( modifier = Modifier.align(Alignment.CenterHorizontally), style = MaterialTheme.typography.titleSmall, - text = loadingMessage + text = loadingMessage, + color = MaterialTheme.colorScheme.onSurface ) } } From e7667cfb65bdde5caf916b69b980fff3ff203a53 Mon Sep 17 00:00:00 2001 From: Yahia Date: Sat, 14 Dec 2024 15:29:22 +0200 Subject: [PATCH 6/7] Replace peekaboo lib with FileKit for image picker and add fix image orientation functions for iOS --- gradle/libs.versions.toml | 3 ++ shared/build.gradle.kts | 2 ++ .../filmsimulator/util/ImageUtils.android.kt | 4 +++ .../filmsimulator/screens/home/HomeScreen.kt | 22 +++--------- .../screens/home/HomeScreenModel.kt | 10 ++++-- .../filmsimulator/util/ImageUtils.kt | 5 ++- .../filmsimulator/util/ImageUtils.ios.kt | 36 ++++++++++++++++++- 7 files changed, 59 insertions(+), 23 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d1033cf..ff61179 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,6 @@ [versions] agp = "8.2.2" +filekitCore = "0.8.8" imageLoader = "1.7.6" kotlin = "2.0.21" compose = "1.7.5" @@ -29,6 +30,8 @@ androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-ru androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelKtx" } androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" } coroutines-extensions = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "nativeDriver" } +filekit-compose = { module = "io.github.vinceglb:filekit-compose", version.ref = "filekitCore" } +filekit-core = { module = "io.github.vinceglb:filekit-core", version.ref = "filekitCore" } image-loader = { module = "io.github.qdsfdhvh:image-loader", version.ref = "imageLoader" } image-loader-extension-blur = { module = "io.github.qdsfdhvh:image-loader-extension-blur", version.ref = "imageLoader" } kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index abfde36..50a85cc 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -95,6 +95,8 @@ kotlin { implementation(libs.multiplatform.settings.serialization) implementation(libs.multiplatform.settings.coroutines) api(libs.image.loader) + implementation(libs.filekit.core) + implementation(libs.filekit.compose) //api(libs.image.loader.extension.blur) } diff --git a/shared/src/androidMain/kotlin/io/github/yahiaangelo/filmsimulator/util/ImageUtils.android.kt b/shared/src/androidMain/kotlin/io/github/yahiaangelo/filmsimulator/util/ImageUtils.android.kt index 3a502bc..2928b9e 100644 --- a/shared/src/androidMain/kotlin/io/github/yahiaangelo/filmsimulator/util/ImageUtils.android.kt +++ b/shared/src/androidMain/kotlin/io/github/yahiaangelo/filmsimulator/util/ImageUtils.android.kt @@ -59,4 +59,8 @@ actual suspend fun ImageBitmap.readPixels(): ByteArray { stream.toByteArray() } +} + +actual suspend fun ByteArray.fixImageOrientation(): ByteArray { + return this //Image picker library already fixes it } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt index 21f6e24..a7774b0 100644 --- a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt +++ b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreen.kt @@ -53,10 +53,6 @@ import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.koin.getScreenModel import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow -import com.example.compose.AppTheme -import com.preat.peekaboo.image.picker.ResizeOptions -import com.preat.peekaboo.image.picker.SelectionMode -import com.preat.peekaboo.image.picker.rememberImagePickerLauncher import com.seiko.imageloader.rememberImagePainter import film_simulator.shared.generated.resources.Res @@ -66,6 +62,9 @@ import film_simulator.shared.generated.resources.search import film_simulator.shared.generated.resources.select_image import film_simulator.shared.generated.resources.select_your_film +import io.github.vinceglb.filekit.compose.rememberFilePickerLauncher +import io.github.vinceglb.filekit.core.PickerMode +import io.github.vinceglb.filekit.core.PickerType import io.github.yahiaangelo.filmsimulator.FilmLut import io.github.yahiaangelo.filmsimulator.data.source.network.GITHUB_BASE_URL import io.github.yahiaangelo.filmsimulator.screens.settings.SettingsScreen @@ -92,19 +91,7 @@ data class HomeScreen( val vm = getScreenModel() val uiState by vm.uiState.collectAsState() - - val singleImagePicker = rememberImagePickerLauncher( - selectionMode = SelectionMode.Single, - scope = scope, - resizeOptions = ResizeOptions( - width = 4080, - height = 4080, - resizeThresholdBytes = 40 * 1024 * 1024L, - compressionQuality = 1.0 - ), - onResult = vm::onImagePickerResult - ) - + val singleImagePicker = rememberFilePickerLauncher(mode = PickerMode.Single, type = PickerType.Image, onResult = vm::onImagePickerResult) AppScaffold( @@ -136,7 +123,6 @@ data class HomeScreen( } uiState.isLoading.let { loading -> - print("I got new loading $loading") if (loading) ProgressDialog(loadingMessage = uiState.loadingMessage) } diff --git a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreenModel.kt b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreenModel.kt index 4f584ae..5d87926 100644 --- a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreenModel.kt +++ b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/screens/home/HomeScreenModel.kt @@ -4,9 +4,11 @@ import androidx.compose.ui.graphics.ImageBitmap import cafe.adriel.voyager.core.model.ScreenModel import cafe.adriel.voyager.core.model.screenModelScope import com.preat.peekaboo.image.picker.toImageBitmap +import io.github.vinceglb.filekit.core.PlatformFile import io.github.yahiaangelo.filmsimulator.FilmLut import io.github.yahiaangelo.filmsimulator.data.source.FilmRepository import io.github.yahiaangelo.filmsimulator.util.AppContext +import io.github.yahiaangelo.filmsimulator.util.fixImageOrientation import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO import kotlinx.coroutines.flow.MutableStateFlow @@ -87,13 +89,15 @@ data class HomeScreenModel(val repository: FilmRepository) : ScreenModel { } } - fun onImagePickerResult(byteArrays: List) { - byteArrays.firstOrNull()?.let { + fun onImagePickerResult(file: PlatformFile?) { + file?.let { screenModelScope.launch { - val image = it.toImageBitmap() + val fixedImage = it.readBytes().fixImageOrientation() + val image = fixedImage.toImageBitmap() _originalImage.emit(image) _editedImage.emit(image) updateUiState { it.copy(image = image) } + _uiState.value.lut?.let { selectFilmLut(it) } } } } diff --git a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/util/ImageUtils.kt b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/util/ImageUtils.kt index f54da03..1df7cc5 100644 --- a/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/util/ImageUtils.kt +++ b/shared/src/commonMain/kotlin/io/github/yahiaangelo/filmsimulator/util/ImageUtils.kt @@ -16,4 +16,7 @@ expect suspend fun addGrain(imageBitmap: ImageBitmap, intensity: Int): ImageBitm */ expect suspend fun ImageBitmap.readPixels(): ByteArray - +/** + * Fix image's Exif orientation + */ +expect suspend fun ByteArray.fixImageOrientation(): ByteArray \ No newline at end of file diff --git a/shared/src/iosMain/kotlin/io/github/yahiaangelo/filmsimulator/util/ImageUtils.ios.kt b/shared/src/iosMain/kotlin/io/github/yahiaangelo/filmsimulator/util/ImageUtils.ios.kt index cbfbbf2..936e687 100644 --- a/shared/src/iosMain/kotlin/io/github/yahiaangelo/filmsimulator/util/ImageUtils.ios.kt +++ b/shared/src/iosMain/kotlin/io/github/yahiaangelo/filmsimulator/util/ImageUtils.ios.kt @@ -4,6 +4,7 @@ import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.asSkiaBitmap import com.seiko.imageloader.asImageBitmap import io.github.yahiaangelo.filmsimulator.data.source.local.SettingsStorageImpl +import kotlinx.cinterop.BetaInteropApi import kotlinx.cinterop.CPointer import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.UByteVar @@ -11,12 +12,12 @@ import kotlinx.cinterop.addressOf import kotlinx.cinterop.allocArray import kotlinx.cinterop.memScoped import kotlinx.cinterop.nativeHeap +import kotlinx.cinterop.refTo import kotlinx.cinterop.set import kotlinx.cinterop.usePinned import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO import kotlinx.coroutines.withContext -import org.jetbrains.skia.Bitmap import org.jetbrains.skia.EncodedImageFormat import org.jetbrains.skia.Image import platform.CoreFoundation.CFDataCreate @@ -24,10 +25,17 @@ import platform.CoreGraphics.CGColorRenderingIntent import platform.CoreGraphics.CGColorSpaceCreateDeviceRGB import platform.CoreGraphics.CGDataProviderCreateWithCFData import platform.CoreGraphics.CGImageCreate +import platform.CoreGraphics.CGPointMake import platform.CoreImage.CIImage import platform.Foundation.NSData import platform.Foundation.dataWithBytes +import platform.UIKit.UIGraphicsBeginImageContext +import platform.UIKit.UIGraphicsEndImageContext +import platform.UIKit.UIGraphicsGetImageFromCurrentImageContext import platform.UIKit.UIImage +import platform.UIKit.UIImageJPEGRepresentation +import platform.UIKit.UIImageOrientation +import platform.posix.memcpy import kotlin.random.Random @@ -133,3 +141,29 @@ fun ByteArray.toUIImage(): UIImage? { } return UIImage.imageWithData(nsData) } + +actual suspend fun ByteArray.fixImageOrientation(): ByteArray { + return withContext(Dispatchers.IO) { + this@fixImageOrientation.toUIImage()?.fixImageOrientation()?.toByteArray(1.0) ?: this@fixImageOrientation + } +} + +@OptIn(ExperimentalForeignApi::class, BetaInteropApi::class) +private fun UIImage.fixImageOrientation(): UIImage { + if (this.imageOrientation == UIImageOrientation.UIImageOrientationUp) return this + + UIGraphicsBeginImageContext(size = this.size) + this.drawAtPoint(CGPointMake(0.0, 0.0)) + val fixedImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + return fixedImage ?: this +} + +@OptIn(ExperimentalForeignApi::class) +private fun UIImage.toByteArray(compressionQuality: Double): ByteArray { + val validCompressionQuality = compressionQuality.coerceIn(0.0, 1.0) + val jpegData = UIImageJPEGRepresentation(this, validCompressionQuality)!! + return ByteArray(jpegData.length.toInt()).apply { + memcpy(this.refTo(0), jpegData.bytes, jpegData.length) + } +} \ No newline at end of file From b2416623bc8ce4aa839af4aad5c0162785115bd2 Mon Sep 17 00:00:00 2001 From: Yahia Date: Sat, 14 Dec 2024 16:38:22 +0200 Subject: [PATCH 7/7] Update imageLoader lib --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ff61179..db9dee9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] agp = "8.2.2" filekitCore = "0.8.8" -imageLoader = "1.7.6" +imageLoader = "1.9.0" kotlin = "2.0.21" compose = "1.7.5" compose-material3 = "1.3.1"