From e8786ea73fbdf67be9be57d54377fd7008486b20 Mon Sep 17 00:00:00 2001
From: "dima.avdeev" <99798741+dima-avdeev-jb@users.noreply.github.com>
Date: Fri, 25 Nov 2022 17:33:42 +0300
Subject: [PATCH] Copy imageviewer to experimental/examples (#2500)
---
experimental/examples/imageviewer/.gitignore | 15 +
.../examples/imageviewer/.run/desktop.run.xml | 21 +
experimental/examples/imageviewer/README.md | 18 +
.../imageviewer/android/build.gradle.kts | 26 ++
.../android/src/main/AndroidManifest.xml | 28 ++
.../java/example/imageviewer/MainActivity.kt | 23 ++
.../examples/imageviewer/build.gradle.kts | 18 +
.../imageviewer/common/build.gradle.kts | 54 +++
.../src/androidMain/AndroidManifest.xml | 2 +
.../example/imageviewer/core/BitmapFilter.kt | 7 +
.../imageviewer/model/AndroidContentState.kt | 383 ++++++++++++++++++
.../example/imageviewer/model/ImageHandler.kt | 131 ++++++
.../example/imageviewer/model/Picture.kt | 12 +
.../model/filtration/BlurFilter.kt | 13 +
.../model/filtration/EmptyFilter.kt | 12 +
.../model/filtration/FiltersManager.kt | 54 +++
.../model/filtration/GrayScaleFilter.kt | 12 +
.../model/filtration/PixelFilter.kt | 12 +
.../example/imageviewer/style/Decoration.kt | 38 ++
.../example/imageviewer/utils/Caching.kt | 52 +++
.../example/imageviewer/utils/Coroutines.kt | 9 +
.../example/imageviewer/utils/GraphicsMath.kt | 195 +++++++++
.../kotlin/example/imageviewer/view/AppUI.kt | 40 ++
.../imageviewer/view/FullscreenImage.kt | 197 +++++++++
.../example/imageviewer/view/MainScreen.kt | 218 ++++++++++
.../src/androidMain/res/drawable/back.png | Bin 0 -> 6035 bytes
.../src/androidMain/res/drawable/blur_off.png | Bin 0 -> 36186 bytes
.../src/androidMain/res/drawable/blur_on.png | Bin 0 -> 38425 bytes
.../src/androidMain/res/drawable/dots.png | Bin 0 -> 2242 bytes
.../src/androidMain/res/drawable/empty.png | Bin 0 -> 50553 bytes
.../res/drawable/filter_unknown.png | Bin 0 -> 11150 bytes
.../res/drawable/grayscale_off.png | Bin 0 -> 9280 bytes
.../androidMain/res/drawable/grayscale_on.png | Bin 0 -> 10361 bytes
.../androidMain/res/drawable/pixel_off.png | Bin 0 -> 6916 bytes
.../src/androidMain/res/drawable/pixel_on.png | Bin 0 -> 8144 bytes
.../src/androidMain/res/drawable/refresh.png | Bin 0 -> 8353 bytes
.../res/mipmap-anydpi-v26/ic_imageviewer.xml | 5 +
.../ic_imageviewer_round.xml | 5 +
.../res/mipmap-hdpi/ic_imageviewer.png | Bin 0 -> 5933 bytes
.../mipmap-hdpi/ic_imageviewer_background.png | Bin 0 -> 20774 bytes
.../mipmap-hdpi/ic_imageviewer_foreground.png | Bin 0 -> 3498 bytes
.../res/mipmap-hdpi/ic_imageviewer_round.png | Bin 0 -> 9081 bytes
.../res/mipmap-mdpi/ic_imageviewer.png | Bin 0 -> 3121 bytes
.../mipmap-mdpi/ic_imageviewer_background.png | Bin 0 -> 9820 bytes
.../mipmap-mdpi/ic_imageviewer_foreground.png | Bin 0 -> 2048 bytes
.../res/mipmap-mdpi/ic_imageviewer_round.png | Bin 0 -> 4733 bytes
.../res/mipmap-xhdpi/ic_imageviewer.png | Bin 0 -> 9553 bytes
.../ic_imageviewer_background.png | Bin 0 -> 34508 bytes
.../ic_imageviewer_foreground.png | Bin 0 -> 5103 bytes
.../res/mipmap-xhdpi/ic_imageviewer_round.png | Bin 0 -> 14598 bytes
.../res/mipmap-xxhdpi/ic_imageviewer.png | Bin 0 -> 18690 bytes
.../ic_imageviewer_background.png | Bin 0 -> 69170 bytes
.../ic_imageviewer_foreground.png | Bin 0 -> 8909 bytes
.../mipmap-xxhdpi/ic_imageviewer_round.png | Bin 0 -> 27863 bytes
.../res/mipmap-xxxhdpi/ic_imageviewer.png | Bin 0 -> 30597 bytes
.../ic_imageviewer_background.png | Bin 0 -> 109639 bytes
.../ic_imageviewer_foreground.png | Bin 0 -> 13444 bytes
.../mipmap-xxxhdpi/ic_imageviewer_round.png | Bin 0 -> 44733 bytes
.../src/androidMain/res/values-ru/strings.xml | 15 +
.../src/androidMain/res/values/strings.xml | 14 +
.../example/imageviewer/core/EventLocker.kt | 18 +
.../example/imageviewer/core/FilterType.kt | 5 +
.../example/imageviewer/core/Repository.kt | 5 +
.../imageviewer/model/ImageRepository.kt | 33 ++
.../example/imageviewer/model/Miniatures.kt | 41 ++
.../example/imageviewer/model/ScreenType.kt | 23 ++
.../example/imageviewer/style/Palette.kt | 16 +
.../example/imageviewer/utils/Coroutines.kt | 7 +
.../example/imageviewer/utils/Network.kt | 37 ++
.../example/imageviewer/view/Clickable.kt | 21 +
.../example/imageviewer/view/Draggable.kt | 88 ++++
.../example/imageviewer/view/LoadingScreen.kt | 43 ++
.../example/imageviewer/view/Scalable.kt | 47 +++
.../example/imageviewer/view/SplashUI.kt | 27 ++
.../kotlin/example/imageviewer/R.kt | 53 +++
.../example/imageviewer/core/BitmapFilter.kt | 7 +
.../imageviewer/model/DesktopContentState.kt | 362 +++++++++++++++++
.../example/imageviewer/model/ImageHandler.kt | 130 ++++++
.../example/imageviewer/model/Picture.kt | 12 +
.../model/filtration/BlurFilter.kt | 12 +
.../model/filtration/EmptyFilter.kt | 12 +
.../model/filtration/FiltersManager.kt | 53 +++
.../model/filtration/GrayScaleFilter.kt | 12 +
.../model/filtration/PixelFilter.kt | 12 +
.../example/imageviewer/style/Decoration.kt | 42 ++
.../example/imageviewer/utils/Caching.kt | 53 +++
.../example/imageviewer/utils/Coroutines.kt | 9 +
.../example/imageviewer/utils/GraphicsMath.kt | 206 ++++++++++
.../kotlin/example/imageviewer/view/AppUI.kt | 40 ++
.../imageviewer/view/FullscreenImage.kt | 207 ++++++++++
.../example/imageviewer/view/MainScreen.kt | 250 ++++++++++++
.../kotlin/example/imageviewer/view/Toast.kt | 59 +++
.../example/imageviewer/view/Tooltip.kt | 38 ++
.../example/imageviewer/view/Zoomable.kt | 67 +++
.../src/desktopMain/resources/images/back.png | Bin 0 -> 6035 bytes
.../desktopMain/resources/images/blur_off.png | Bin 0 -> 36186 bytes
.../desktopMain/resources/images/blur_on.png | Bin 0 -> 38425 bytes
.../src/desktopMain/resources/images/dots.png | Bin 0 -> 2242 bytes
.../desktopMain/resources/images/empty.png | Bin 0 -> 50553 bytes
.../resources/images/filter_unknown.png | Bin 0 -> 11150 bytes
.../resources/images/grayscale_off.png | Bin 0 -> 9280 bytes
.../resources/images/grayscale_on.png | Bin 0 -> 10361 bytes
.../resources/images/ic_imageviewer_round.png | Bin 0 -> 44733 bytes
.../resources/images/icon-linux.png | Bin 0 -> 22764 bytes
.../resources/images/icon-mac.icns | Bin 0 -> 22354 bytes
.../resources/images/icon-windows.ico | Bin 0 -> 67758 bytes
.../resources/images/pixel_off.png | Bin 0 -> 6916 bytes
.../desktopMain/resources/images/pixel_on.png | Bin 0 -> 8144 bytes
.../desktopMain/resources/images/refresh.png | Bin 0 -> 8353 bytes
.../imageviewer/desktop/build.gradle.kts | 46 +++
.../examples/imageviewer/desktop/rules.pro | 12 +
.../kotlin/example/imageviewer/Main.kt | 59 +++
.../examples/imageviewer/gradle.properties | 24 ++
.../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58695 bytes
.../gradle/wrapper/gradle-wrapper.properties | 5 +
experimental/examples/imageviewer/gradlew | 185 +++++++++
experimental/examples/imageviewer/gradlew.bat | 104 +++++
.../screenshots/desktop-run-configuration.png | Bin 0 -> 2582 bytes
.../imageviewer/screenshots/imageviewer.png | Bin 0 -> 431322 bytes
.../examples/imageviewer/settings.gradle.kts | 22 +
120 files changed, 4133 insertions(+)
create mode 100644 experimental/examples/imageviewer/.gitignore
create mode 100755 experimental/examples/imageviewer/.run/desktop.run.xml
create mode 100755 experimental/examples/imageviewer/README.md
create mode 100755 experimental/examples/imageviewer/android/build.gradle.kts
create mode 100755 experimental/examples/imageviewer/android/src/main/AndroidManifest.xml
create mode 100755 experimental/examples/imageviewer/android/src/main/java/example/imageviewer/MainActivity.kt
create mode 100755 experimental/examples/imageviewer/build.gradle.kts
create mode 100755 experimental/examples/imageviewer/common/build.gradle.kts
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/AndroidManifest.xml
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/core/BitmapFilter.kt
create mode 100644 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/model/AndroidContentState.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/model/ImageHandler.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/model/Picture.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/model/filtration/BlurFilter.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/model/filtration/EmptyFilter.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/model/filtration/FiltersManager.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/model/filtration/GrayScaleFilter.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/model/filtration/PixelFilter.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/style/Decoration.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/utils/Caching.kt
create mode 100644 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/utils/Coroutines.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/utils/GraphicsMath.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/view/AppUI.kt
create mode 100644 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/view/FullscreenImage.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/view/MainScreen.kt
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/drawable/back.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/drawable/blur_off.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/drawable/blur_on.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/drawable/dots.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/drawable/empty.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/drawable/filter_unknown.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/drawable/grayscale_off.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/drawable/grayscale_on.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/drawable/pixel_off.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/drawable/pixel_on.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/drawable/refresh.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-anydpi-v26/ic_imageviewer.xml
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-anydpi-v26/ic_imageviewer_round.xml
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-hdpi/ic_imageviewer.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-hdpi/ic_imageviewer_background.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-hdpi/ic_imageviewer_foreground.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-hdpi/ic_imageviewer_round.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-mdpi/ic_imageviewer.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-mdpi/ic_imageviewer_background.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-mdpi/ic_imageviewer_foreground.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-mdpi/ic_imageviewer_round.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-xhdpi/ic_imageviewer.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-xhdpi/ic_imageviewer_background.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-xhdpi/ic_imageviewer_foreground.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-xhdpi/ic_imageviewer_round.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-xxhdpi/ic_imageviewer.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-xxhdpi/ic_imageviewer_background.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-xxhdpi/ic_imageviewer_foreground.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-xxhdpi/ic_imageviewer_round.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-xxxhdpi/ic_imageviewer.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-xxxhdpi/ic_imageviewer_background.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-xxxhdpi/ic_imageviewer_foreground.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/mipmap-xxxhdpi/ic_imageviewer_round.png
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/values-ru/strings.xml
create mode 100755 experimental/examples/imageviewer/common/src/androidMain/res/values/strings.xml
create mode 100755 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/core/EventLocker.kt
create mode 100755 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/core/FilterType.kt
create mode 100755 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/core/Repository.kt
create mode 100755 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/model/ImageRepository.kt
create mode 100755 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/model/Miniatures.kt
create mode 100755 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/model/ScreenType.kt
create mode 100755 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/style/Palette.kt
create mode 100644 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/utils/Coroutines.kt
create mode 100755 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/utils/Network.kt
create mode 100755 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/view/Clickable.kt
create mode 100755 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/view/Draggable.kt
create mode 100644 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/view/LoadingScreen.kt
create mode 100755 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/view/Scalable.kt
create mode 100644 experimental/examples/imageviewer/common/src/commonMain/kotlin/example/imageviewer/view/SplashUI.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/R.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/core/BitmapFilter.kt
create mode 100644 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/model/DesktopContentState.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/model/ImageHandler.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/model/Picture.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/model/filtration/BlurFilter.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/model/filtration/EmptyFilter.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/model/filtration/FiltersManager.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/model/filtration/GrayScaleFilter.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/model/filtration/PixelFilter.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/style/Decoration.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/utils/Caching.kt
create mode 100644 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/utils/Coroutines.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/utils/GraphicsMath.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/AppUI.kt
create mode 100644 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/FullscreenImage.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/MainScreen.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/Toast.kt
create mode 100644 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/Tooltip.kt
create mode 100644 experimental/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/Zoomable.kt
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/back.png
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/blur_off.png
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/blur_on.png
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/dots.png
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/empty.png
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/filter_unknown.png
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/grayscale_off.png
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/grayscale_on.png
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/ic_imageviewer_round.png
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/icon-linux.png
create mode 100644 experimental/examples/imageviewer/common/src/desktopMain/resources/images/icon-mac.icns
create mode 100644 experimental/examples/imageviewer/common/src/desktopMain/resources/images/icon-windows.ico
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/pixel_off.png
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/pixel_on.png
create mode 100755 experimental/examples/imageviewer/common/src/desktopMain/resources/images/refresh.png
create mode 100755 experimental/examples/imageviewer/desktop/build.gradle.kts
create mode 100644 experimental/examples/imageviewer/desktop/rules.pro
create mode 100644 experimental/examples/imageviewer/desktop/src/jvmMain/kotlin/example/imageviewer/Main.kt
create mode 100755 experimental/examples/imageviewer/gradle.properties
create mode 100644 experimental/examples/imageviewer/gradle/wrapper/gradle-wrapper.jar
create mode 100755 experimental/examples/imageviewer/gradle/wrapper/gradle-wrapper.properties
create mode 100755 experimental/examples/imageviewer/gradlew
create mode 100755 experimental/examples/imageviewer/gradlew.bat
create mode 100644 experimental/examples/imageviewer/screenshots/desktop-run-configuration.png
create mode 100755 experimental/examples/imageviewer/screenshots/imageviewer.png
create mode 100755 experimental/examples/imageviewer/settings.gradle.kts
diff --git a/experimental/examples/imageviewer/.gitignore b/experimental/examples/imageviewer/.gitignore
new file mode 100644
index 0000000000..a32b16597b
--- /dev/null
+++ b/experimental/examples/imageviewer/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+build/
+/captures
+.externalNativeBuild
+.cxx
diff --git a/experimental/examples/imageviewer/.run/desktop.run.xml b/experimental/examples/imageviewer/.run/desktop.run.xml
new file mode 100755
index 0000000000..d9335c1be5
--- /dev/null
+++ b/experimental/examples/imageviewer/.run/desktop.run.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
\ No newline at end of file
diff --git a/experimental/examples/imageviewer/README.md b/experimental/examples/imageviewer/README.md
new file mode 100755
index 0000000000..3d79c52613
--- /dev/null
+++ b/experimental/examples/imageviewer/README.md
@@ -0,0 +1,18 @@
+An example of image gallery for remote server image viewing, based on Jetpack Compose UI library (desktop and android).
+
+### 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)
+
+### Building native desktop distribution
+```
+./gradlew :desktop:packageDistributionForCurrentOS
+# outputs are written to desktop/build/compose/binaries
+```
+
+### Running Android application
+
+Open project in IntelliJ IDEA or Android Studio and run "android" configuration.
+
+![Desktop](screenshots/imageviewer.png)
diff --git a/experimental/examples/imageviewer/android/build.gradle.kts b/experimental/examples/imageviewer/android/build.gradle.kts
new file mode 100755
index 0000000000..d5807ca5f3
--- /dev/null
+++ b/experimental/examples/imageviewer/android/build.gradle.kts
@@ -0,0 +1,26 @@
+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/AndroidManifest.xml b/experimental/examples/imageviewer/android/src/main/AndroidManifest.xml
new file mode 100755
index 0000000000..5b1501c058
--- /dev/null
+++ b/experimental/examples/imageviewer/android/src/main/AndroidManifest.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
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
new file mode 100755
index 0000000000..53bb8c6160
--- /dev/null
+++ b/experimental/examples/imageviewer/android/src/main/java/example/imageviewer/MainActivity.kt
@@ -0,0 +1,23 @@
+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/build.gradle.kts b/experimental/examples/imageviewer/build.gradle.kts
new file mode 100755
index 0000000000..bf95fe23b1
--- /dev/null
+++ b/experimental/examples/imageviewer/build.gradle.kts
@@ -0,0 +1,18 @@
+plugins {
+ // this is necessary to avoid the plugins to be loaded multiple times
+ // in each subproject's classloader
+ kotlin("jvm") apply false
+ kotlin("multiplatform") apply false
+ kotlin("android") apply false
+ id("com.android.application") apply false
+ id("com.android.library") apply false
+ id("org.jetbrains.compose") apply false
+}
+
+subprojects {
+ repositories {
+ google()
+ mavenCentral()
+ maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
+ }
+}
diff --git a/experimental/examples/imageviewer/common/build.gradle.kts b/experimental/examples/imageviewer/common/build.gradle.kts
new file mode 100755
index 0000000000..3a67917bbe
--- /dev/null
+++ b/experimental/examples/imageviewer/common/build.gradle.kts
@@ -0,0 +1,54 @@
+plugins {
+ id("com.android.library")
+ kotlin("multiplatform")
+ id("org.jetbrains.compose")
+}
+
+kotlin {
+ android()
+ jvm("desktop")
+ sourceSets {
+ named("commonMain") {
+ dependencies {
+ api(compose.runtime)
+ api(compose.foundation)
+ api(compose.material)
+ implementation("io.ktor:ktor-client-core:1.4.1")
+ }
+ }
+ named("androidMain") {
+ dependencies {
+ api("androidx.appcompat:appcompat:1.5.1")
+ api("androidx.core:core-ktx:1.8.0")
+ implementation("io.ktor:ktor-client-cio:1.4.1")
+ }
+ }
+ named("desktopMain") {
+ dependencies {
+ api(compose.desktop.common)
+ implementation("io.ktor:ktor-client-cio:1.4.1")
+ }
+ }
+ }
+}
+
+android {
+ compileSdk = 32
+
+ defaultConfig {
+ minSdk = 26
+ targetSdk = 32
+ }
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+ }
+
+ sourceSets {
+ named("main") {
+ manifest.srcFile("src/androidMain/AndroidManifest.xml")
+ res.srcDirs("src/androidMain/res")
+ }
+ }
+}
diff --git a/experimental/examples/imageviewer/common/src/androidMain/AndroidManifest.xml b/experimental/examples/imageviewer/common/src/androidMain/AndroidManifest.xml
new file mode 100755
index 0000000000..7a302a744c
--- /dev/null
+++ b/experimental/examples/imageviewer/common/src/androidMain/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
\ 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
new file mode 100755
index 0000000000..bf5d0b8c88
--- /dev/null
+++ b/experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/core/BitmapFilter.kt
@@ -0,0 +1,7 @@
+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
new file mode 100644
index 0000000000..00d4b026bc
--- /dev/null
+++ b/experimental/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/model/AndroidContentState.kt
@@ -0,0 +1,383 @@
+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