diff --git a/examples/imageviewer/README.md b/examples/imageviewer/README.md index ed9fd665e9..6b2a834eed 100755 --- a/examples/imageviewer/README.md +++ b/examples/imageviewer/README.md @@ -9,6 +9,9 @@ To setup the environment, please consult these [instructions](https://github.com ## How to run +If you already runned this sample before, then you need to execute command at least once: +`/gradlew podInstall` + Choose a run configuration for an appropriate target in IDE and run it. ![run-configurations.png](screenshots/run-configurations.png) diff --git a/examples/imageviewer/gradle.properties b/examples/imageviewer/gradle.properties index ed81b24b3f..ae8c087e06 100644 --- a/examples/imageviewer/gradle.properties +++ b/examples/imageviewer/gradle.properties @@ -11,6 +11,6 @@ kotlin.mpp.androidSourceSetLayoutVersion=2 kotlin.native.useEmbeddableCompilerJar=true # Enable kotlin/native experimental memory model kotlin.native.binary.memoryModel=experimental -kotlin.version=1.8.20 +kotlin.version=1.9.0 agp.version=7.1.3 -compose.version=1.4.1 +compose.version=1.5.0-dev1114 diff --git a/examples/imageviewer/shared/src/androidMain/kotlin/example/imageviewer/platform.android.kt b/examples/imageviewer/shared/src/androidMain/kotlin/example/imageviewer/platform.android.kt index 21fb2cdcb5..ca508bfed2 100644 --- a/examples/imageviewer/shared/src/androidMain/kotlin/example/imageviewer/platform.android.kt +++ b/examples/imageviewer/shared/src/androidMain/kotlin/example/imageviewer/platform.android.kt @@ -10,8 +10,6 @@ import androidx.compose.ui.graphics.vector.ImageVector import kotlinx.coroutines.Dispatchers import java.util.UUID -actual fun Modifier.notchPadding(): Modifier = this.displayCutoutPadding().statusBarsPadding() - class AndroidStorableImage( val imageBitmap: ImageBitmap ) diff --git a/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/platform.common.kt b/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/platform.common.kt index a1bc1acc81..532a29bdfe 100644 --- a/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/platform.common.kt +++ b/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/platform.common.kt @@ -4,8 +4,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import kotlinx.coroutines.CoroutineDispatcher -expect fun Modifier.notchPadding(): Modifier - expect class PlatformStorableImage expect fun createUUID(): String diff --git a/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/view/GalleryScreen.kt b/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/view/GalleryScreen.kt index a161f5ee93..07302cd279 100755 --- a/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/view/GalleryScreen.kt +++ b/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/view/GalleryScreen.kt @@ -56,7 +56,11 @@ fun GalleryScreen( val imageProvider = LocalImageProvider.current val viewScope = rememberCoroutineScope() - val pagerState = rememberPagerState(initialPage = selectedPictureIndex.value) + val pagerState = rememberPagerState( + initialPage = selectedPictureIndex.value, + initialPageOffsetFraction = 0f, + pageCount = { pictures.size }, + ) LaunchedEffect(pagerState) { // Subscribe to page changes snapshotFlow { pagerState.currentPage }.collect { page -> @@ -116,7 +120,7 @@ fun GalleryScreen( onClickPreviewPicture(pagerState.currentPage) } ) { - HorizontalPager(pictures.size, state = pagerState) { index -> + HorizontalPager(state = pagerState) { index -> val picture = pictures[index] var image: ImageBitmap? by remember(picture) { mutableStateOf(null) } LaunchedEffect(picture) { diff --git a/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/view/TopLayout.kt b/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/view/TopLayout.kt index 1e2a0a059d..57d6328ced 100644 --- a/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/view/TopLayout.kt +++ b/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/view/TopLayout.kt @@ -2,13 +2,15 @@ package example.imageviewer.view import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import example.imageviewer.notchPadding @Composable fun TopLayout( @@ -18,7 +20,7 @@ fun TopLayout( Box( Modifier .fillMaxWidth() - .notchPadding() + .windowInsetsPadding(WindowInsets.systemBars) .padding(12.dp) ) { Row(Modifier.align(Alignment.CenterStart)) { diff --git a/examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/platform.desktop.kt b/examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/platform.desktop.kt index e9afee75af..d592f8aeb9 100644 --- a/examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/platform.desktop.kt +++ b/examples/imageviewer/shared/src/desktopMain/kotlin/example/imageviewer/platform.desktop.kt @@ -10,8 +10,6 @@ import androidx.compose.ui.unit.dp import kotlinx.coroutines.Dispatchers import java.util.UUID -actual fun Modifier.notchPadding(): Modifier = Modifier.padding(top = 12.dp) - class DesktopStorableImage( val imageBitmap: ImageBitmap ) diff --git a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/platform.ios.kt b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/platform.ios.kt index 9926f5250c..711d3cb385 100644 --- a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/platform.ios.kt +++ b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/platform.ios.kt @@ -1,46 +1,22 @@ package example.imageviewer -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.windowInsetsPadding -import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.unit.Density -import androidx.compose.ui.unit.LayoutDirection import example.imageviewer.icon.IconIosShare -import kotlinx.cinterop.useContents +import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO import platform.CoreFoundation.CFUUIDCreate import platform.CoreFoundation.CFUUIDCreateString import platform.Foundation.CFBridgingRelease -import platform.UIKit.UIApplication import platform.UIKit.UIImage -private val iosNotchInset = object : WindowInsets { - override fun getTop(density: Density): Int { - val safeAreaInsets = UIApplication.sharedApplication.keyWindow?.safeAreaInsets - return if (safeAreaInsets != null) { - val topInset = safeAreaInsets.useContents { this.top } - (topInset * density.density).toInt() - } else { - 0 - } - } - - override fun getLeft(density: Density, layoutDirection: LayoutDirection): Int = 0 - override fun getRight(density: Density, layoutDirection: LayoutDirection): Int = 0 - override fun getBottom(density: Density): Int = 0 -} - -actual fun Modifier.notchPadding(): Modifier = - this.windowInsetsPadding(iosNotchInset) - class IosStorableImage( val rawValue: UIImage ) actual typealias PlatformStorableImage = IosStorableImage +@OptIn(ExperimentalForeignApi::class) actual fun createUUID(): String = CFBridgingRelease(CFUUIDCreateString(null, CFUUIDCreate(null))) as String diff --git a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/FileExtensions.kt b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/FileExtensions.kt index 3513a1f662..a003027160 100644 --- a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/FileExtensions.kt +++ b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/FileExtensions.kt @@ -1,3 +1,5 @@ +@file:OptIn(ExperimentalForeignApi::class) + package example.imageviewer.storage import kotlinx.cinterop.* diff --git a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/IosImageStorage.ios.kt b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/IosImageStorage.ios.kt index 93408a61d1..59b0d7c1be 100644 --- a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/IosImageStorage.ios.kt +++ b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/storage/IosImageStorage.ios.kt @@ -7,6 +7,7 @@ import example.imageviewer.PlatformStorableImage import example.imageviewer.model.PictureData import example.imageviewer.toImageBitmap import kotlinx.cinterop.CValue +import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.useContents import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -122,6 +123,7 @@ class IosImageStorage( } } +@OptIn(ExperimentalForeignApi::class) private fun UIImage.fitInto(px: Int): UIImage { val targetScale = maxOf( px.toFloat() / size.useContents { width }, @@ -131,6 +133,7 @@ private fun UIImage.fitInto(px: Int): UIImage { return resize(newSize) } +@OptIn(ExperimentalForeignApi::class) private fun UIImage.resize(targetSize: CValue): UIImage { val currentSize = this.size val widthRatio = targetSize.useContents { width } / currentSize.useContents { width } diff --git a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/view/CameraView.ios.kt b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/view/CameraView.ios.kt index c76d44fa88..5499750fba 100644 --- a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/view/CameraView.ios.kt +++ b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/view/CameraView.ios.kt @@ -18,6 +18,7 @@ import example.imageviewer.model.GpsPosition import example.imageviewer.model.PictureData import example.imageviewer.model.createCameraPictureData import kotlinx.cinterop.CValue +import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.ObjCAction import kotlinx.cinterop.useContents import platform.AVFoundation.* @@ -121,6 +122,7 @@ private fun BoxScope.AuthorizedCamera( } } +@OptIn(ExperimentalForeignApi::class) @Composable private fun BoxScope.RealDeviceCamera( camera: AVCaptureDevice, @@ -272,6 +274,7 @@ private fun BoxScope.RealDeviceCamera( } } +@OptIn(ExperimentalForeignApi::class) fun CLLocation.toGps() = GpsPosition( latitude = coordinate.useContents { latitude }, diff --git a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/view/LocationVisualizer.ios.kt b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/view/LocationVisualizer.ios.kt index 451d3b9ee5..4da53ef73b 100644 --- a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/view/LocationVisualizer.ios.kt +++ b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/view/LocationVisualizer.ios.kt @@ -6,11 +6,13 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.interop.UIKitView import example.imageviewer.model.GpsPosition +import kotlinx.cinterop.ExperimentalForeignApi import platform.CoreLocation.CLLocationCoordinate2DMake import platform.MapKit.MKCoordinateRegionMakeWithDistance import platform.MapKit.MKMapView import platform.MapKit.MKPointAnnotation +@OptIn(ExperimentalForeignApi::class) @Composable actual fun LocationVisualizer( modifier: Modifier,