diff --git a/artwork/imageviewerrepo/pictures.json b/artwork/imageviewerrepo/pictures.json
new file mode 100644
index 0000000000..adecca674d
--- /dev/null
+++ b/artwork/imageviewerrepo/pictures.json
@@ -0,0 +1,15 @@
+[
+ {"big": "1.jpg", "small": "small/1.jpg"},
+ {"big": "2.jpg", "small": "small/2.jpg"},
+ {"big": "3.jpg", "small": "small/3.jpg"},
+ {"big": "4.jpg", "small": "small/4.jpg"},
+ {"big": "5.jpg", "small": "small/5.jpg"},
+ {"big": "6.jpg", "small": "small/6.jpg"},
+ {"big": "7.jpg", "small": "small/7.jpg"},
+ {"big": "8.jpg", "small": "small/8.jpg"},
+ {"big": "9.jpg", "small": "small/9.jpg"},
+ {"big": "10.jpg", "small": "small/10.jpg"},
+ {"big": "11.jpg", "small": "small/11.jpg"},
+ {"big": "12.jpg", "small": "small/12.jpg"},
+ {"big": "13.jpg", "small": "small/13.jpg"}
+]
diff --git a/artwork/imageviewerrepo/small/1.jpg b/artwork/imageviewerrepo/small/1.jpg
new file mode 100644
index 0000000000..1543e7e338
Binary files /dev/null and b/artwork/imageviewerrepo/small/1.jpg differ
diff --git a/artwork/imageviewerrepo/small/10.jpg b/artwork/imageviewerrepo/small/10.jpg
new file mode 100644
index 0000000000..cd09c38c2f
Binary files /dev/null and b/artwork/imageviewerrepo/small/10.jpg differ
diff --git a/artwork/imageviewerrepo/small/11.jpg b/artwork/imageviewerrepo/small/11.jpg
new file mode 100644
index 0000000000..ea908b312c
Binary files /dev/null and b/artwork/imageviewerrepo/small/11.jpg differ
diff --git a/artwork/imageviewerrepo/small/12.jpg b/artwork/imageviewerrepo/small/12.jpg
new file mode 100644
index 0000000000..e9134db062
Binary files /dev/null and b/artwork/imageviewerrepo/small/12.jpg differ
diff --git a/artwork/imageviewerrepo/small/13.jpg b/artwork/imageviewerrepo/small/13.jpg
new file mode 100644
index 0000000000..c74d019768
Binary files /dev/null and b/artwork/imageviewerrepo/small/13.jpg differ
diff --git a/artwork/imageviewerrepo/small/2.jpg b/artwork/imageviewerrepo/small/2.jpg
new file mode 100644
index 0000000000..9c466759b8
Binary files /dev/null and b/artwork/imageviewerrepo/small/2.jpg differ
diff --git a/artwork/imageviewerrepo/small/3.jpg b/artwork/imageviewerrepo/small/3.jpg
new file mode 100644
index 0000000000..17a4e4fc36
Binary files /dev/null and b/artwork/imageviewerrepo/small/3.jpg differ
diff --git a/artwork/imageviewerrepo/small/4.jpg b/artwork/imageviewerrepo/small/4.jpg
new file mode 100644
index 0000000000..7269b9dfb8
Binary files /dev/null and b/artwork/imageviewerrepo/small/4.jpg differ
diff --git a/artwork/imageviewerrepo/small/5.jpg b/artwork/imageviewerrepo/small/5.jpg
new file mode 100644
index 0000000000..40630f7132
Binary files /dev/null and b/artwork/imageviewerrepo/small/5.jpg differ
diff --git a/artwork/imageviewerrepo/small/6.jpg b/artwork/imageviewerrepo/small/6.jpg
new file mode 100644
index 0000000000..4b8cc6c393
Binary files /dev/null and b/artwork/imageviewerrepo/small/6.jpg differ
diff --git a/artwork/imageviewerrepo/small/7.jpg b/artwork/imageviewerrepo/small/7.jpg
new file mode 100644
index 0000000000..08335a4fe4
Binary files /dev/null and b/artwork/imageviewerrepo/small/7.jpg differ
diff --git a/artwork/imageviewerrepo/small/8.jpg b/artwork/imageviewerrepo/small/8.jpg
new file mode 100644
index 0000000000..7da656b68e
Binary files /dev/null and b/artwork/imageviewerrepo/small/8.jpg differ
diff --git a/artwork/imageviewerrepo/small/9.jpg b/artwork/imageviewerrepo/small/9.jpg
new file mode 100644
index 0000000000..f7dc5754c1
Binary files /dev/null and b/artwork/imageviewerrepo/small/9.jpg differ
diff --git a/experimental/examples/imageviewer/.gitignore b/experimental/examples/imageviewer/.gitignore
index a32b16597b..994fd0a8a4 100644
--- a/experimental/examples/imageviewer/.gitignore
+++ b/experimental/examples/imageviewer/.gitignore
@@ -13,3 +13,9 @@ build/
/captures
.externalNativeBuild
.cxx
+iosApp/Podfile.lock
+iosApp/Pods/*
+iosApp/Imageviewer.xcworkspace/*
+iosApp/Imageviewer.xcodeproj/*
+!iosApp/Imageviewer.xcodeproj/project.pbxproj
+shared/shared.podspec
diff --git a/experimental/examples/imageviewer/.run/desktop.run.xml b/experimental/examples/imageviewer/.run/desktopApp.run.xml
old mode 100755
new mode 100644
similarity index 63%
rename from experimental/examples/imageviewer/.run/desktop.run.xml
rename to experimental/examples/imageviewer/.run/desktopApp.run.xml
index d9335c1be5..95395e11ee
--- a/experimental/examples/imageviewer/.run/desktop.run.xml
+++ b/experimental/examples/imageviewer/.run/desktopApp.run.xml
@@ -1,8 +1,8 @@
-
+
-
+
- true
+ true
+ true
+ false
\ No newline at end of file
diff --git a/experimental/examples/imageviewer/.run/iosApp (AndroidStudio).run.xml b/experimental/examples/imageviewer/.run/iosApp (AndroidStudio).run.xml
new file mode 100644
index 0000000000..9784842232
--- /dev/null
+++ b/experimental/examples/imageviewer/.run/iosApp (AndroidStudio).run.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/experimental/examples/imageviewer/.run/iosApp.run.xml b/experimental/examples/imageviewer/.run/iosApp.run.xml
new file mode 100644
index 0000000000..3a59900d23
--- /dev/null
+++ b/experimental/examples/imageviewer/.run/iosApp.run.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/experimental/examples/imageviewer/README.md b/experimental/examples/imageviewer/README.md
index 3d79c52613..c9fca538d1 100755
--- a/experimental/examples/imageviewer/README.md
+++ b/experimental/examples/imageviewer/README.md
@@ -1,11 +1,27 @@
-An example of image gallery for remote server image viewing, based on Jetpack Compose UI library (desktop and android).
+# Imageviewer
-### Running desktop application
- * To run, launch command: `./gradlew :desktop:run`
- * Or choose **desktop** configuration in IDE and run it.
- ![desktop-run-configuration.png](screenshots/desktop-run-configuration.png)
+An example of image gallery for remote server image viewing,
+based on Compose Multiplatform UI library (desktop, android and iOS).
+
+## How to run
+
+Choose a run configuration for an appropriate target in IDE and run it.
+
+![run-configurations.png](run-configurations.png)
+
+To run on iOS device, please correct `iosApp/Configuration/TeamId.xcconfig` with your Apple Team ID.
+Alternatively, you may setup signing within XCode opening `iosApp/Imageviewer.xcworkspace` and then
+using "Signing & Capabilities" tab of `ImageViewer` target.
+
+Then choose **iosApp** configuration in IDE and run it
+(may also be referred as `ImageViewer` in the Run Configurations or `iosApp (AndroidStudio)` for Android studio).
+
+## Run on desktop via Gradle
+
+`./gradlew desktopApp:run`
### Building native desktop distribution
+
```
./gradlew :desktop:packageDistributionForCurrentOS
# outputs are written to desktop/build/compose/binaries
diff --git a/experimental/examples/imageviewer/android/build.gradle.kts b/experimental/examples/imageviewer/android/build.gradle.kts
deleted file mode 100755
index d5807ca5f3..0000000000
--- a/experimental/examples/imageviewer/android/build.gradle.kts
+++ /dev/null
@@ -1,26 +0,0 @@
-plugins {
- id("com.android.application")
- kotlin("android")
- id("org.jetbrains.compose")
-}
-
-android {
- compileSdk = 32
-
- defaultConfig {
- minSdk = 26
- targetSdk = 32
- versionCode = 1
- versionName = "1.0"
- }
-
- compileOptions {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
- }
-}
-
-dependencies {
- implementation(project(":common"))
- implementation("androidx.activity:activity-compose:1.5.0")
-}
diff --git a/experimental/examples/imageviewer/android/src/main/java/example/imageviewer/MainActivity.kt b/experimental/examples/imageviewer/android/src/main/java/example/imageviewer/MainActivity.kt
deleted file mode 100755
index 53bb8c6160..0000000000
--- a/experimental/examples/imageviewer/android/src/main/java/example/imageviewer/MainActivity.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package example.imageviewer
-
-import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
-import androidx.activity.compose.setContent
-import example.imageviewer.view.AppUI
-import example.imageviewer.model.ContentState
-import example.imageviewer.model.ImageRepository
-
-class MainActivity : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- val content = ContentState.applyContent(
- this@MainActivity,
- "https://raw.githubusercontent.com/JetBrains/compose-jb/master/artwork/imageviewerrepo/fetching.list"
- )
-
- setContent {
- AppUI(content)
- }
- }
-}
\ No newline at end of file
diff --git a/experimental/examples/imageviewer/androidApp/build.gradle.kts b/experimental/examples/imageviewer/androidApp/build.gradle.kts
new file mode 100755
index 0000000000..cdb92d493a
--- /dev/null
+++ b/experimental/examples/imageviewer/androidApp/build.gradle.kts
@@ -0,0 +1,33 @@
+plugins {
+ kotlin("multiplatform")
+ id("com.android.application")
+ id("org.jetbrains.compose")
+}
+
+kotlin {
+ android()
+ sourceSets {
+ val androidMain by getting {
+ dependencies {
+ implementation(project(":shared"))
+ implementation("androidx.appcompat:appcompat:1.5.1")
+ implementation("androidx.activity:activity-compose:1.6.1")
+ }
+ }
+ }
+}
+
+android {
+ compileSdk = 33
+ defaultConfig {
+ applicationId = "org.jetbrains.imageviewer"
+ minSdk = 24
+ targetSdk = 33
+ versionCode = 1
+ versionName = "1.0"
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+}
diff --git a/experimental/examples/imageviewer/android/src/main/AndroidManifest.xml b/experimental/examples/imageviewer/androidApp/src/main/AndroidManifest.xml
similarity index 91%
rename from experimental/examples/imageviewer/android/src/main/AndroidManifest.xml
rename to experimental/examples/imageviewer/androidApp/src/main/AndroidManifest.xml
index 5b1501c058..025f2c4a29 100755
--- a/experimental/examples/imageviewer/android/src/main/AndroidManifest.xml
+++ b/experimental/examples/imageviewer/androidApp/src/main/AndroidManifest.xml
@@ -5,7 +5,6 @@
-
-
\ No newline at end of file
diff --git a/experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/core/BitmapFilter.kt b/experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/core/BitmapFilter.kt
deleted file mode 100755
index bf5d0b8c88..0000000000
--- a/experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/core/BitmapFilter.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package example.imageviewer.core
-
-import android.graphics.Bitmap
-
-interface BitmapFilter {
- fun apply(bitmap: Bitmap) : Bitmap
-}
\ No newline at end of file
diff --git a/experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/model/AndroidContentState.kt b/experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/model/AndroidContentState.kt
deleted file mode 100644
index 00d4b026bc..0000000000
--- a/experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/model/AndroidContentState.kt
+++ /dev/null
@@ -1,383 +0,0 @@
-package example.imageviewer.model
-
-import android.content.Context
-import android.graphics.*
-import android.os.Handler
-import android.os.Looper
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.mutableStateOf
-import example.imageviewer.common.R
-import example.imageviewer.core.FilterType
-import example.imageviewer.model.filtration.FiltersManager
-import example.imageviewer.utils.clearCache
-import example.imageviewer.utils.isInternetAvailable
-import example.imageviewer.view.showPopUpMessage
-import java.util.concurrent.ExecutorService
-import java.util.concurrent.Executors
-
-
-object ContentState {
-
- private lateinit var context: Context
- private lateinit var repository: ImageRepository
- private lateinit var uriRepository: String
-
- fun applyContent(context: Context, uriRepository: String): ContentState {
- if (this::uriRepository.isInitialized && this.uriRepository == uriRepository) {
- return this
- }
-
- this.context = context
- this.uriRepository = uriRepository
- repository = ImageRepository(uriRepository)
- appliedFilters = FiltersManager(context)
- isContentReady.value = false
-
- initData()
-
- return this
- }
-
- private val executor: ExecutorService by lazy { Executors.newFixedThreadPool(2) }
-
- private val handler: Handler by lazy { Handler(Looper.getMainLooper()) }
-
- fun getContext(): Context {
- return context
- }
-
- fun getOrientation(): Int {
- return context.resources.configuration.orientation
- }
-
- private val isAppReady = mutableStateOf(false)
- fun isAppReady(): Boolean {
- return isAppReady.value
- }
-
- private val isContentReady = mutableStateOf(false)
- fun isContentReady(): Boolean {
- return isContentReady.value
- }
-
- fun getString(id: Int): String {
- return context.getString(id)
- }
-
- // drawable content
- private val mainImage = mutableStateOf(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888))
- private val currentImageIndex = mutableStateOf(0)
- private val miniatures = Miniatures()
-
- fun getMiniatures(): List