From 33b7e31f35f76f1002ce586db681b6b0aefdf5fe Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Wed, 9 Oct 2024 16:56:56 -0400 Subject: [PATCH 01/19] initial commit --- androidApp/build.gradle.kts | 12 ++--- atomik/build.gradle.kts | 21 ++++---- build.gradle.kts | 23 ++++---- desktopApp/build.gradle.kts | 15 +++--- .../kotlin-project-structure-metadata.json | 28 ---------- .../build/tmp/allMetadataJar/MANIFEST.MF | 2 - gradle.properties | 5 -- gradle/libs.versions.toml | 21 ++++++++ gradle/wrapper/gradle-wrapper.properties | 3 +- settings.gradle.kts | 38 ++++---------- shared/build.gradle.kts | 52 +++++++++---------- .../fotopresenter/KoinAndroid.kt | 2 + .../com/kevinschildhorn/fotopresenter/Koin.kt | 2 +- 13 files changed, 97 insertions(+), 127 deletions(-) delete mode 100644 desktopApp/build/kotlinProjectStructureMetadata/kotlin-project-structure-metadata.json delete mode 100644 desktopApp/build/tmp/allMetadataJar/MANIFEST.MF create mode 100644 gradle/libs.versions.toml diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index acef0180..73989477 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -1,9 +1,9 @@ plugins { - kotlin("multiplatform") id("com.android.application") - id("org.jetbrains.compose") - id("com.google.gms.google-services") - id("com.google.firebase.crashlytics") + kotlin("multiplatform") + alias(libs.plugins.google.services) + alias(libs.plugins.crashlytics) + alias(libs.plugins.kotlin.compose) } kotlin { @@ -12,8 +12,8 @@ kotlin { val androidMain by getting { dependencies { implementation(project(":shared")) - implementation("io.insert-koin:koin-android:3.4.0") - implementation("com.google.firebase:firebase-crashlytics:18.6.0") + implementation("io.insert-koin:koin-android:3.5.3") + implementation("com.google.firebase:firebase-crashlytics:19.2.0") } } } diff --git a/atomik/build.gradle.kts b/atomik/build.gradle.kts index 606c3e12..6b9a6282 100644 --- a/atomik/build.gradle.kts +++ b/atomik/build.gradle.kts @@ -1,8 +1,8 @@ plugins { kotlin("multiplatform") - id("com.android.library") - id("org.jetbrains.compose") - id("org.jlleitschuh.gradle.ktlint") + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.compose) + alias(libs.plugins.ktlint) } /* // Exclude compose from iOS @@ -51,13 +51,14 @@ kotlin { jvmToolchain(15) sourceSets { val commonMain by getting { + dependencies { implementation(kotlin("stdlib-common")) - implementation("co.touchlab:kermit:1.2.2") - implementation(compose.runtime) + implementation("co.touchlab:kermit:2.0.4") + /*implementation(compose.runtime) implementation(compose.foundation) implementation(compose.material) - implementation(compose.ui) + implementation(compose.ui)*/ api("dev.icerock.moko:resources:0.23.0") api("dev.icerock.moko:resources-compose:0.23.0") // for compose multiplatform } @@ -73,9 +74,10 @@ kotlin { val androidMain by getting { dependsOn(jvmMain) + languageSettings.optIn("kotlin.ExperimentalMultiplatform") dependencies { - api("androidx.appcompat:appcompat:1.6.1") - api("androidx.core:core-ktx:1.12.0") + api("androidx.appcompat:appcompat:1.7.0") + api("androidx.core:core-ktx:1.13.1") } } /* @@ -91,6 +93,7 @@ kotlin { val desktopMain by getting { dependsOn(jvmMain) + languageSettings.optIn("kotlin.ExperimentalMultiplatform") } } } @@ -98,7 +101,7 @@ kotlin { android { namespace = "com.kevinschildhorn.atomik" - compileSdk = 33 + compileSdk = 34 defaultConfig { minSdk = (findProperty("android.minSdk") as String).toInt() diff --git a/build.gradle.kts b/build.gradle.kts index b9249406..50278925 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,14 +1,13 @@ plugins { - // this is necessary to avoid the plugins to be loaded multiple times - // in each subproject's classloader - kotlin("multiplatform").apply(false) - id("com.android.application").apply(false) - id("com.android.library").apply(false) - id("org.jetbrains.compose").apply(false) - id("org.jlleitschuh.gradle.ktlint").version("12.0.2").apply(false) - id("dev.icerock.mobile.multiplatform-resources").version("0.23.0").apply(false) - id("app.cash.sqldelight").version("2.0.1").apply(false) - kotlin("plugin.serialization").version("1.9.21").apply(false) - id("com.google.firebase.crashlytics").version("2.9.9").apply(false) - id("com.google.gms.google-services").version("4.4.0").apply(false) + alias(libs.plugins.google.services).apply(false) + alias(libs.plugins.crashlytics).apply(false) + alias(libs.plugins.android.application).apply(false) + alias(libs.plugins.android.library).apply(false) + alias(libs.plugins.kotlin.android).apply(false) + alias(libs.plugins.kotlin.compose).apply(false) + alias(libs.plugins.sqldelight).apply(false) + alias(libs.plugins.resources).apply(false) + alias(libs.plugins.serialization).apply(false) + alias(libs.plugins.kotlinMultiplatform).apply(false) + } diff --git a/desktopApp/build.gradle.kts b/desktopApp/build.gradle.kts index 37d582e4..c2e526d4 100644 --- a/desktopApp/build.gradle.kts +++ b/desktopApp/build.gradle.kts @@ -1,8 +1,7 @@ -import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { kotlin("multiplatform") - id("org.jetbrains.compose") + alias(libs.plugins.kotlin.compose) } kotlin { @@ -10,17 +9,17 @@ kotlin { sourceSets { val jvmMain by getting { dependencies { - implementation(compose.desktop.currentOs) - implementation("io.insert-koin:koin-core:3.4.0") - implementation("co.touchlab:kermit:1.2.2") - implementation("com.russhwolf:multiplatform-settings:1.0.0") + //implementation(compose.desktop.currentOs) + implementation("io.insert-koin:koin-core:3.5.3") + implementation("co.touchlab:kermit:2.0.4") + implementation("com.russhwolf:multiplatform-settings:1.1.1") implementation(project(":shared")) } } } } - +/* compose.desktop { application { mainClass = "MainKt" @@ -31,4 +30,4 @@ compose.desktop { packageVersion = "1.0.0" } } -} +}*/ diff --git a/desktopApp/build/kotlinProjectStructureMetadata/kotlin-project-structure-metadata.json b/desktopApp/build/kotlinProjectStructureMetadata/kotlin-project-structure-metadata.json deleted file mode 100644 index fda7cbb1..00000000 --- a/desktopApp/build/kotlinProjectStructureMetadata/kotlin-project-structure-metadata.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "projectStructure": { - "formatVersion": "0.3.3", - "isPublishedAsRoot": "true", - "variants": [ - { - "name": "jvmApiElements", - "sourceSet": [ - "commonMain" - ] - }, - { - "name": "jvmRuntimeElements", - "sourceSet": [ - "commonMain" - ] - } - ], - "sourceSets": [ - { - "name": "commonMain", - "dependsOn": [], - "moduleDependency": [], - "binaryLayout": "klib" - } - ] - } -} \ No newline at end of file diff --git a/desktopApp/build/tmp/allMetadataJar/MANIFEST.MF b/desktopApp/build/tmp/allMetadataJar/MANIFEST.MF deleted file mode 100644 index 59499bce..00000000 --- a/desktopApp/build/tmp/allMetadataJar/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Manifest-Version: 1.0 - diff --git a/gradle.properties b/gradle.properties index 283cc9cd..6efd8543 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,8 +14,3 @@ android.useAndroidX=true android.compileSdk=34 android.targetSdk=34 android.minSdk=23 - -#Versions -kotlin.version=1.9.21 -agp.version=8.1.4 -compose.version=1.5.11 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 00000000..bcaae2a4 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,21 @@ +[versions] +agp = "8.5.2" +kotlin = "2.0.10" +crashlytics = "3.0.2" +google-services = "4.4.2" +ktlint-plugin = "12.1.1" +sqldelight = "2.0.2" +resources = "0.24.3" + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +android-library = { id = "com.android.library", version.ref = "agp" } +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +google-services = { id = "com.google.gms.google-services", version.ref = "google-services" } +crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "crashlytics" } +ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint-plugin" } +sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" } +resources = { id = "dev.icerock.mobile.multiplatform-resources", version.ref = "resources"} +serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a5952066..a19841b5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Wed Oct 09 16:09:25 EDT 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index 63d189bd..8f47dbe6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,42 +1,22 @@ -rootProject.name = "FotoPresenter" - -include(":androidApp") -include(":shared") -include(":desktopApp") -include(":atomik") pluginManagement { repositories { - gradlePluginPortal() - mavenCentral() google() + mavenCentral() + gradlePluginPortal() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } - - plugins { - val kotlinVersion = extra["kotlin.version"] as String - val agpVersion = extra["agp.version"] as String - val composeVersion = extra["compose.version"] as String - - kotlin("jvm").version(kotlinVersion) - kotlin("multiplatform").version(kotlinVersion) - kotlin("android").version(kotlinVersion) - - id("com.android.application").version(agpVersion) - id("com.android.library").version(agpVersion) - - id("org.jetbrains.compose").version(composeVersion) - } -} - -plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version("0.4.0") } - dependencyResolutionManagement { repositories { - mavenCentral() google() + mavenCentral() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } } + +rootProject.name = "FotoPresenter" +include(":androidApp") +include(":shared") +include(":desktopApp") +include(":atomik") \ No newline at end of file diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index b27f9b45..f522a775 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -1,13 +1,12 @@ plugins { - kotlin("multiplatform") - id("com.android.library") - id("org.jetbrains.compose") - id("org.jlleitschuh.gradle.ktlint") - id("dev.icerock.mobile.multiplatform-resources") - id("app.cash.sqldelight") - id("com.google.firebase.crashlytics") - - kotlin("plugin.serialization") + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.compose) + alias(libs.plugins.ktlint) + alias(libs.plugins.sqldelight) + //alias(libs.plugins.crashlytics) + alias(libs.plugins.resources) + alias(libs.plugins.serialization) } kotlin { @@ -29,21 +28,22 @@ kotlin { sourceSets { val commonMain by getting { dependencies { + implementation(kotlin("stdlib-common")) implementation(project(":atomik")) - implementation(compose.runtime) - implementation(compose.foundation) - implementation(compose.material) - @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) - implementation(compose.components.resources) + //implementation(compose.runtime) + //implementation(compose.foundation) + //implementation(compose.material) + //@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) + //implementation(compose.components.resources) implementation("br.com.devsrsouza.compose.icons:eva-icons:1.1.0") implementation("io.github.reactivecircus.cache4k:cache4k:0.12.0") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2") - implementation("io.insert-koin:koin-core:3.4.0") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.2") + implementation("io.insert-koin:koin-core:3.5.3") implementation("androidx.security:security-crypto:1.1.0-alpha06") - implementation("co.touchlab:kermit:1.2.2") + implementation("co.touchlab:kermit:2.0.4") implementation("co.touchlab:kermit-koin:1.2.2") - implementation("com.russhwolf:multiplatform-settings:1.0.0") - implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.5.0") + implementation("com.russhwolf:multiplatform-settings:1.1.1") + implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0") implementation("com.ashampoo:kim:0.8.3") api("dev.icerock.moko:resources:0.23.0") api("dev.icerock.moko:resources-compose:0.23.0") // for compose multiplatform @@ -65,7 +65,7 @@ kotlin { resources.srcDir("src/commonMain/resources") dependencies { implementation("com.hierynomus:smbj:0.11.5") - implementation(compose.uiTooling) + //implementation(compose.uiTooling) implementation("app.cash.sqldelight:sqlite-driver:2.0.1") } } @@ -74,9 +74,9 @@ kotlin { dependsOn(jvmMain) resources.srcDirs("src/commonMain/resources") dependencies { - api("androidx.activity:activity-compose:1.8.1") - api("androidx.appcompat:appcompat:1.6.1") - api("androidx.core:core-ktx:1.12.0") + api("androidx.activity:activity-compose:2.0.10") + api("androidx.appcompat:appcompat:1.7.0") + api("androidx.core:core-ktx:1.13.1") implementation("io.github.kevinschildhorn:atomik:0.0.6") implementation("app.cash.sqldelight:android-driver:2.0.1") } @@ -97,8 +97,8 @@ kotlin { dependsOn(jvmMain) dependencies { resources.srcDirs("src/commonMain/resources") - implementation(compose.preview) - implementation(compose.desktop.common) + //implementation(compose.preview) + //implementation(compose.desktop.common) } } } @@ -125,7 +125,7 @@ android { } multiplatformResources { - multiplatformResourcesPackage = "com.kevinschildhorn.fotopresenter" // required + //multiplatformResourcesPackage = "com.kevinschildhorn.fotopresenter" // required } dependencies { diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt index f880f59b..b4b5b554 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt @@ -12,6 +12,7 @@ import com.kevinschildhorn.fotopresenter.ui.shared.DriverFactory import com.russhwolf.settings.Settings import com.russhwolf.settings.SharedPreferencesSettings import org.koin.core.KoinApplication +import org.koin.core.annotation.KoinInternalApi import org.koin.core.context.startKoin import org.koin.core.logger.Level import org.koin.core.module.Module @@ -46,6 +47,7 @@ internal actual val platformModule: Module = module { single { DriverFactory(context = get()).createDriver() } } +@OptIn(KoinInternalApi::class) fun KoinApplication.androidContext(androidContext: Context): KoinApplication { if (koin.logger.isAt(Level.INFO)) { koin.logger.info("[init] declare Android Context") diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt index 32f875b1..27543619 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt @@ -33,7 +33,7 @@ import org.koin.core.module.Module import org.koin.dsl.module -val baseLogger = Logger(LoggerConfig.default) +val baseLogger = Logger.withTag("") val commonModule = From 4af6c11838157e92c4460255d4b8bc102b5ecf31 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 10 Oct 2024 10:48:09 -0400 Subject: [PATCH 02/19] updating more details --- androidApp/build.gradle.kts | 7 +- atomik/build.gradle.kts | 26 ++++-- build.gradle.kts | 3 +- desktopApp/build.gradle.kts | 8 +- gradle/libs.versions.toml | 54 +++++++++++- shared/build.gradle.kts | 84 +++++++++++-------- .../fotopresenter/UseCaseFactoryDesktop.kt | 1 - 7 files changed, 130 insertions(+), 53 deletions(-) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 73989477..1962eab1 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -3,7 +3,8 @@ plugins { kotlin("multiplatform") alias(libs.plugins.google.services) alias(libs.plugins.crashlytics) - alias(libs.plugins.kotlin.compose) + alias(libs.plugins.compose.compiler) + alias(libs.plugins.jetbrains.compose) } kotlin { @@ -12,8 +13,8 @@ kotlin { val androidMain by getting { dependencies { implementation(project(":shared")) - implementation("io.insert-koin:koin-android:3.5.3") - implementation("com.google.firebase:firebase-crashlytics:19.2.0") + implementation(libs.koin.android) + implementation(libs.firebase.crashlytics) } } } diff --git a/atomik/build.gradle.kts b/atomik/build.gradle.kts index 6b9a6282..1cc4a759 100644 --- a/atomik/build.gradle.kts +++ b/atomik/build.gradle.kts @@ -1,7 +1,13 @@ +@file:OptIn(ExperimentalKotlinGradlePluginApi::class) + +import org.gradle.kotlin.dsl.add +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi + plugins { kotlin("multiplatform") alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.compose) + alias(libs.plugins.compose.compiler) + alias(libs.plugins.jetbrains.compose) alias(libs.plugins.ktlint) } /* @@ -54,13 +60,13 @@ kotlin { dependencies { implementation(kotlin("stdlib-common")) - implementation("co.touchlab:kermit:2.0.4") - /*implementation(compose.runtime) + implementation(libs.kermit) + implementation(compose.runtime) implementation(compose.foundation) implementation(compose.material) - implementation(compose.ui)*/ - api("dev.icerock.moko:resources:0.23.0") - api("dev.icerock.moko:resources-compose:0.23.0") // for compose multiplatform + implementation(compose.ui) + api(libs.resources) + api(libs.resources.compose) // for compose multiplatform } } val commonTest by getting { @@ -76,8 +82,8 @@ kotlin { dependsOn(jvmMain) languageSettings.optIn("kotlin.ExperimentalMultiplatform") dependencies { - api("androidx.appcompat:appcompat:1.7.0") - api("androidx.core:core-ktx:1.13.1") + api(libs.appcompat) + api(libs.core.ktx) } } /* @@ -96,6 +102,10 @@ kotlin { languageSettings.optIn("kotlin.ExperimentalMultiplatform") } } + + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + } } android { diff --git a/build.gradle.kts b/build.gradle.kts index 50278925..7d0d9df1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,8 @@ plugins { alias(libs.plugins.android.application).apply(false) alias(libs.plugins.android.library).apply(false) alias(libs.plugins.kotlin.android).apply(false) - alias(libs.plugins.kotlin.compose).apply(false) + alias(libs.plugins.compose.compiler).apply(false) + alias(libs.plugins.jetbrains.compose).apply(false) alias(libs.plugins.sqldelight).apply(false) alias(libs.plugins.resources).apply(false) alias(libs.plugins.serialization).apply(false) diff --git a/desktopApp/build.gradle.kts b/desktopApp/build.gradle.kts index c2e526d4..40940c87 100644 --- a/desktopApp/build.gradle.kts +++ b/desktopApp/build.gradle.kts @@ -1,7 +1,7 @@ plugins { kotlin("multiplatform") - alias(libs.plugins.kotlin.compose) + alias(libs.plugins.compose.compiler) } kotlin { @@ -10,9 +10,9 @@ kotlin { val jvmMain by getting { dependencies { //implementation(compose.desktop.currentOs) - implementation("io.insert-koin:koin-core:3.5.3") - implementation("co.touchlab:kermit:2.0.4") - implementation("com.russhwolf:multiplatform-settings:1.1.1") + implementation(libs.koin.core) + implementation(libs.kermit) + implementation(libs.multiplatform.settings) implementation(project(":shared")) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bcaae2a4..e3ec5453 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,17 +1,69 @@ [versions] +activity-compose = "1.9.2" agp = "8.5.2" +appcompat = "1.7.0" +atomik = "0.0.6" +cache4k = "0.12.0" +core-ktx = "1.13.1" +eva-icons = "1.1.0" +firebase-crashlytics = "19.2.0" +kermit = "2.0.4" +kermit-koin = "1.2.2" +kim = "0.8.3" +koin-core = "3.5.3" +koin-test = "3.4.0" kotlin = "2.0.10" crashlytics = "3.0.2" google-services = "4.4.2" +kotlinx-datetime = "0.6.0" +kotlinx-serialization-json = "1.7.3" +ktlint = "0.0.26" ktlint-plugin = "12.1.1" +multiplatform-settings = "1.1.1" +multiplatform-settings-test = "1.0.0" +resources-version = "0.23.0" +security-crypto = "1.1.0-alpha06" +smbj = "0.11.5" sqldelight = "2.0.2" resources = "0.24.3" +compose = "1.6.11" +sqlite-driver = "2.0.1" +turbine = "1.0.0" + +[libraries] +activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity-compose" } +android-driver = { module = "app.cash.sqldelight:android-driver", version.ref = "sqlite-driver" } +appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" } +atomik = { module = "io.github.kevinschildhorn:atomik", version.ref = "atomik" } +cache4k = { module = "io.github.reactivecircus.cache4k:cache4k", version.ref = "cache4k" } +core-ktx = { module = "androidx.core:core-ktx", version.ref = "core-ktx" } +eva-icons = { module = "br.com.devsrsouza.compose.icons:eva-icons", version.ref = "eva-icons" } +firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics", version.ref = "firebase-crashlytics" } +kermit = { module = "co.touchlab:kermit", version.ref = "kermit" } +kermit-koin = { module = "co.touchlab:kermit-koin", version.ref = "kermit-koin" } +kim = { module = "com.ashampoo:kim", version.ref = "kim" } +koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin-core" } +koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin-core" } +koin-test = { module = "io.insert-koin:koin-test", version.ref = "koin-test" } +kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-serialization-json" } +kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" } +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization-json" } +ktlint = { module = "com.twitter.compose.rules:ktlint", version.ref = "ktlint" } +multiplatform-settings = { module = "com.russhwolf:multiplatform-settings", version.ref = "multiplatform-settings" } +multiplatform-settings-test = { module = "com.russhwolf:multiplatform-settings-test", version.ref = "multiplatform-settings-test" } +resources = { module = "dev.icerock.moko:resources", version.ref = "resources-version" } +resources-compose = { module = "dev.icerock.moko:resources-compose", version.ref = "resources-version" } +security-crypto = { module = "androidx.security:security-crypto", version.ref = "security-crypto" } +smbj = { module = "com.hierynomus:smbj", version.ref = "smbj" } +sqlite-driver = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqlite-driver" } +turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } android-library = { id = "com.android.library", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } -kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +jetbrains-compose = { id = "org.jetbrains.compose", version.ref = "compose" } +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } google-services = { id = "com.google.gms.google-services", version.ref = "google-services" } crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "crashlytics" } diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index f522a775..a0bdac8a 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -1,7 +1,13 @@ +@file:OptIn(ExperimentalKotlinGradlePluginApi::class) + +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import kotlin.collections.plusAssign + plugins { alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.compose) + alias(libs.plugins.compose.compiler) + alias(libs.plugins.jetbrains.compose) alias(libs.plugins.ktlint) alias(libs.plugins.sqldelight) //alias(libs.plugins.crashlytics) @@ -26,37 +32,40 @@ kotlin { }*/ sourceSets { + all { + languageSettings.optIn("kotlin.RequiresOptIn") + } val commonMain by getting { dependencies { implementation(kotlin("stdlib-common")) implementation(project(":atomik")) - //implementation(compose.runtime) - //implementation(compose.foundation) - //implementation(compose.material) - //@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) - //implementation(compose.components.resources) - implementation("br.com.devsrsouza.compose.icons:eva-icons:1.1.0") - implementation("io.github.reactivecircus.cache4k:cache4k:0.12.0") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.2") - implementation("io.insert-koin:koin-core:3.5.3") - implementation("androidx.security:security-crypto:1.1.0-alpha06") - implementation("co.touchlab:kermit:2.0.4") - implementation("co.touchlab:kermit-koin:1.2.2") - implementation("com.russhwolf:multiplatform-settings:1.1.1") - implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0") - implementation("com.ashampoo:kim:0.8.3") - api("dev.icerock.moko:resources:0.23.0") - api("dev.icerock.moko:resources-compose:0.23.0") // for compose multiplatform + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material) + @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) + implementation(compose.components.resources) + implementation(libs.eva.icons) + implementation(libs.cache4k) + implementation(libs.kotlinx.serialization.json) + implementation(libs.koin.core) + implementation(libs.security.crypto) + implementation(libs.kermit) + implementation(libs.kermit.koin) + implementation(libs.multiplatform.settings) + implementation(libs.kotlinx.datetime) + implementation(libs.kim) + api(libs.resources) + api(libs.resources.compose) // for compose multiplatform } } val commonTest by getting { dependencies { implementation(kotlin("test")) - implementation("com.russhwolf:multiplatform-settings-test:1.0.0") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") - implementation("io.insert-koin:koin-test:3.4.0") - implementation("app.cash.turbine:turbine:1.0.0") - implementation("app.cash.sqldelight:sqlite-driver:2.0.1") + implementation(libs.multiplatform.settings.test) + implementation(libs.kotlinx.coroutines.test) + implementation(libs.koin.test) + implementation(libs.turbine) + implementation(libs.sqlite.driver) } } @@ -64,9 +73,9 @@ kotlin { dependsOn(commonMain) resources.srcDir("src/commonMain/resources") dependencies { - implementation("com.hierynomus:smbj:0.11.5") - //implementation(compose.uiTooling) - implementation("app.cash.sqldelight:sqlite-driver:2.0.1") + implementation(libs.smbj) + implementation(compose.uiTooling) + implementation(libs.sqlite.driver) } } @@ -74,11 +83,11 @@ kotlin { dependsOn(jvmMain) resources.srcDirs("src/commonMain/resources") dependencies { - api("androidx.activity:activity-compose:2.0.10") - api("androidx.appcompat:appcompat:1.7.0") - api("androidx.core:core-ktx:1.13.1") - implementation("io.github.kevinschildhorn:atomik:0.0.6") - implementation("app.cash.sqldelight:android-driver:2.0.1") + api(libs.activity.compose) + api(libs.appcompat) + api(libs.core.ktx) + implementation(libs.atomik) + implementation(libs.android.driver) } } /* @@ -97,11 +106,15 @@ kotlin { dependsOn(jvmMain) dependencies { resources.srcDirs("src/commonMain/resources") - //implementation(compose.preview) - //implementation(compose.desktop.common) + implementation(compose.preview) + implementation(compose.desktop.common) } } } + + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + } } android { @@ -125,11 +138,12 @@ android { } multiplatformResources { - //multiplatformResourcesPackage = "com.kevinschildhorn.fotopresenter" // required + resourcesPackage.set("com.kevinschildhorn.fotopresenter") // required + resourcesClassName.set("SharedRes") } dependencies { - ktlintRuleset("com.twitter.compose.rules:ktlint:0.0.26") + ktlintRuleset(libs.ktlint) } sqldelight { diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt index 7ff30a9b..460b0abf 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt @@ -32,7 +32,6 @@ import java.util.prefs.Preferences actual object UseCaseFactory { - val baseLogger = Logger(LoggerConfig.default) private val preferences: Preferences = Preferences.userRoot() private val settings = PreferencesSettings(preferences) private val networkHandler: NetworkHandler = SMBJHandler From 226f277661a52995b15f581437126cd0a92d9984 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 10 Oct 2024 11:39:46 -0400 Subject: [PATCH 03/19] updating dependencies --- androidApp/build.gradle.kts | 11 +++++---- atomik/build.gradle.kts | 23 ++++++++----------- .../atomik/atomic/atoms/compose/+TextAtom.kt | 2 +- gradle.properties | 3 --- gradle/libs.versions.toml | 15 +++++++++--- shared/build.gradle.kts | 13 +++++------ .../screens/common/composables/AtomikText.kt | 2 +- .../screens/common/composables/ErrorView.kt | 2 -- .../common/composables/PrimaryTextButton.kt | 2 +- .../screens/common/composables/TitleView.kt | 3 --- .../common/composables/ToastOverlay.kt | 2 +- .../ui/screens/directory/DirectoryScreen.kt | 2 +- .../composables/grid/DirectoryGridCell.kt | 2 +- .../composables/LoginPasswordTextField.kt | 2 +- .../login/composables/LoginTextField.kt | 2 +- .../composables/PlaylistScreenCreateRow.kt | 4 ---- .../composables/PlaylistScreenPlaylistRow.kt | 4 ---- 17 files changed, 43 insertions(+), 51 deletions(-) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 1962eab1..1614f358 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -1,3 +1,6 @@ +import org.gradle.kotlin.dsl.get +import org.gradle.kotlin.dsl.java + plugins { id("com.android.application") kotlin("multiplatform") @@ -21,15 +24,15 @@ kotlin { } android { - compileSdk = (findProperty("android.compileSdk") as String).toInt() + compileSdk = libs.versions.compileSdk.get().toInt() namespace = "com.kevinschildhorn" sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") defaultConfig { applicationId = "com.kevinschildhorn.fotopresenter" - minSdk = (findProperty("android.minSdk") as String).toInt() - targetSdk = (findProperty("android.targetSdk") as String).toInt() + minSdk = libs.versions.minSdk.get().toInt() + targetSdk = libs.versions.targetSdk.get().toInt() versionCode = 1 versionName = "1.0" } @@ -38,6 +41,6 @@ android { targetCompatibility = JavaVersion.VERSION_17 } kotlin { - jvmToolchain(17) + jvmToolchain(libs.versions.java.get().toInt()) } } diff --git a/atomik/build.gradle.kts b/atomik/build.gradle.kts index 1cc4a759..56a243bd 100644 --- a/atomik/build.gradle.kts +++ b/atomik/build.gradle.kts @@ -1,6 +1,9 @@ @file:OptIn(ExperimentalKotlinGradlePluginApi::class) import org.gradle.kotlin.dsl.add +import org.gradle.kotlin.dsl.get +import org.gradle.kotlin.dsl.implementation +import org.gradle.kotlin.dsl.java import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi plugins { @@ -29,12 +32,6 @@ android { namespace = "com.kevinschildhorn.atomik" } -tasks.withType().configureEach { - kotlinOptions { - jvmTarget = "15" - } -} - kotlin { explicitApi() applyDefaultHierarchyTemplate() @@ -54,7 +51,7 @@ kotlin { }*/ jvm("desktop") - jvmToolchain(15) + jvmToolchain(libs.versions.java.get().toInt()) sourceSets { val commonMain by getting { @@ -65,8 +62,8 @@ kotlin { implementation(compose.foundation) implementation(compose.material) implementation(compose.ui) - api(libs.resources) - api(libs.resources.compose) // for compose multiplatform + implementation(compose.components.resources) + api(libs.bundles.moko.resources) } } val commonTest by getting { @@ -111,15 +108,15 @@ kotlin { android { namespace = "com.kevinschildhorn.atomik" - compileSdk = 34 + compileSdk = libs.versions.compileSdk.get().toInt() defaultConfig { - minSdk = (findProperty("android.minSdk") as String).toInt() + minSdk = libs.versions.minSdk.get().toInt() } compileOptions { - sourceCompatibility = JavaVersion.VERSION_15 - targetCompatibility = JavaVersion.VERSION_15 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } sourceSets { diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+TextAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+TextAtom.kt index 296a704d..a3b655c4 100644 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+TextAtom.kt +++ b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+TextAtom.kt @@ -1,6 +1,6 @@ @file:Suppress("ktlint:standard:filename") -package com.kevinschildhorn.atomik.atomic.atoms +package com.kevinschildhorn.atomik.atomic.atoms.compose import androidx.compose.runtime.Composable import androidx.compose.ui.text.TextStyle diff --git a/gradle.properties b/gradle.properties index 6efd8543..8b768577 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,6 +11,3 @@ kotlin.mpp.androidSourceSetLayoutVersion=2 #Android android.useAndroidX=true -android.compileSdk=34 -android.targetSdk=34 -android.minSdk=23 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e3ec5453..57a818b8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,11 +25,17 @@ resources-version = "0.23.0" security-crypto = "1.1.0-alpha06" smbj = "0.11.5" sqldelight = "2.0.2" -resources = "0.24.3" +resources = "0.23.0" compose = "1.6.11" sqlite-driver = "2.0.1" turbine = "1.0.0" +## SDK Versions +minSdk = "23" +targetSdk = "34" +compileSdk = "34" +java = "21" + [libraries] activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity-compose" } android-driver = { module = "app.cash.sqldelight:android-driver", version.ref = "sqlite-driver" } @@ -51,8 +57,8 @@ kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serializa ktlint = { module = "com.twitter.compose.rules:ktlint", version.ref = "ktlint" } multiplatform-settings = { module = "com.russhwolf:multiplatform-settings", version.ref = "multiplatform-settings" } multiplatform-settings-test = { module = "com.russhwolf:multiplatform-settings-test", version.ref = "multiplatform-settings-test" } -resources = { module = "dev.icerock.moko:resources", version.ref = "resources-version" } -resources-compose = { module = "dev.icerock.moko:resources-compose", version.ref = "resources-version" } +moko-resource = { module = "dev.icerock.moko:resources", version.ref = "resources-version" } +moko-resource-compose = { module = "dev.icerock.moko:resources-compose", version.ref = "resources-version" } security-crypto = { module = "androidx.security:security-crypto", version.ref = "security-crypto" } smbj = { module = "com.hierynomus:smbj", version.ref = "smbj" } sqlite-driver = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqlite-driver" } @@ -71,3 +77,6 @@ ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint-plugin" } sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" } resources = { id = "dev.icerock.mobile.multiplatform-resources", version.ref = "resources"} serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } + +[bundles] +moko-resources = ["moko-resource", "moko-resource-compose"] \ No newline at end of file diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index a0bdac8a..90c337ce 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -1,5 +1,6 @@ @file:OptIn(ExperimentalKotlinGradlePluginApi::class) +import org.gradle.kotlin.dsl.get import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import kotlin.collections.plusAssign @@ -54,8 +55,7 @@ kotlin { implementation(libs.multiplatform.settings) implementation(libs.kotlinx.datetime) implementation(libs.kim) - api(libs.resources) - api(libs.resources.compose) // for compose multiplatform + api(libs.bundles.moko.resources) } } val commonTest by getting { @@ -118,7 +118,7 @@ kotlin { } android { - compileSdk = (findProperty("android.compileSdk") as String).toInt() + compileSdk = libs.versions.compileSdk.get().toInt() namespace = "com.kevinschildhorn.common" sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") @@ -126,20 +126,19 @@ android { sourceSets["main"].resources.srcDirs("src/commonMain/resources") defaultConfig { - minSdk = (findProperty("android.minSdk") as String).toInt() + minSdk = libs.versions.minSdk.get().toInt() } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } kotlin { - jvmToolchain(17) + jvmToolchain(libs.versions.java.get().toInt()) } } multiplatformResources { - resourcesPackage.set("com.kevinschildhorn.fotopresenter") // required - resourcesClassName.set("SharedRes") + multiplatformResourcesPackage = "com.kevinschildhorn.fotopresenter" // required } dependencies { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/AtomikText.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/AtomikText.kt index 64ddc51f..05d73a9e 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/AtomikText.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/AtomikText.kt @@ -4,7 +4,7 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.kevinschildhorn.atomik.atomic.atoms.interfaces.TextAtom -import com.kevinschildhorn.atomik.atomic.atoms.textStyle +import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle import com.kevinschildhorn.atomik.color.base.composeColor @Composable diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ErrorView.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ErrorView.kt index 444ef6f3..db75bc8a 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ErrorView.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ErrorView.kt @@ -4,11 +4,9 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.atomic.atoms.textStyle import com.kevinschildhorn.atomik.color.base.composeColor import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreenAtoms.errorView diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryTextButton.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryTextButton.kt index 9b3b12db..ec1bc121 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryTextButton.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryTextButton.kt @@ -4,7 +4,7 @@ package com.kevinschildhorn.fotopresenter.ui.screens.common.composables import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.kevinschildhorn.atomik.atomic.atoms.textStyle +import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreenAtoms @Composable diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/TitleView.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/TitleView.kt index de287166..c414599a 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/TitleView.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/TitleView.kt @@ -1,10 +1,7 @@ package com.kevinschildhorn.fotopresenter.ui.screens.common.composables -import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.kevinschildhorn.atomik.atomic.atoms.textStyle -import com.kevinschildhorn.atomik.color.base.composeColor import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreenAtoms.title diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ToastOverlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ToastOverlay.kt index 8e8fe956..547b7fba 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ToastOverlay.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ToastOverlay.kt @@ -21,7 +21,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.atomic.atoms.textStyle +import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle import com.kevinschildhorn.atomik.color.base.composeColor import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors import com.kevinschildhorn.fotopresenter.ui.atoms.Padding diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt index 4917e0ad..0345e49d 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt @@ -20,7 +20,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.atomic.atoms.textStyle +import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle import com.kevinschildhorn.atomik.color.base.composeColor import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails import com.kevinschildhorn.fotopresenter.ui.UiState diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGridCell.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGridCell.kt index 243b76c2..eda2ef93 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGridCell.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGridCell.kt @@ -13,7 +13,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.atomic.atoms.textStyle +import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle import com.kevinschildhorn.atomik.color.base.composeColor import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryAtoms diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginPasswordTextField.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginPasswordTextField.kt index 18cdedd4..e9475a2d 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginPasswordTextField.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginPasswordTextField.kt @@ -15,7 +15,7 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import com.kevinschildhorn.atomik.atomic.atoms.shape -import com.kevinschildhorn.atomik.atomic.atoms.textStyle +import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreenAtoms import compose.icons.EvaIcons import compose.icons.evaicons.Fill diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginTextField.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginTextField.kt index 2f45f716..23d4412f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginTextField.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginTextField.kt @@ -5,7 +5,7 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.kevinschildhorn.atomik.atomic.atoms.shape -import com.kevinschildhorn.atomik.atomic.atoms.textStyle +import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreenAtoms @Composable diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenCreateRow.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenCreateRow.kt index 3f6746ae..2967f69a 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenCreateRow.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenCreateRow.kt @@ -5,15 +5,11 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.width -import androidx.compose.material.Icon -import androidx.compose.material.Text import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.atomic.atoms.textStyle -import com.kevinschildhorn.atomik.color.base.composeColor import com.kevinschildhorn.fotopresenter.ui.atoms.Padding import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.AtomikIcon import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.AtomikText diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenPlaylistRow.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenPlaylistRow.kt index 2e4967c8..920f33db 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenPlaylistRow.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenPlaylistRow.kt @@ -8,15 +8,11 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.width -import androidx.compose.material.Icon -import androidx.compose.material.Text import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.atomic.atoms.textStyle -import com.kevinschildhorn.atomik.color.base.composeColor import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.AtomikIcon import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.AtomikText import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistScreenAtoms From ffcd000e9e479205a066a3cdcb256674c69cad4f Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 10 Oct 2024 13:40:46 -0400 Subject: [PATCH 04/19] Fixing composables --- androidApp/build.gradle.kts | 4 +- atomik/.gitignore | 1 - atomik/build.gradle.kts | 133 ------------------ atomik/src/androidMain/AndroidManifest.xml | 2 - .../atomic/atoms/xml/EditTextExtensions.kt | 12 -- .../atomic/atoms/xml/TextViewExtensions.kt | 37 ----- .../atomik/atomic/atoms/xml/ViewExtensions.kt | 18 --- .../atomik/color/base/AtomikColor.kt | 52 ------- .../typography/AtomikTypographyExtensions.kt | 26 ---- .../typography/PlatformTypographySet.kt | 55 -------- .../kevinschildhorn/atomik/DesignSystem.kt | 63 --------- .../atomik/ExperimentalAtomik.kt | 6 - .../atomik/atomic/atoms/Atom.kt | 39 ----- .../atomik/atomic/atoms/FigmaAtom.kt | 115 --------------- .../atomik/atomic/atoms/ImageAtom.kt | 12 -- .../atomik/atomic/atoms/TextViewAtom.kt | 25 ---- .../atomic/atoms/compose/+AtomikColorType.kt | 14 -- .../atomic/atoms/compose/+ConstrainedAtom.kt | 57 -------- .../atomic/atoms/compose/+EnablableAtom.kt | 13 -- .../atomic/atoms/compose/+FixedSizeAtom.kt | 14 -- .../atomic/atoms/compose/+RoundedAtom.kt | 11 -- .../atomik/atomic/atoms/compose/+TextAtom.kt | 43 ------ .../atomic/atoms/interfaces/AtomInterface.kt | 13 -- .../atomic/atoms/interfaces/AtomType.kt | 18 --- .../atomic/atoms/interfaces/BorderedAtom.kt | 22 --- .../atomic/atoms/interfaces/ColorAtom.kt | 26 ---- .../atoms/interfaces/ConstrainedAtom.kt | 40 ------ .../atomic/atoms/interfaces/EnablableAtom.kt | 19 --- .../atomic/atoms/interfaces/FixedSizeAtom.kt | 20 --- .../atomic/atoms/interfaces/PaddingAtom.kt | 36 ----- .../atomic/atoms/interfaces/ResourceAtom.kt | 10 -- .../atomic/atoms/interfaces/RoundedAtom.kt | 18 --- .../atomic/atoms/interfaces/TextAtom.kt | 36 ----- .../atomik/atomic/molecules/BaseMolecule.kt | 15 -- .../molecules/OutlinedTextFieldMolecule.kt | 86 ----------- .../atomic/molecules/TextButtonMolecule.kt | 16 --- .../atomic/molecules/TextFieldMolecule.kt | 74 ---------- .../atomik/atomic/organisms/BaseOrganism.kt | 7 - .../atomik/atomic/organisms/FormOrganism.kt | 7 - .../atomik/color/CustomColorSet.kt | 26 ---- .../atomik/color/CustomColorSetTyped.kt | 33 ----- .../atomik/color/base/AtomikColor.kt | 52 ------- .../atomik/color/base/AtomikColorData.kt | 101 ------------- .../atomik/color/base/AtomikColorType.kt | 13 -- .../atomik/color/base/ColorSet.kt | 20 --- .../atomik/typography/+TypographyWeight.kt | 17 --- .../atomik/typography/CustomTypographySet.kt | 27 ---- .../typography/CustomTypographySetTyped.kt | 34 ----- .../typography/base/AtomikFontFamily.kt | 14 -- .../typography/base/AtomikTypography.kt | 17 --- .../typography/base/AtomikTypographyType.kt | 13 -- .../typography/base/AtomikTypographyWeight.kt | 18 --- .../atomik/typography/base/TypographySet.kt | 20 --- .../kevinschildhorn/atomik/AtomikColorTest.kt | 103 -------------- .../atomik/color/base/AtomikColor.kt | 55 -------- .../atomik/atomic/atoms/+TextAtom.kt | 10 -- .../atomik/color/base/AtomikColor.kt | 48 ------- .../atomik/typography/+TypographyWeight.kt | 33 ----- .../typography/PlatformTypographySet.kt | 38 ----- .../typography/base/AtomikFontFamily.kt | 16 --- .../atomik/atomic/atoms/+Modifier.kt | 18 --- .../typography/base/AtomikFontFamily.kt | 15 -- build.gradle.kts | 1 - desktopApp/build.gradle.kts | 8 +- desktopApp/src/jvmMain/kotlin/Main.kt | 9 +- gradle/libs.versions.toml | 10 +- settings.gradle.kts | 1 - shared/build.gradle.kts | 12 +- .../ui/shared/SharedImageConverter.kt | 2 +- .../font/quicksand_bold.ttf} | Bin .../font/quicksand_light.ttf} | Bin .../font/quicksand_medium.ttf} | Bin .../font/quicksand_regular.ttf} | Bin .../font/quicksand_semibold.ttf} | Bin .../fotopresenter/ui/atoms/FotoColors.kt | 44 ++++-- .../fotopresenter/ui/atoms/FotoTypography.kt | 63 +++++---- .../fotopresenter/ui/screens/.DS_Store | Bin 0 -> 6148 bytes .../fotopresenter/ui/screens/common/.DS_Store | Bin 0 -> 6148 bytes .../ui/screens/common/CommonAtoms.kt | 32 ----- .../ui/screens/common/composables/.DS_Store | Bin 0 -> 6148 bytes .../screens/common/composables/ActionSheet.kt | 8 +- .../screens/common/composables/AtomikIcon.kt | 23 --- .../screens/common/composables/AtomikText.kt | 18 --- .../common/composables/ConfirmationDialog.kt | 3 +- .../common/composables/DialogButtonText.kt | 47 +++++++ .../screens/common/composables/ErrorView.kt | 13 +- .../common/composables/FilterDialog.kt | 28 +++- .../screens/common/composables/FotoDIalog.kt | 15 +- .../common/composables/ImagePreviewOverlay.kt | 4 +- .../common/composables/LoadingOverlay.kt | 8 +- .../ui/screens/common/composables/Overlay.kt | 6 +- .../common/composables/PrimaryButton.kt | 11 +- .../common/composables/PrimaryTextButton.kt | 8 +- .../screens/common/composables/TitleView.kt | 5 +- .../common/composables/ToastOverlay.kt | 11 +- .../ui/screens/directory/.DS_Store | Bin 0 -> 6148 bytes .../ui/screens/directory/DirectoryAtoms.kt | 55 -------- .../ui/screens/directory/DirectoryScreen.kt | 12 +- .../composables/grid/DirectoryGridCell.kt | 12 +- .../grid/FolderDirectoryGridCell.kt | 14 +- .../grid/ImageDirectoryGridCell.kt | 7 +- .../navbar/DirectoryNavigationBar.kt | 5 +- .../navbar/DirectoryNavigationHome.kt | 20 ++- .../navbar/DirectoryNavigationItem.kt | 19 +-- .../navrail/DirectoryTitleBarButton.kt | 5 +- .../navrail/NavigationRailOverlay.kt | 13 +- .../ui/screens/login/LoginScreenAtoms.kt | 62 -------- .../composables/LoginPasswordTextField.kt | 18 +-- .../login/composables/LoginTextField.kt | 30 ++-- .../screens/playlist/PlaylistScreenAtoms.kt | 20 --- .../playlist/composables/PlaylistColumn.kt | 16 +-- .../composables/PlaylistScreenCreateRow.kt | 13 +- .../composables/PlaylistScreenPlaylistRow.kt | 21 ++- .../kevinschildhorn/fotopresenter/KoinTest.kt | 2 +- .../domain/SaveCredentialsUseCaseTest.kt | 2 +- 115 files changed, 276 insertions(+), 2416 deletions(-) delete mode 100644 atomik/.gitignore delete mode 100644 atomik/build.gradle.kts delete mode 100644 atomik/src/androidMain/AndroidManifest.xml delete mode 100644 atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/xml/EditTextExtensions.kt delete mode 100644 atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/xml/TextViewExtensions.kt delete mode 100644 atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/xml/ViewExtensions.kt delete mode 100644 atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt delete mode 100644 atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/typography/AtomikTypographyExtensions.kt delete mode 100644 atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/typography/PlatformTypographySet.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/DesignSystem.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/ExperimentalAtomik.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/Atom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/FigmaAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/ImageAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/TextViewAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+AtomikColorType.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+ConstrainedAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+EnablableAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+FixedSizeAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+RoundedAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+TextAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/AtomInterface.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/AtomType.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/BorderedAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/ColorAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/ConstrainedAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/EnablableAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/FixedSizeAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/PaddingAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/ResourceAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/RoundedAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/TextAtom.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/BaseMolecule.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/OutlinedTextFieldMolecule.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/TextButtonMolecule.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/TextFieldMolecule.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/organisms/BaseOrganism.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/organisms/FormOrganism.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/CustomColorSet.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/CustomColorSetTyped.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColorData.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColorType.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/ColorSet.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/+TypographyWeight.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/CustomTypographySet.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/CustomTypographySetTyped.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikFontFamily.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikTypography.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikTypographyType.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikTypographyWeight.kt delete mode 100644 atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/TypographySet.kt delete mode 100644 atomik/src/commonTest/kotlin/com/kevinschildhorn/atomik/AtomikColorTest.kt delete mode 100644 atomik/src/desktopMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt delete mode 100644 atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/+TextAtom.kt delete mode 100644 atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt delete mode 100644 atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/typography/+TypographyWeight.kt delete mode 100644 atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/typography/PlatformTypographySet.kt delete mode 100644 atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikFontFamily.kt delete mode 100644 atomik/src/jvmMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/+Modifier.kt delete mode 100644 atomik/src/jvmMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikFontFamily.kt rename shared/src/commonMain/{resources/MR/fonts/Quicksand-Bold.ttf => composeResources/font/quicksand_bold.ttf} (100%) rename shared/src/commonMain/{resources/MR/fonts/Quicksand-Light.ttf => composeResources/font/quicksand_light.ttf} (100%) rename shared/src/commonMain/{resources/MR/fonts/Quicksand-Medium.ttf => composeResources/font/quicksand_medium.ttf} (100%) rename shared/src/commonMain/{resources/MR/fonts/Quicksand-Regular.ttf => composeResources/font/quicksand_regular.ttf} (100%) rename shared/src/commonMain/{resources/MR/fonts/Quicksand-Semibold.ttf => composeResources/font/quicksand_semibold.ttf} (100%) create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/.DS_Store create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/.DS_Store delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/CommonAtoms.kt create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/.DS_Store delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/AtomikIcon.kt delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/AtomikText.kt create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/DialogButtonText.kt create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/.DS_Store delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryAtoms.kt delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/LoginScreenAtoms.kt delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistScreenAtoms.kt diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 1614f358..d536b274 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -37,8 +37,8 @@ android { versionName = "1.0" } compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } kotlin { jvmToolchain(libs.versions.java.get().toInt()) diff --git a/atomik/.gitignore b/atomik/.gitignore deleted file mode 100644 index 42afabfd..00000000 --- a/atomik/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/atomik/build.gradle.kts b/atomik/build.gradle.kts deleted file mode 100644 index 56a243bd..00000000 --- a/atomik/build.gradle.kts +++ /dev/null @@ -1,133 +0,0 @@ -@file:OptIn(ExperimentalKotlinGradlePluginApi::class) - -import org.gradle.kotlin.dsl.add -import org.gradle.kotlin.dsl.get -import org.gradle.kotlin.dsl.implementation -import org.gradle.kotlin.dsl.java -import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi - -plugins { - kotlin("multiplatform") - alias(libs.plugins.android.library) - alias(libs.plugins.compose.compiler) - alias(libs.plugins.jetbrains.compose) - alias(libs.plugins.ktlint) -} -/* -// Exclude compose from iOS -plugins.removeAll { it is ComposeCompilerKotlinSupportPlugin } -class ComposeNoNativePlugin : org.jetbrains.kotlin.gradle.plugin.KotlinCompilerPluginSupportPlugin by ComposeCompilerKotlinSupportPlugin() { - override fun isApplicable(kotlinCompilation: org.jetbrains.kotlin.gradle.plugin.KotlinCompilation<*>): Boolean { - return when (kotlinCompilation.target.platformType) { - org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.native -> false - else -> ComposeCompilerKotlinSupportPlugin().isApplicable(kotlinCompilation) - } - } -} -apply() // Re-adding Compose Compilers only for non-native environments -*/ -group = "io.github.kevinschildhorn" -version = "0.0.6" -android { - namespace = "com.kevinschildhorn.atomik" -} - -kotlin { - explicitApi() - applyDefaultHierarchyTemplate() - androidTarget { - publishLibraryVariants("debug", "release") - } - jvm("desktop") - /* - listOf( - iosX64(), - iosArm64(), - iosSimulatorArm64(), - ).forEach { iosTarget -> - iosTarget.binaries.framework { - baseName = "atomik" - } - }*/ - jvm("desktop") - - jvmToolchain(libs.versions.java.get().toInt()) - sourceSets { - val commonMain by getting { - - dependencies { - implementation(kotlin("stdlib-common")) - implementation(libs.kermit) - implementation(compose.runtime) - implementation(compose.foundation) - implementation(compose.material) - implementation(compose.ui) - implementation(compose.components.resources) - api(libs.bundles.moko.resources) - } - } - val commonTest by getting { - dependencies { - implementation(kotlin("test")) - } - } - val jvmMain by creating { - dependsOn(commonMain) - } - - val androidMain by getting { - dependsOn(jvmMain) - languageSettings.optIn("kotlin.ExperimentalMultiplatform") - dependencies { - api(libs.appcompat) - api(libs.core.ktx) - } - } - /* - val iosX64Main by getting - val iosArm64Main by getting - val iosSimulatorArm64Main by getting - val iosMain by getting { - dependsOn(commonMain) - iosX64Main.dependsOn(this) - iosArm64Main.dependsOn(this) - iosSimulatorArm64Main.dependsOn(this) - }*/ - - val desktopMain by getting { - dependsOn(jvmMain) - languageSettings.optIn("kotlin.ExperimentalMultiplatform") - } - } - - compilerOptions { - freeCompilerArgs.add("-Xexpect-actual-classes") - } -} - -android { - namespace = "com.kevinschildhorn.atomik" - - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - minSdk = libs.versions.minSdk.get().toInt() - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 - } - - sourceSets { - named("main") { - manifest.srcFile("src/androidMain/AndroidManifest.xml") - res.srcDirs("src/androidMain/res") - } - } - buildTypes { - release { - isMinifyEnabled = true - } - } -} diff --git a/atomik/src/androidMain/AndroidManifest.xml b/atomik/src/androidMain/AndroidManifest.xml deleted file mode 100644 index de749acb..00000000 --- a/atomik/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/xml/EditTextExtensions.kt b/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/xml/EditTextExtensions.kt deleted file mode 100644 index e175de86..00000000 --- a/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/xml/EditTextExtensions.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms.xml - -import android.widget.EditText -import com.kevinschildhorn.atomik.atomic.molecules.TextFieldMolecule - -public fun EditText.applyMolecule(molecule: TextFieldMolecule) { - setTextColor(molecule.textAtom.textColor.viewColor) - // setBackgroundColor(molecule.backgroundColorAtom.color.viewColor) TODO Add later - molecule.hintTextAtom?.let { - setHintTextColor(it.textColor.viewColor) - } -} diff --git a/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/xml/TextViewExtensions.kt b/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/xml/TextViewExtensions.kt deleted file mode 100644 index b4c03cfb..00000000 --- a/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/xml/TextViewExtensions.kt +++ /dev/null @@ -1,37 +0,0 @@ -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.atomic.atoms.xml - -import android.widget.TextView -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.ColorAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.TextAtom -import com.kevinschildhorn.atomik.typography.typeFace - -/** - * Applies a [TextAtom] to a [TextView], setting the text color and size - * - * @param textAtom the [TextAtom] that will be applied to the [TextView] - */ -public fun TextView.applyTextAtom(textAtom: TextAtom?) { - textAtom?.let { - setTextColor(it.textColor.viewColor) - typeface = it.typography.typeFace - textSize = it.typography.size.toFloat() - } -} - -/** - * Applies a [ColorAtom] to a [TextView], setting the text color - * - * @param colorAtom the [ColorAtom] that will be applied to the [TextView] - * @param foreground a [Boolean] indicating whether the atom should be applied to the foreground or background [TextView] - */ -public fun TextView.applyColorAtom(colorAtom: ColorAtom?, foreground: Boolean = true) { - colorAtom?.let { - if (foreground) { - setTextColor(it.color.viewColor) - } else { - setBackgroundColor(it.color.viewColor) - } - } -} diff --git a/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/xml/ViewExtensions.kt b/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/xml/ViewExtensions.kt deleted file mode 100644 index 2d830197..00000000 --- a/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/xml/ViewExtensions.kt +++ /dev/null @@ -1,18 +0,0 @@ -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.atomic.atoms.xml - -import android.view.View -import android.widget.TextView -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.ColorAtom - -/** - * Applies a [ColorAtom] to a [TextView], setting the background color - * - * @param colorAtom the [ColorAtom] that will be applied to the [View] - */ -public fun View.applyColorAtom(colorAtom: ColorAtom?) { - colorAtom?.let { - setBackgroundColor(it.color.viewColor) - } -} diff --git a/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt b/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt deleted file mode 100644 index 5e642a52..00000000 --- a/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.kevinschildhorn.atomik.color.base - -import androidx.compose.ui.graphics.Color - -/* - * Android implementation of [AtomikColor] - * - * @property viewColor the AtomikColor as an android graphics Color [android.graphics.Color] - * (https://developer.android.com/reference/android/graphics/Color#parseColor(java.lang.String)) - * Format is either #RRGGBB or #AARRGGBB - * @property composeColor the AtomikColor as a compose Color [androidx.compose.ui.graphics.Color] - * hex code for color (#AARRGGBB) (alpha optional) - * @property hexString The hex value of the color (#AARRGGBB) - * @property r The red Value (0-255) - * @property g The red Value (0-255) - * @property b The red Value (0-255) - * @property a The alpha Value (0-1) (Defaults to 1) - */ -public actual class AtomikColor { - public actual val hexString: String - public actual val r: Int - public actual val g: Int - public actual val b: Int - public actual val a: Float - - /* - * hex code for color (#AARRGGBB) (alpha optional) - */ - private val androidHexColor: String - public val viewColor: Int - get() = android.graphics.Color.parseColor(androidHexColor) - - public actual constructor(hex: Long) { - val data = AtomikColorData(hex) - this.hexString = data.hexString - this.androidHexColor = data.hexStringAlphaFirst - this.r = data.r - this.g = data.g - this.b = data.b - this.a = data.a - } - - public actual constructor(r: Int, g: Int, b: Int, a: Float?) { - val data = AtomikColorData(r, g, b, a) - this.hexString = data.hexString - this.androidHexColor = data.hexStringAlphaFirst - this.r = data.r - this.g = data.g - this.b = data.b - this.a = data.a - } -} diff --git a/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/typography/AtomikTypographyExtensions.kt b/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/typography/AtomikTypographyExtensions.kt deleted file mode 100644 index ebaad42f..00000000 --- a/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/typography/AtomikTypographyExtensions.kt +++ /dev/null @@ -1,26 +0,0 @@ -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.typography - -import android.graphics.Typeface -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.unit.sp -import com.kevinschildhorn.atomik.typography.base.AtomikTypography -import com.kevinschildhorn.atomik.typography.base.AtomikTypographyWeight - -public fun AtomikTypography.asComposeTextStyle(fontFamily: FontFamily): TextStyle = - TextStyle( - fontFamily = fontFamily, - fontWeight = this.weight.fontWeight, - fontSize = this.size.sp, - ) - -/* - * Converting the Weight to a Typeface - */ -public val AtomikTypography.typeFace: Typeface - get() = when (this.weight) { - AtomikTypographyWeight.BOLD -> Typeface.DEFAULT_BOLD - else -> Typeface.DEFAULT - } diff --git a/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/typography/PlatformTypographySet.kt b/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/typography/PlatformTypographySet.kt deleted file mode 100644 index beb37ad2..00000000 --- a/atomik/src/androidMain/kotlin/com/kevinschildhorn/atomik/typography/PlatformTypographySet.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.kevinschildhorn.atomik.typography - -/* -actual class PlatformTypographySet// actual constructor(typographySet: DefaultTypographySet) : TypographySet { - - val h1: AtomikTypography = typographySet.h1 ?: typographySet.fallbackTypography - val h2: AtomikTypography = typographySet.h2 ?: typographySet.fallbackTypography - val h3: AtomikTypography = typographySet.h3 ?: typographySet.fallbackTypography - val h4: AtomikTypography = typographySet.h4 ?: typographySet.fallbackTypography - val h5: AtomikTypography = typographySet.h5 ?: typographySet.fallbackTypography - val h6: AtomikTypography = h5 - val subtitle1: AtomikTypography = typographySet.subtitle ?: typographySet.fallbackTypography - val subtitle2: AtomikTypography = typographySet.subtitle ?: typographySet.fallbackTypography - val body: AtomikTypography = typographySet.body - val body2: AtomikTypography = body - val button: AtomikTypography = typographySet.button ?: typographySet.fallbackTypography - val caption: AtomikTypography = typographySet.caption ?: typographySet.fallbackTypography - val overline: AtomikTypography = typographySet.footnote ?: typographySet.fallbackTypography - - fun asComposeTypography(fontFamily: FontFamily) = androidx.compose.material.Typography( - h1 = h1.asComposeTextStyle(fontFamily), - h2 = h2.asComposeTextStyle(fontFamily), - h3 = h3.asComposeTextStyle(fontFamily), - h4 = h4.asComposeTextStyle(fontFamily), - h5 = h5.asComposeTextStyle(fontFamily), - h6 = h6.asComposeTextStyle(fontFamily), - subtitle1 = subtitle1.asComposeTextStyle(fontFamily), - subtitle2 = subtitle2.asComposeTextStyle(fontFamily), - body1 = body.asComposeTextStyle(fontFamily), - body2 = body2.asComposeTextStyle(fontFamily), - button = button.asComposeTextStyle(fontFamily), - caption = caption.asComposeTextStyle(fontFamily), - overline = overline.asComposeTextStyle(fontFamily), - ) - - override val fallbackTypography: AtomikTypography = typographySet.fallbackTypography - - override fun getTypography(type: AtomikTypographyType): AtomikTypography = fallbackTypography - when (type) { - AtomikTypographyType.H1 -> h1 - AtomikTypographyType.H2 -> h2 - AtomikTypographyType.H3 -> h3 - AtomikTypographyType.H4 -> h4 - AtomikTypographyType.H5 -> h5 - AtomikTypographyType.H6 -> h6 - AtomikTypographyType.Subtitle -> subtitle1 - AtomikTypographyType.Subtitle2 -> subtitle2 - AtomikTypographyType.Body -> body - AtomikTypographyType.Body2 -> body2 - AtomikTypographyType.Button -> button - AtomikTypographyType.Caption -> caption - AtomikTypographyType.Overline -> overline - else -> fallbackTypography - } -}*/ diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/DesignSystem.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/DesignSystem.kt deleted file mode 100644 index 3ea3e6c4..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/DesignSystem.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.kevinschildhorn.atomik - -import com.kevinschildhorn.atomik.atomic.atoms.Atom -import com.kevinschildhorn.atomik.color.CustomColorSet -import com.kevinschildhorn.atomik.color.base.ColorSet -import com.kevinschildhorn.atomik.typography.CustomTypographySet -import com.kevinschildhorn.atomik.typography.base.AtomikFontFamily -import com.kevinschildhorn.atomik.typography.base.TypographySet - -/** - * A Design System - * - * This is the core of the Atomik Library, representing a Design Systems components. - * This is based on atomic design which is included in the Design System - * - * @property colorSet the collection of colors to be used in this Design System - * @property typographySet the collection of typohraphies to be used in this Design System - * @property components the atomic components to be used in this Design System - * @property fontFamily the font family passed into the Design System from the Platform level - */ -@ExperimentalAtomik -public open class DesignSystem( - public open val colorSet: ColorSet, - public open val typographySet: TypographySet, - public open val components: Map, - public open var fontFamily: AtomikFontFamily? = null, -) -/* -@OptIn(ExperimentalAtomik::class) -public class PlatformDesignSystem( - override val colorSet: DefaultColorSet, - override val typographySet: PlatformTypographySet, - override val components: Map, - override var fontFamily: AtomikFontFamily?, -) : DesignSystem(colorSet, typographySet, components, fontFamily) - -@OptIn(ExperimentalAtomik::class) -class DefaultDesignSystem( - override val colorSet: DefaultColorSet, - override val typographySet: DefaultTypographySet, - override val components: Map, - override var fontFamily: AtomikFontFamily?, -) : DesignSystem(colorSet, typographySet, components, fontFamily) -*/ - -/** - * A Custom implementation of a Design System - * - * This inherits the [DesignSystem], and uses Custom implementations of the properties - * This is based on atomic design which is included in the Design System - * - * @property colorSet the custom collection of colors to be used in this Design System - * @property typographySet the custom collection of typohraphies to be used in this Design System - * @property components the atomic components to be used in this Design System - * @property fontFamily the font family passed into the Design System from the Platform level - */ -@OptIn(ExperimentalAtomik::class) -internal class CustomDesignSystem( - override val colorSet: CustomColorSet, - override val typographySet: CustomTypographySet, - override val components: Map, - override var fontFamily: AtomikFontFamily?, -) : DesignSystem(colorSet, typographySet, components, fontFamily) diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/ExperimentalAtomik.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/ExperimentalAtomik.kt deleted file mode 100644 index 784fd8bd..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/ExperimentalAtomik.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.kevinschildhorn.atomik - -@RequiresOptIn(message = "This API Is Experimental") -@Retention(AnnotationRetention.BINARY) -@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) -public annotation class ExperimentalAtomik diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/Atom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/Atom.kt deleted file mode 100644 index 17b517e8..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/Atom.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms - -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.AtomInterface -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.AtomType - -/** - * Represents an Atom from Atomic Design, as a class - * https://atomicdesign.bradfrost.com/ - * - * An abstract class that represents an Atom. While interfaces are used to specify what Atoms conform to, - * the [Atom] class provides the UI details. In Atomic Design, components contain subcomponents - * that are related to the parent component. For example Organisms contain Molecules, which contain Atoms. - * - * @property type the Type of atom being displayed, such as button or text - * @property subComponents the components related to this atom, as mentioned in description - */ -public abstract class Atom { - public abstract val type: AtomType - public open val subComponents: List = emptyList() - - /** - * Checks to see if the Atom has any subcomponents. Returns boolean - */ - public val hasSubComponents: Boolean - get() = subComponents.isNotEmpty() - - /** - * Checks to see if this Atom implements a certain [AtomInterface] and if it does returns the interface - * @return the atom as the interface - */ - @Suppress("UNCHECKED_CAST") - public fun asAtom(): T? = (this as? T) - - /** - * Finds a subComponent matching a specified [AtomInterface] if it exists - * @return the subComponent of a specified interface if it's found - */ - public inline fun subAtom(): T? = subComponents.find { it is T } as? T -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/FigmaAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/FigmaAtom.kt deleted file mode 100644 index 04050e7f..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/FigmaAtom.kt +++ /dev/null @@ -1,115 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms - -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.AtomType -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.AtomikConstraintX -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.AtomikConstraintY -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.ColorAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.ConstrainedAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.FixedSizeAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.PaddingAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.TextAtom -import com.kevinschildhorn.atomik.color.base.AtomikColor -import com.kevinschildhorn.atomik.typography.base.AtomikFontFamily -import com.kevinschildhorn.atomik.typography.base.AtomikTypography - -/** - * Represents an Atom with all of the properties found in a Figma atom - * - * This atom contains the components that are configurable in a Figma file. These are the base components, - * as in Figma you can create shape and text components. There are child classes for those components. - * - * @property type the Type of atom being displayed, such as button or text - * @property width the width of the UI (in dp / pt) - * @property height the height of the UI (in dp / pt) - * @property constraintX the constraint in the X Axis (horizontal) - * @property constraintY the constraint in the Y Axis (vertical) - */ -public open class FigmaBaseAtom( - override val type: AtomType, - override val width: Int?, - override val height: Int?, - override val constraintX: AtomikConstraintX, - override val constraintY: AtomikConstraintY, -) : Atom(), FixedSizeAtom, ConstrainedAtom - -/** - * Represents an Atom with all of the properties found in a Figma Shape atom - * - * This atom contains the components that are configurable in a Figma file, for a component that has a shape. - * - * @property type the Type of atom being displayed, such as button or text - * @property subComponents the components related to this atom, as mentioned in description - * @property width the width of the UI (in dp / pt) - * @property height the height of the UI (in dp / pt) - * @property constraintX the constraint in the X Axis (horizontal) - * @property constraintY the constraint in the Y Axis (vertical) - * @property color the color of the UI. - * @property padding the horizontal padding of the atom (in dp/pt) - * @property paddingHorizontal the horizontal padding of the atom (in dp/pt) - * @property paddingVertical the vertical padding of the atom (in dp/pt) - * @property paddingLeft the padding on the left of the atom (in dp/pt) - * @property paddingRight the padding on the right of the atom (in dp/pt) - * @property paddingTop the padding on the top of the atom (in dp/pt) - * @property paddingBottom the padding on the bottom of the atom (in dp/pt) - */ -public class FigmaShapeAtom( - override val type: AtomType = AtomType.VIEW, - override val subComponents: List = emptyList(), - override val width: Int? = null, - override val height: Int? = null, - override val constraintX: AtomikConstraintX, - override val constraintY: AtomikConstraintY, - // [ColorAtom] - override val color: AtomikColor, - // [PaddingAtom] - override val padding: Int? = null, - override val paddingHorizontal: Int? = padding, - override val paddingVertical: Int? = padding, - override val paddingLeft: Int? = paddingHorizontal, - override val paddingRight: Int? = paddingHorizontal, - override val paddingTop: Int? = paddingVertical, - override val paddingBottom: Int? = paddingVertical, -) : FigmaBaseAtom(type, width, height, constraintX, constraintY), ColorAtom, PaddingAtom - -/** - * Represents an Atom with all of the properties found in a Figma Text atom - * - * This atom contains the components that are configurable in a Figma file, for a component that has text. - * - * @property type the Type of atom being displayed, such as button or text - * @property subComponents the components related to this atom, as mentioned in description - * @property width the width of the UI (in dp / pt) - * @property height the height of the UI (in dp / pt) - * @property constraintX the constraint in the X Axis (horizontal) - * @property constraintY the constraint in the Y Axis (vertical) - * @property textColor the color of the text - * @property typography the typography associated with the text - * @property fontFamily the fontFamily associated with the text - * @property padding the horizontal padding of the atom (in dp/pt) - * @property paddingHorizontal the horizontal padding of the atom (in dp/pt) - * @property paddingVertical the vertical padding of the atom (in dp/pt) - * @property paddingLeft the padding on the left of the atom (in dp/pt) - * @property paddingRight the padding on the right of the atom (in dp/pt) - * @property paddingTop the padding on the top of the atom (in dp/pt) - * @property paddingBottom the padding on the bottom of the atom (in dp/pt) - */ -public class FigmaTextAtom( - override val type: AtomType = AtomType.TEXT, - override val subComponents: List = emptyList(), - override val width: Int? = null, - override val height: Int? = null, - override val constraintX: AtomikConstraintX, - override val constraintY: AtomikConstraintY, - // TextAtom - override val textColor: AtomikColor, - override val typography: AtomikTypography, - override val fontFamily: AtomikFontFamily? = null, - // PaddingAtom - override val padding: Int? = null, - override val paddingHorizontal: Int? = padding, - override val paddingVertical: Int? = padding, - override val paddingLeft: Int? = paddingHorizontal, - override val paddingRight: Int? = paddingHorizontal, - override val paddingTop: Int? = paddingVertical, - override val paddingBottom: Int? = paddingVertical, -) : FigmaBaseAtom(type, width, height, constraintX, constraintY), TextAtom, PaddingAtom diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/ImageAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/ImageAtom.kt deleted file mode 100644 index f61d8c89..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/ImageAtom.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms - -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.AtomType -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.ResourceAtom -import com.kevinschildhorn.atomik.color.base.AtomikColor - -public class ImageAtom( - public val color: AtomikColor, - override val image: T, -) : Atom(), ResourceAtom { - override val type: AtomType = AtomType.IMAGE -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/TextViewAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/TextViewAtom.kt deleted file mode 100644 index eb7dde12..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/TextViewAtom.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms - -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.AtomType -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.PaddingAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.TextAtom -import com.kevinschildhorn.atomik.color.base.AtomikColor -import com.kevinschildhorn.atomik.typography.base.AtomikFontFamily -import com.kevinschildhorn.atomik.typography.base.AtomikTypography - -public class TextViewAtom( - override val textColor: AtomikColor, - override val typography: AtomikTypography, - override val fontFamily: AtomikFontFamily? = null, - public val backgroundColor: AtomikColor? = null, - override val paddingHorizontal: Int? = null, - override val paddingVertical: Int? = null, - override val padding: Int? = null, - override val paddingLeft: Int? = null, - override val paddingRight: Int? = null, - override val paddingTop: Int? = null, - override val paddingBottom: Int? = null, -) : Atom(), TextAtom, PaddingAtom { - override val type: AtomType - get() = AtomType.TEXT -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+AtomikColorType.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+AtomikColorType.kt deleted file mode 100644 index beee947a..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+AtomikColorType.kt +++ /dev/null @@ -1,14 +0,0 @@ -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.atomic.atoms.compose -/* -import androidx.compose.ui.graphics.Color -import com.kevinschildhorn.atomik.color.base.AtomikColorType - -/** - * gets a composable [Color] from the [AtomikColorType] - * - */ -internal val AtomikColorType.composeColor: Color - get() = color.composeColor -*/ diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+ConstrainedAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+ConstrainedAtom.kt deleted file mode 100644 index 60b794cc..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+ConstrainedAtom.kt +++ /dev/null @@ -1,57 +0,0 @@ -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.atomic.atoms - -import androidx.compose.ui.Alignment -import androidx.compose.ui.BiasAlignment -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.AtomikConstraintX -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.AtomikConstraintY -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.ConstrainedAtom - -/** - * The Vertical compose Alignment, based on the [ConstrainedAtom] - */ -public val ConstrainedAtom.alignmentVertical: Alignment.Vertical - get() = - when (this.constraintY) { - AtomikConstraintY.ALIGN_TOP -> Alignment.Top - AtomikConstraintY.ALIGN_BOTTOM -> Alignment.Bottom - AtomikConstraintY.CENTER -> Alignment.CenterVertically - AtomikConstraintY.SCALE -> Alignment.CenterVertically - } - -/** - * The Horizontal compose Alignment, based on the [ConstrainedAtom] - */ -public val ConstrainedAtom.alignmentHorizontal: Alignment.Horizontal - get() = - when (this.constraintX) { - AtomikConstraintX.ALIGN_LEFT -> Alignment.Start - AtomikConstraintX.ALIGN_RIGHT -> Alignment.End - AtomikConstraintX.CENTER -> Alignment.CenterHorizontally - AtomikConstraintX.SCALE -> Alignment.CenterHorizontally - } - -/** - * The compose Alignment, based on the [ConstrainedAtom]. Combines both vertical and horizontal - */ -public val ConstrainedAtom.alignment: Alignment - get() = BiasAlignment(horizontalBias, verticalBias) - -private val ConstrainedAtom.verticalBias: Float - get() = - when (this.constraintY) { - AtomikConstraintY.ALIGN_TOP -> -1f - AtomikConstraintY.ALIGN_BOTTOM -> 1f - AtomikConstraintY.CENTER -> 0f - AtomikConstraintY.SCALE -> 0f - } - -private val ConstrainedAtom.horizontalBias: Float - get() = - when (this.constraintX) { - AtomikConstraintX.ALIGN_LEFT -> -1f - AtomikConstraintX.ALIGN_RIGHT -> 1f - AtomikConstraintX.CENTER -> 0f - AtomikConstraintX.SCALE -> 0f - } diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+EnablableAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+EnablableAtom.kt deleted file mode 100644 index 3a7e1013..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+EnablableAtom.kt +++ /dev/null @@ -1,13 +0,0 @@ -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.atomic.atoms.compose - -/* -@Composable -fun EnablableAtom.buttonColors(): ButtonColors = - ButtonDefaults.buttonColors( - backgroundColor = color.color.platformColor, - disabledBackgroundColor = disabledColor?.color?.platformColor ?: color.color.platformColor - ) - - */ diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+FixedSizeAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+FixedSizeAtom.kt deleted file mode 100644 index 1fdf5825..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+FixedSizeAtom.kt +++ /dev/null @@ -1,14 +0,0 @@ -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.atomic.atoms -/* -import androidx.compose.foundation.layout.height -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.FixedSizeAtom - -val FixedSizeAtom.heightModifier: Modifier - get() = height?.let { - Modifier.height(it.dp) - } ?: Modifier -*/ diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+RoundedAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+RoundedAtom.kt deleted file mode 100644 index b7cb7ba7..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+RoundedAtom.kt +++ /dev/null @@ -1,11 +0,0 @@ -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.atomic.atoms - -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.RoundedAtom - -public val RoundedAtom.shape: Shape - get() = RoundedCornerShape(radius.dp) diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+TextAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+TextAtom.kt deleted file mode 100644 index a3b655c4..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/compose/+TextAtom.kt +++ /dev/null @@ -1,43 +0,0 @@ -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.atomic.atoms.compose - -import androidx.compose.runtime.Composable -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.unit.sp -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.TextAtom -import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.atomik.typography.fontWeight -import dev.icerock.moko.resources.compose.fontFamilyResource - -/** - * Creates a compose [TextStyle] from the [TextAtom] - * - * Uses the default FontFamily from the atom - * @return returns a compose [TextStyle] - */ -public val TextAtom.textStyle: TextStyle - @Composable - get() { - return TextStyle( - fontFamily = fontFamilyResource(this.typography.font), - fontWeight = this.typography.weight.fontWeight, - fontSize = this.typography.size.sp, - color = this.textColor.composeColor, - ) - } - -/** - * Creates a compose [TextStyle] from the [TextAtom] - * - * @param fontFamily the [FontFamily] that can be passed in from the platform code - * @return returns a compose [TextStyle] - */ -public fun TextAtom.textStyle(fontFamily: FontFamily): TextStyle = - TextStyle( - fontFamily = fontFamily, - fontWeight = this.typography.weight.fontWeight, - fontSize = this.typography.size.sp, - color = this.textColor.composeColor, - ) diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/AtomInterface.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/AtomInterface.kt deleted file mode 100644 index 8cce5251..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/AtomInterface.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms.interfaces - -/** - * Represents an Atom from Atomic Design, as an interface - * https://atomicdesign.bradfrost.com/ - * - * A common interface that represents an Atom. These interfaces are used to specify what the - * Atoms must contain, and can be used to get specific information about an atom. - * This is the basis of Atomik. Other Atoms inherit from this interface to add UI details to the - * Atom, such as [ColorAtom] or [TextAtom]. Then a UI representation such as a [ButtonAtom] - * implements these interfaces and provides the details to correctly display the UI. - */ -public interface AtomInterface diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/AtomType.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/AtomType.kt deleted file mode 100644 index 31875a41..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/AtomType.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms.interfaces - -import com.kevinschildhorn.atomik.ExperimentalAtomik - -/** - * The type of UI Element an atom is. - * https://atomicdesign.bradfrost.com/ - * - * This is used to determine what kind of UI to display based on the value - */ -@OptIn(ExperimentalAtomik::class) -public enum class AtomType { - BUTTON, - TEXT, - IMAGE, - TEXTFIELD, - VIEW, -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/BorderedAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/BorderedAtom.kt deleted file mode 100644 index 63ee44cc..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/BorderedAtom.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms.interfaces - -import com.kevinschildhorn.atomik.ExperimentalAtomik -import com.kevinschildhorn.atomik.atomic.atoms.Atom -import com.kevinschildhorn.atomik.color.base.AtomikColor - -/** - * An atom that contains information about a border UI - * - * @property borderColor the color of the border surrounding the UI - */ -@OptIn(ExperimentalAtomik::class) -internal interface BorderedAtom : AtomInterface { - public val focusedBorderColor: AtomikColor - public val unFocusedBorderColor: AtomikColor -} - -/** - * Convenience function to get the atom as a bordered atom - */ -internal val Atom.borderedAtom: BorderedAtom? - get() = this.asAtom() diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/ColorAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/ColorAtom.kt deleted file mode 100644 index 1b877fa5..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/ColorAtom.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms.interfaces - -import com.kevinschildhorn.atomik.atomic.atoms.Atom -import com.kevinschildhorn.atomik.color.base.AtomikColor - -/** - * An atom that contains information about the color of the UI - * - * @property color the color of the UI. - */ -public interface ColorAtom : AtomInterface { - public val color: AtomikColor -} - -/** - * Convenience function to get the atom as a color atom - */ -internal val Atom.colorAtom: ColorAtom? - get() = this.asAtom() - -/** - * Convenience class to only get the Color Atom - */ -public class SimpleColorAtom(override val color: AtomikColor) : Atom(), ColorAtom { - override val type: AtomType = AtomType.VIEW -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/ConstrainedAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/ConstrainedAtom.kt deleted file mode 100644 index a1621bc0..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/ConstrainedAtom.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms.interfaces - -import com.kevinschildhorn.atomik.atomic.atoms.Atom - -/** - * An atom that contains information about the constraints of the UI(i.e. alignment) - * - * @property constraintX the constraint in the X Axis (horizontal) - * @property constraintY the constraint in the Y Axis (vertical) - */ -public interface ConstrainedAtom : AtomInterface { - public val constraintX: AtomikConstraintX - public val constraintY: AtomikConstraintY -} - -/** - * An enum that represents the horizontal constraint of the Atom - */ -public enum class AtomikConstraintX { - CENTER, - ALIGN_LEFT, - ALIGN_RIGHT, - SCALE, -} - -/** - * An enum that represents the vertical constraint of the Atom - */ -public enum class AtomikConstraintY { - CENTER, - ALIGN_TOP, - ALIGN_BOTTOM, - SCALE, -} - -/** - * Convenience function to get the atom as a constrained atom - */ -internal val Atom.constrainedAtom: ConstrainedAtom? - get() = this.asAtom() diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/EnablableAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/EnablableAtom.kt deleted file mode 100644 index e4a38baf..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/EnablableAtom.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms.interfaces - -import com.kevinschildhorn.atomik.atomic.atoms.Atom -import com.kevinschildhorn.atomik.color.base.AtomikColor - -/** - * An atom that can be enabled / disabled. Contains the disabled color of the UI and inherits [ColorAtom] - * - * @property disabledColor the disabled color of the UI. - */ -internal interface EnablableAtom : ColorAtom { - public val disabledColor: AtomikColor? -} - -/** - * Convenience function to get the atom as an enabled atom - */ -internal val Atom.enablableAtom: EnablableAtom? - get() = this.asAtom() diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/FixedSizeAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/FixedSizeAtom.kt deleted file mode 100644 index 08769bbf..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/FixedSizeAtom.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms.interfaces - -import com.kevinschildhorn.atomik.atomic.atoms.Atom - -/** - * An atom that has a fixed size, rather than a scalable size, such as a [ConstrainedAtom] - * - * @property width the width of the UI (in dp / pt) - * @property height the height of the UI (in dp / pt) - */ -internal interface FixedSizeAtom : AtomInterface { - public val width: Int? - public val height: Int? -} - -/** - * Convenience function to get the atom as a fixed size atom - */ -internal val Atom.fixedSizeAtom: FixedSizeAtom? - get() = this.asAtom() diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/PaddingAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/PaddingAtom.kt deleted file mode 100644 index 19e6f353..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/PaddingAtom.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms.interfaces - -import com.kevinschildhorn.atomik.atomic.atoms.Atom - -/** - * An atom that can has padding surrounding it. - * - * This atom can take either specific padding(i.e. left, right, top, bottom), - * or more generalized padding (vertical, horizontal, overall) - * - * Padding that is not set defaults back to a more generalized padding - * For example: paddingBottom -> paddingVertical -> padding - * - * @property padding the horizontal padding of the atom (in dp/pt) - * @property paddingHorizontal the horizontal padding of the atom (in dp/pt) - * @property paddingVertical the vertical padding of the atom (in dp/pt) - * @property paddingLeft the padding on the left of the atom (in dp/pt) - * @property paddingRight the padding on the right of the atom (in dp/pt) - * @property paddingTop the padding on the top of the atom (in dp/pt) - * @property paddingBottom the padding on the bottom of the atom (in dp/pt) - */ -internal interface PaddingAtom : AtomInterface { - public val padding: Int? - public val paddingHorizontal: Int? - public val paddingVertical: Int? - public val paddingLeft: Int? - public val paddingRight: Int? - public val paddingTop: Int? - public val paddingBottom: Int? -} - -/** - * Convenience function to get the atom as a padding atom - */ -internal val Atom.paddingAtom: PaddingAtom? - get() = this.asAtom() diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/ResourceAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/ResourceAtom.kt deleted file mode 100644 index 35763550..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/ResourceAtom.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms.interfaces - -/** - * An atom that has an image resource associated with it - * - * @property image the image associated with the atom - */ -internal interface ResourceAtom : AtomInterface { - public val image: T -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/RoundedAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/RoundedAtom.kt deleted file mode 100644 index f1eb81f9..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/RoundedAtom.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms.interfaces - -import com.kevinschildhorn.atomik.atomic.atoms.Atom - -/** - * An atom that has rounded edges - * - * @property radius the radius of the rounded edges (in dp / pt) - */ -public interface RoundedAtom : AtomInterface { - public val radius: Int -} - -/** - * Convenience function to get the atom as a rounded atom - */ -internal val Atom.roundedAtom: RoundedAtom? - get() = this.asAtom() diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/TextAtom.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/TextAtom.kt deleted file mode 100644 index 77d603c1..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/interfaces/TextAtom.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.atoms.interfaces - -import com.kevinschildhorn.atomik.atomic.atoms.Atom -import com.kevinschildhorn.atomik.color.base.AtomikColor -import com.kevinschildhorn.atomik.typography.base.AtomikFontFamily -import com.kevinschildhorn.atomik.typography.base.AtomikTypography - -/** - * An atom that has text - * - * @property textColor the color of the text - * @property typography the typography associated with the text - * @property fontFamily the fontFamily associated with the text - */ -public interface TextAtom : AtomInterface { - public val textColor: AtomikColor - public val typography: AtomikTypography - public val fontFamily: AtomikFontFamily? -} - -/** - * Convenience function to get the atom as a text atom - */ -public val Atom.textAtom: TextAtom? - get() = this.asAtom() - -/** - * Convenience class to only get the Text Atom - */ -public class SimpleTextAtom( - override val textColor: AtomikColor, - override val typography: AtomikTypography, - override val fontFamily: AtomikFontFamily?, -) : Atom(), TextAtom { - override val type: AtomType = AtomType.TEXT -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/BaseMolecule.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/BaseMolecule.kt deleted file mode 100644 index e1af1b2c..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/BaseMolecule.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.molecules - -import com.kevinschildhorn.atomik.atomic.atoms.Atom - -/** - * Represents a Molecule from Atomic Design, as an interface - * https://atomicdesign.bradfrost.com/ - * - * An abstract class that represents a molecule. A molecule consists of multiple atoms to create a - * robust UI element. This Base molecule contains an array of atoms used, and can be inherited for - * more specific functionality. - */ -public abstract class BaseMolecule { - public abstract val atoms: List -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/OutlinedTextFieldMolecule.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/OutlinedTextFieldMolecule.kt deleted file mode 100644 index e31ae0fe..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/OutlinedTextFieldMolecule.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.molecules - -import androidx.compose.material.ContentAlpha -import androidx.compose.material.TextFieldColors -import androidx.compose.material.TextFieldDefaults -import androidx.compose.runtime.Composable -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.BorderedAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.ColorAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.RoundedAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.TextAtom -import com.kevinschildhorn.atomik.color.base.AtomikColor -import com.kevinschildhorn.atomik.color.base.composeColor - -/** - * A molecule that contains information about a TextField - * - * @property textAtom the [TextAtom] used for the entered Text - * @property hintTextAtom the [TextAtom] used for the hint Text when the field is empty - * @property errorTextAtom the [TextAtom] used for the error Text when the field has an error - * @property disabledColorAtom the [ColorAtom] of the text if the ui is disabled - * @property backgroundColorAtom the [ColorAtom] of the background - * @property cursorColor the [AtomikColor] of the cursor - * @property errorColor the [AtomikColor] of the error, used for all error elements in the View - * @property borderColor the [AtomikColor] of the border - */ -public open class OutlinedTextFieldMolecule( - textAtom: TextAtom, - backgroundColorAtom: ColorAtom, - hintTextAtom: TextAtom? = null, - errorTextAtom: TextAtom? = null, - disabledColorAtom: ColorAtom? = null, - cursorColor: AtomikColor? = null, - errorColor: AtomikColor? = errorTextAtom?.textColor, - override val focusedBorderColor: AtomikColor, - override val unFocusedBorderColor: AtomikColor = focusedBorderColor, - override val radius: Int, -) : TextFieldMolecule( - textAtom, - backgroundColorAtom, - hintTextAtom, - errorTextAtom, - disabledColorAtom, - cursorColor, - errorColor, - ), - BorderedAtom, - RoundedAtom { - @Composable - public override fun colors(): TextFieldColors { - val textColor = textAtom.textColor.composeColor - val backgroundColor = backgroundColorAtom.color.composeColor - val disabledBackgroundColor = backgroundColor.copy(alpha = ContentAlpha.disabled) - val errorTextColor = textAtom.textColor.composeColor - - return TextFieldDefaults.outlinedTextFieldColors( - textColor = textColor, - backgroundColor = backgroundColor, - placeholderColor = - hintTextAtom?.textColor?.composeColor ?: backgroundColor.copy( - ContentAlpha.medium, - ), - cursorColor = cursorColor?.composeColor ?: textColor, - focusedBorderColor = focusedBorderColor.composeColor, - unfocusedBorderColor = unFocusedBorderColor.composeColor, - disabledTextColor = - disabledColorAtom?.color?.composeColor - ?: textColor.copy(ContentAlpha.disabled), - disabledBorderColor = disabledColorAtom?.color?.composeColor ?: disabledBackgroundColor, - disabledLabelColor = disabledColorAtom?.color?.composeColor ?: disabledBackgroundColor, - disabledLeadingIconColor = - disabledColorAtom?.color?.composeColor - ?: disabledBackgroundColor, - disabledPlaceholderColor = - disabledColorAtom?.color?.composeColor - ?: disabledBackgroundColor, - disabledTrailingIconColor = - disabledColorAtom?.color?.composeColor - ?: disabledBackgroundColor, - errorCursorColor = errorColor?.composeColor ?: errorTextColor, - errorBorderColor = errorColor?.composeColor ?: errorTextColor, - errorLabelColor = errorColor?.composeColor ?: errorTextColor, - errorLeadingIconColor = errorColor?.composeColor ?: errorTextColor, - errorTrailingIconColor = errorColor?.composeColor ?: errorTextColor, - ) - } -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/TextButtonMolecule.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/TextButtonMolecule.kt deleted file mode 100644 index e102eb81..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/TextButtonMolecule.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.molecules - -import com.kevinschildhorn.atomik.atomic.atoms.Atom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.EnablableAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.RoundedAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.TextAtom -import com.kevinschildhorn.atomik.color.base.AtomikColor - -public class TextButtonMolecule( - override val color: AtomikColor, - override val disabledColor: AtomikColor, - override val radius: Int, - public val textAtom: TextAtom, -) : BaseMolecule(), EnablableAtom, RoundedAtom { - override val atoms: List = listOf(textAtom as Atom) -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/TextFieldMolecule.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/TextFieldMolecule.kt deleted file mode 100644 index b503224a..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/molecules/TextFieldMolecule.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.molecules - -import androidx.compose.material.ContentAlpha -import androidx.compose.material.TextFieldColors -import androidx.compose.material.TextFieldDefaults -import androidx.compose.runtime.Composable -import com.kevinschildhorn.atomik.atomic.atoms.Atom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.ColorAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.TextAtom -import com.kevinschildhorn.atomik.color.base.AtomikColor -import com.kevinschildhorn.atomik.color.base.composeColor - -/** - * A molecule that contains information about a TextField - * - * @property textAtom the [TextAtom] used for the entered Text - * @property hintTextAtom the [TextAtom] used for the hint Text when the field is empty - * @property errorTextAtom the [TextAtom] used for the error Text when the field has an error - * @property disabledColorAtom the [ColorAtom] of the text if the ui is disabled - * @property backgroundColorAtom the [ColorAtom] of the background - * @property cursorColor the [AtomikColor] of the cursor - * @property errorColor the [AtomikColor] of the error, used for all error elements in the View - */ -public open class TextFieldMolecule( - public val textAtom: TextAtom, - public val backgroundColorAtom: ColorAtom, - public val hintTextAtom: TextAtom? = null, - public val errorTextAtom: TextAtom? = null, - public val disabledColorAtom: ColorAtom? = null, - public val cursorColor: AtomikColor? = null, - public val errorColor: AtomikColor? = errorTextAtom?.textColor, -) : BaseMolecule() { - override val atoms: List - get() = listOf() - - @Composable - public open fun colors(): TextFieldColors { - val textColor = textAtom.textColor.composeColor - val backgroundColor = backgroundColorAtom.color.composeColor - val disabledBackgroundColor = backgroundColor.copy(alpha = ContentAlpha.disabled) - val errorTextColor = textAtom.textColor.composeColor - - return TextFieldDefaults.textFieldColors( - textColor = textColor, - backgroundColor = backgroundColor, - placeholderColor = - hintTextAtom?.textColor?.composeColor ?: backgroundColor.copy( - ContentAlpha.medium, - ), - cursorColor = cursorColor?.composeColor ?: textColor, - disabledTextColor = - disabledColorAtom?.color?.composeColor - ?: textColor.copy(ContentAlpha.disabled), - disabledIndicatorColor = - disabledColorAtom?.color?.composeColor - ?: disabledBackgroundColor, - disabledLabelColor = disabledColorAtom?.color?.composeColor ?: disabledBackgroundColor, - disabledLeadingIconColor = - disabledColorAtom?.color?.composeColor - ?: disabledBackgroundColor, - disabledPlaceholderColor = - disabledColorAtom?.color?.composeColor - ?: disabledBackgroundColor, - disabledTrailingIconColor = - disabledColorAtom?.color?.composeColor - ?: disabledBackgroundColor, - errorCursorColor = errorColor?.composeColor ?: errorTextColor, - errorIndicatorColor = errorColor?.composeColor ?: errorTextColor, - errorLabelColor = errorColor?.composeColor ?: errorTextColor, - errorLeadingIconColor = errorColor?.composeColor ?: errorTextColor, - errorTrailingIconColor = errorColor?.composeColor ?: errorTextColor, - ) - } -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/organisms/BaseOrganism.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/organisms/BaseOrganism.kt deleted file mode 100644 index 29ea8d08..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/organisms/BaseOrganism.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.organisms - -import com.kevinschildhorn.atomik.atomic.molecules.BaseMolecule - -public abstract class BaseOrganism { - public abstract val molecules: List -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/organisms/FormOrganism.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/organisms/FormOrganism.kt deleted file mode 100644 index 611b7fce..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/atomic/organisms/FormOrganism.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.kevinschildhorn.atomik.atomic.organisms - -import com.kevinschildhorn.atomik.atomic.molecules.BaseMolecule - -public class FormOrganism( - override val molecules: List, -) : BaseOrganism() diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/CustomColorSet.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/CustomColorSet.kt deleted file mode 100644 index 59c71aae..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/CustomColorSet.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.kevinschildhorn.atomik.color - -import com.kevinschildhorn.atomik.color.base.AtomikColor -import com.kevinschildhorn.atomik.color.base.ColorSet - -/** - * A custom set of colors to be used in the project - * - * Is an implementation of [ColorSet] that contains a map of [AtomikColor]. - * Allows for adding colors with custom ids. - * For now this acts as a wrapper to a collection of colors - * - * @property fallbackColor the color that is passed if the requested color cannot be found - * @property colors a map of colors that are contained in this set - */ -public class CustomColorSet( - override val fallbackColor: AtomikColor, - private val colors: Map, -) : ColorSet { - /** - * Gets the color based on a type. If none is found then the fallback is returned - * @param name The name of color you want to get as a [String] - * @return the [AtomikColor] based on the name passed - */ - override fun getColor(name: String): AtomikColor = colors[name] ?: fallbackColor -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/CustomColorSetTyped.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/CustomColorSetTyped.kt deleted file mode 100644 index 7db78e18..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/CustomColorSetTyped.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.kevinschildhorn.atomik.color - -import com.kevinschildhorn.atomik.color.base.AtomikColor -import com.kevinschildhorn.atomik.color.base.ColorSet - -/** - * A custom set of colors data to be used in the project - * - * Is an implementation of [ColorSet] that contains a map of [AtomikColor]. - * Allows for adding colors with custom ids, that can be referenced from a custom - * enum that is passed in. For now this acts as a wrapper to a collection of colors - * - * @property fallbackColor the color that is passed if the requested color cannot be found - * @property colors a map of colors that are contained in this set - */ -internal class CustomColorSetTyped>( - override val fallbackColor: AtomikColor, - private val colors: Map, -) : ColorSet { - /** - * Gets the color based on an enum value. If none is found then the fallback is returned - * @param type The enum associated with the typography you want to get as a [AtomikColor] - * @return the [AtomikColor] based on the type passed - */ - public fun getColor(type: E): AtomikColor = colors[type] ?: fallbackColor - - /** - * Gets the color based on a type. If none is found then the fallback is returned - * @param name The name of color you want to get as a [String] - * @return the [AtomikColor] based on the name passed - */ - override fun getColor(name: String): AtomikColor = fallbackColor // TODO -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt deleted file mode 100644 index 4bc1361c..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.kevinschildhorn.atomik.color.base - -import androidx.compose.ui.graphics.Color - -/** - * A common implementation of a Color - * - * This contains platform specific implementations in the actual versions. Can be created from - * either a hex Long or an RGBA value - * - * @property hexString The hex value of the color (#RRGGBBAA) - * @property r The red Value (0-255) - * @property g The red Value (0-255) - * @property b The red Value (0-255) - * @property a The alpha Value (0-1) (Defaults to 1) - */ -@Suppress("SpellCheckingInspection") -public expect class AtomikColor { - public val hexString: String - public val r: Int - public val g: Int - public val b: Int - public val a: Float - - /** - * Constructor with hex variable - * - * @constructor Creates a color based on the hex value(i.e. 0xFFFFFF) - * @param hex - The Hex Value of the color (#RRGGBBAA) - */ - public constructor(hex: Long) - - /** - * Constructor with r, g, b, a - * - * @constructor Creates a color based on the rgb values. Alpha defaults to 1. - * @param r - Red value (0-255) - * @param g - Green Value (0-255) - * @param b - Blue Value (0-255) - * @param a - Alpha value (0-1) (defaults to 1) - */ - public constructor(r: Int, g: Int, b: Int, a: Float? = null) -} - -public val AtomikColor.composeColor: Color - get() = - Color( - red = r.toFloat() / 255, - green = g.toFloat() / 255, - blue = b.toFloat() / 255, - alpha = this.a, - ) diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColorData.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColorData.kt deleted file mode 100644 index 29da7c78..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColorData.kt +++ /dev/null @@ -1,101 +0,0 @@ -package com.kevinschildhorn.atomik.color.base - -import kotlin.math.roundToInt - -/** - * A common collection of Color Data - * - * This is used to share logic to create [AtomikColor], while using platform specific - * implementations of [AtomikColor] - * - * @param hexString the hex value of the color as a string, with the alpha at the end (format: #RRGGBBAA) - * @param hexStringAlphaFirst the hex value of the color as a string, with the alpha at the beginning (format: #AARRGGBB) - * @param r The red Value (0-255) - * @param g The red Value (0-255) - * @param b The red Value (0-255) - * @param a The alpha Value (0-1) (Defaults to 1) - */ -@Suppress("SpellCheckingInspection") -internal data class AtomikColorData( - val hexString: String, - val hexStringAlphaFirst: String = hexString, - val r: Int, - val g: Int, - val b: Int, - val a: Float, -) { - /** - * @constructor constructor with hex value - * @param hex hex value - **/ - constructor(hex: Long) : this( - hexString = hex.asHexString, - hexStringAlphaFirst = hex.asHexString, - r = hex.red, - g = hex.green, - b = hex.blue, - a = hex.alpha, - ) - - /** - * @constructor constructor with rgba value - * @param r red value (0-255) - * @param g green value (0-255) - * @param b blue value (0-255) - * @param a alpha value (0-1) (Defaults to 1) - **/ - constructor(r: Int, g: Int, b: Int, a: Float? = null) : this( - hexString = hexFromRGB(r, g, b, a, false), - hexStringAlphaFirst = hexFromRGB(r, g, b, a, true), - r = r, - g = g, - b = b, - a = a ?: 1F, - ) -} - -// Hex String to RGBA - -private val Long.asHexString: String - get() = "#${this.toString(16)}".uppercase() - -private val Long.red: Int - get() = if (this.asHexString.isLongFormHex) (this and 0xFF000000 shr 24).toInt() else (this and 0xFF0000 shr 16).toInt() - -private val Long.green: Int - get() = if (this.asHexString.isLongFormHex) (this and 0xFF0000 shr 16).toInt() else (this and 0xFF00 shr 8).toInt() - -private val Long.blue: Int - get() = if (this.asHexString.isLongFormHex) (this and 0xFF00 shr 8).toInt() else (this and 0xFF).toInt() - -private val Long.alpha: Float - get() = if (this.asHexString.isLongFormHex) ((this and 0xFF).toFloat() / 255).rounded else 1F - -private val String.isLongFormHex: Boolean - get() = this.length == 8 + 1 - -private fun hexFromRGB( - r: Int, - g: Int, - b: Int, - a: Float?, - alphaIsPrefix: Boolean, -): String { - val rgbString = (r.asHexString + g.asHexString + b.asHexString) - return if (alphaIsPrefix) { - "#${a.asAlphaString + rgbString}".uppercase() - } else { - "#${rgbString + a.asAlphaString}".uppercase() - } -} - -// RGBA to String - -private val Float.rounded: Float - get() = (this * 100).toInt() / 100F - -private val Int.asHexString: String - get() = toString(16).padStart(2, '0') - -private val Float?.asAlphaString: String - get() = this?.let { (it * 255).roundToInt().asHexString } ?: "" diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColorType.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColorType.kt deleted file mode 100644 index 123d94b4..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColorType.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.kevinschildhorn.atomik.color.base - -/** - * A wrapper for an AtomikColor associated with an id. - * - * @property id the id associated with the color - * @property color the color - */ -@Suppress("SpellCheckingInspection") -public interface AtomikColorType { - public val id: String - public val color: AtomikColor -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/ColorSet.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/ColorSet.kt deleted file mode 100644 index 4d7581bc..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/color/base/ColorSet.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.kevinschildhorn.atomik.color.base - -/** - * A set of colors to be used in the project - * - * Is an interface that is used to hold the colors used in the project. - * Implemented in [DefaultColorSet] and [CustomColorSet] - * - * @property[fallbackColor] the color that is passed if the requested color cannot be found - */ -public interface ColorSet { - public val fallbackColor: AtomikColor - - /** - * Gets the color based on a name - * @param name the name of the color - * @return the [AtomikColor] based on the name passed - */ - public fun getColor(name: String): AtomikColor -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/+TypographyWeight.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/+TypographyWeight.kt deleted file mode 100644 index 404eaf59..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/+TypographyWeight.kt +++ /dev/null @@ -1,17 +0,0 @@ - -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.typography - -import androidx.compose.ui.text.font.FontWeight -import com.kevinschildhorn.atomik.typography.base.AtomikTypographyWeight - -/** - * A composable [FontWeight] based on the [AtomikTypographyWeight] - */ -internal val AtomikTypographyWeight.fontWeight: FontWeight - get() = - when (this) { - AtomikTypographyWeight.BOLD -> FontWeight.Bold - else -> FontWeight.Normal - } diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/CustomTypographySet.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/CustomTypographySet.kt deleted file mode 100644 index 63a7047d..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/CustomTypographySet.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.kevinschildhorn.atomik.typography - -import com.kevinschildhorn.atomik.typography.base.AtomikTypography -import com.kevinschildhorn.atomik.typography.base.AtomikTypographyType -import com.kevinschildhorn.atomik.typography.base.TypographySet - -/** - * A custom set of typography data to be used in the project - * - * Is an implementation of [TypographySet] that contains a map of [AtomikTypography]. - * Allows for adding Typographies with custom ids. - * For now this acts as a wrapper to a collection of typographies - * - * @property fallbackTypography the Typography that is passed if the requested typography cannot be found - * @property typographies a map of typographies that are contained in this set - */ -internal class CustomTypographySet( - override val fallbackTypography: AtomikTypography, - private val typographies: Map, -) : TypographySet { - /** - * Gets the typography based on a type. If none is found then the fallback is returned - * @param type The type of typography you want to get as a [AtomikTypographyType] - * @return the [AtomikTypography] based on the type passed - */ - override fun getTypography(type: AtomikTypographyType): AtomikTypography = typographies[type] ?: fallbackTypography -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/CustomTypographySetTyped.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/CustomTypographySetTyped.kt deleted file mode 100644 index be369a17..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/CustomTypographySetTyped.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.kevinschildhorn.atomik.typography - -import com.kevinschildhorn.atomik.typography.base.AtomikTypography -import com.kevinschildhorn.atomik.typography.base.AtomikTypographyType -import com.kevinschildhorn.atomik.typography.base.TypographySet - -/** - * A custom set of typography data to be used in the project - * - * Is an implementation of [TypographySet] that contains a map of [AtomikTypography]. - * Allows for adding Typographies with custom ids, that can be referenced from a custom - * enum that is passed in. For now this acts as a wrapper to a collection of typographies - * - * @property fallbackTypography the Typography that is passed if the requested typography cannot be found - * @property typographies a map of typographies that are contained in this set - */ -internal class CustomTypographySetTyped>( - override val fallbackTypography: AtomikTypography, - private val typographies: Map, -) : TypographySet { - /** - * Gets the typography based on an enum value. If none is found then the fallback is returned - * @param type The enum associated with the typography you want to get as a [AtomikTypographyType] - * @return the [AtomikTypography] based on the type passed - */ - public fun getTypography(type: E): AtomikTypography = typographies[type] ?: fallbackTypography - - /** - * Gets the typography based on a type. If none is found then the fallback is returned - * @param type The type of typography you want to get as a [AtomikTypographyType] - * @return the [AtomikTypography] based on the type passed - */ - override fun getTypography(type: AtomikTypographyType): AtomikTypography = fallbackTypography -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikFontFamily.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikFontFamily.kt deleted file mode 100644 index 13140ecf..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikFontFamily.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.kevinschildhorn.atomik.typography.base - -import androidx.compose.ui.text.font.FontFamily - -/** - * A class containing the Font Family of the Design system - * - * This is either a group of UIFonts in iOS or a FontFamily in compose. It is needed to use - * platform specific font functionality - */ -@Suppress("SpellCheckingInspection") -public expect class AtomikFontFamily { - public val fontFamily: FontFamily -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikTypography.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikTypography.kt deleted file mode 100644 index 0b7f2640..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikTypography.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.kevinschildhorn.atomik.typography.base - -import dev.icerock.moko.resources.FontResource - -/** - * A common implementation of a Typography, that contains data for describing a font. - * - * @property weight the weight of the text (ex. bold, thin, normal, etc) - * @property size the size of the text (in dp or pt) - * @property fontName the name of the font used, if not specified it will use the default font - */ -@Suppress("SpellCheckingInspection") -public data class AtomikTypography( - val weight: AtomikTypographyWeight = AtomikTypographyWeight.NORMAL, - val size: Int, - val font: FontResource, -) diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikTypographyType.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikTypographyType.kt deleted file mode 100644 index 34f821f6..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikTypographyType.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.kevinschildhorn.atomik.typography.base - -/** - * A wrapper for an AtomikTypography associated with an id. - * - * @property id the id associated with the Typography - * @property typography the typography - */ -@Suppress("SpellCheckingInspection") -public interface AtomikTypographyType { - public val id: String - public val typography: AtomikTypography -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikTypographyWeight.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikTypographyWeight.kt deleted file mode 100644 index 75f4b72f..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikTypographyWeight.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.kevinschildhorn.atomik.typography.base - -/** - * A common implementation of the weight of a text, such as bold or thin. - * Meant to cover the common Weights that would be used in UI Design - */ -@Suppress("SpellCheckingInspection") -public enum class AtomikTypographyWeight { - THIN, - EXTRALIGHT, - LIGHT, - NORMAL, - MEDIUM, - SEMIBOLD, - BOLD, - EXTRABOLD, - BLACK, -} diff --git a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/TypographySet.kt b/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/TypographySet.kt deleted file mode 100644 index 544e7ab3..00000000 --- a/atomik/src/commonMain/kotlin/com/kevinschildhorn/atomik/typography/base/TypographySet.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.kevinschildhorn.atomik.typography.base - -/** - * A set of typography data to be used in the project - * - * Is an interface that is used to hold the typographies used in the project. - * Implemented in [CustomTypographySet] - * - * @property[fallbackTypography] the Typography that is passed if the requested color cannot be found - */ -public interface TypographySet { - public val fallbackTypography: AtomikTypography - - /** - * Gets the typography based on a type. If none is found then the fallback is returned - * @param type The type of typography you want to get as a [AtomikTypographyType] - * @return the [AtomikTypography] based on the type passed - */ - public fun getTypography(type: AtomikTypographyType): AtomikTypography -} diff --git a/atomik/src/commonTest/kotlin/com/kevinschildhorn/atomik/AtomikColorTest.kt b/atomik/src/commonTest/kotlin/com/kevinschildhorn/atomik/AtomikColorTest.kt deleted file mode 100644 index 393bb1f9..00000000 --- a/atomik/src/commonTest/kotlin/com/kevinschildhorn/atomik/AtomikColorTest.kt +++ /dev/null @@ -1,103 +0,0 @@ -package com.kevinschildhorn.atomik - -import com.kevinschildhorn.atomik.color.base.AtomikColor -import kotlin.test.Test -import kotlin.test.assertEquals - -class AtomikColorTest { - data class ColorTest( - val hexColor: Long, - val hexColorString: String, - val r: Int, - val g: Int, - val b: Int, - val a: Float = 1F, - ) - - private val colorTestNoAlpha = - ColorTest( - hexColor = 0xa63028, - hexColorString = "#A63028", - r = 166, - g = 48, - b = 40, - ) - - private val colorTestAlpha = - ColorTest( - hexColor = 0xa63028E6, - hexColorString = "#A63028E6", - r = 166, - g = 48, - b = 40, - a = 0.90F, - ) - - private val colorWhite = - ColorTest( - hexColor = 0xffffffff, - hexColorString = "#FFFFFFFF", - r = 255, - g = 255, - b = 255, - a = 1F, - ) - - @Test - fun testColorRGB() { - val color = AtomikColor(colorTestNoAlpha.r, colorTestNoAlpha.g, colorTestNoAlpha.b) - assertEquals(expected = colorTestNoAlpha.a, actual = color.a) - assertEquals(expected = colorTestNoAlpha.r, actual = color.r) - assertEquals(expected = colorTestNoAlpha.g, actual = color.g) - assertEquals(expected = colorTestNoAlpha.b, actual = color.b) - assertEquals(expected = colorTestNoAlpha.hexColorString, actual = color.hexString) - assertAll(colorTestNoAlpha, color) - } - - @Test - fun testColorRGBA() { - val color = - AtomikColor( - colorTestAlpha.r, - colorTestAlpha.g, - colorTestAlpha.b, - colorTestAlpha.a, - ) - assertAll(colorTestAlpha, color) - } - - @Test - fun testColorRGBAFull() { - val color = - AtomikColor( - colorWhite.r, - colorWhite.g, - colorWhite.b, - colorWhite.a, - ) - assertAll(colorWhite, color) - } - - @Test - fun testColorHex() { - val color = AtomikColor(colorTestNoAlpha.hexColor) - assertAll(colorTestNoAlpha, color) - } - - @Test - fun testColorHexWithAlpha() { - val color = AtomikColor(colorTestAlpha.hexColor) - assertAll(colorTestAlpha, color) - } - - private fun assertAll( - ColorTest: ColorTest, - color: AtomikColor, - ) { - assertEquals(expected = ColorTest.a, actual = color.a) - assertEquals(expected = ColorTest.r, actual = color.r) - assertEquals(expected = ColorTest.g, actual = color.g) - assertEquals(expected = ColorTest.b, actual = color.b) - assertEquals(expected = ColorTest.hexColorString, actual = color.hexString) - } -} diff --git a/atomik/src/desktopMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt b/atomik/src/desktopMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt deleted file mode 100644 index 24a0ba52..00000000 --- a/atomik/src/desktopMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.kevinschildhorn.atomik.color.base - -/** - * A common implementation of a Color - * - * This contains platform specific implementations in the actual versions. Can be created from - * either a hex Long or an RGBA value - * - * @property hexString The hex value of the color (#RRGGBBAA) - * @property r The red Value (0-255) - * @property g The red Value (0-255) - * @property b The red Value (0-255) - * @property a The alpha Value (0-1) (Defaults to 1) - */ -@Suppress("SpellCheckingInspection") -public actual class AtomikColor { - public actual val hexString: String - public actual val r: Int - public actual val g: Int - public actual val b: Int - public actual val a: Float - - /** - * Constructor with hex variable - * - * @constructor Creates a color based on the hex value(i.e. 0xFFFFFF) - * @param hex - The Hex Value of the color (#RRGGBBAA) - */ - public actual constructor(hex: Long) { - val data = AtomikColorData(hex) - this.hexString = data.hexString - this.r = data.r - this.g = data.g - this.b = data.b - this.a = data.a - } - - /** - * Constructor with r, g, b, a - * - * @constructor Creates a color based on the rgb values. Alpha defaults to 1. - * @param r - Red value (0-255) - * @param g - Green Value (0-255) - * @param b - Blue Value (0-255) - * @param a - Alpha value (0-1) (defaults to 1) - */ - public actual constructor(r: Int, g: Int, b: Int, a: Float?) { - val data = AtomikColorData(r, g, b, a) - this.hexString = data.hexString - this.r = data.r - this.g = data.g - this.b = data.b - this.a = data.a - } -} diff --git a/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/+TextAtom.kt b/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/+TextAtom.kt deleted file mode 100644 index df7a07d6..00000000 --- a/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/+TextAtom.kt +++ /dev/null @@ -1,10 +0,0 @@ - -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.atomic.atoms - -/* -val TextAtom.uiFont: UIFont? - get() = fontFamily?.uiFonts?.get(typography.weight) - ?.fontWithSize(typography.size.toDouble()) -*/ diff --git a/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt b/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt deleted file mode 100644 index fe822baf..00000000 --- a/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/color/base/AtomikColor.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.kevinschildhorn.atomik.color.base - -import platform.UIKit.UIColor - -@Suppress("SpellCheckingInspection") -/* - * iOS implementation of [AtomikColor] - * - * @property uiColor the AtomikColor as an iOS UIColor [platform.UIKit.UIColor] - * @property hexString The hex value of the color (#RRGGBBAA) - * @property r The red Value (0-255) - * @property g The red Value (0-255) - * @property b The red Value (0-255) - * @property a The alpha Value (0-1) (Defaults to 1) - */ -public actual class AtomikColor { - public actual val hexString: String - public actual val r: Int - public actual val g: Int - public actual val b: Int - public actual val a: Float - - public val uiColor: UIColor - get() = UIColor( - red = r.toDouble() / 255, - green = g.toDouble() / 255, - blue = b.toDouble() / 255, - alpha = a.toDouble(), - ) - - public actual constructor(hex: Long) { - val data = AtomikColorData(hex) - this.hexString = data.hexString - this.r = data.r - this.g = data.g - this.b = data.b - this.a = data.a - } - - public actual constructor(r: Int, g: Int, b: Int, a: Float?) { - val data = AtomikColorData(r, g, b, a) - this.hexString = data.hexString - this.r = data.r - this.g = data.g - this.b = data.b - this.a = data.a - } -} diff --git a/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/typography/+TypographyWeight.kt b/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/typography/+TypographyWeight.kt deleted file mode 100644 index c8c4a00f..00000000 --- a/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/typography/+TypographyWeight.kt +++ /dev/null @@ -1,33 +0,0 @@ - -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.typography - -import com.kevinschildhorn.atomik.typography.base.AtomikTypographyWeight -import platform.UIKit.UIFontWeight -import platform.UIKit.UIFontWeightBlack -import platform.UIKit.UIFontWeightBold -import platform.UIKit.UIFontWeightMedium -import platform.UIKit.UIFontWeightRegular -import platform.UIKit.UIFontWeightThin -import platform.UIKit.UIFontWeightUltraLight - -/** - * the UIFontWeight based on the common [AtomikTypographyWeight] - */ -@Suppress("SpellCheckingInspection") -internal val AtomikTypographyWeight.uiFontWeight: UIFontWeight - get() = when (this) { - AtomikTypographyWeight.NORMAL -> UIFontWeightRegular - AtomikTypographyWeight.BOLD -> UIFontWeightBold - AtomikTypographyWeight.BLACK, - AtomikTypographyWeight.EXTRABOLD, - -> UIFontWeightBlack - AtomikTypographyWeight.MEDIUM, - AtomikTypographyWeight.SEMIBOLD, - -> UIFontWeightMedium - AtomikTypographyWeight.THIN, - AtomikTypographyWeight.LIGHT, - -> UIFontWeightThin - AtomikTypographyWeight.EXTRALIGHT -> UIFontWeightUltraLight - } diff --git a/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/typography/PlatformTypographySet.kt b/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/typography/PlatformTypographySet.kt deleted file mode 100644 index 56aae883..00000000 --- a/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/typography/PlatformTypographySet.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.kevinschildhorn.atomik.typography - -/* -@Suppress("unused", "usedFromiOS") -actual class PlatformTypographySet actual constructor(typographySet: DefaultTypographySet) : - TypographySet { - val largeTitle: AtomikTypography = typographySet.h1 ?: typographySet.fallbackTypography - val title: AtomikTypography = typographySet.h2 ?: typographySet.fallbackTypography - val title2: AtomikTypography = typographySet.h3 ?: typographySet.fallbackTypography - val title3: AtomikTypography = typographySet.h4 ?: typographySet.fallbackTypography - val headline: AtomikTypography = typographySet.h5 ?: typographySet.fallbackTypography - val subheadline: AtomikTypography = typographySet.subtitle ?: typographySet.fallbackTypography - val body: AtomikTypography = typographySet.body - val callout: AtomikTypography = typographySet.button ?: typographySet.fallbackTypography - val caption: AtomikTypography = typographySet.caption ?: typographySet.fallbackTypography - val caption2: AtomikTypography = caption - val footnote: AtomikTypography = typographySet.footnote ?: typographySet.fallbackTypography - - override val fallbackTypography: AtomikTypography - get() = body - - override fun getTypography(type: AtomikTypographyType): AtomikTypography = - when (type) { - AtomikTypographyType.LargeTitle -> largeTitle - AtomikTypographyType.Title -> title - AtomikTypographyType.Title2 -> title2 - AtomikTypographyType.Title3 -> title3 - AtomikTypographyType.Headline -> headline - AtomikTypographyType.Subheadline -> subheadline - AtomikTypographyType.Body -> body - AtomikTypographyType.Callout -> callout - AtomikTypographyType.Caption -> caption - AtomikTypographyType.Caption2 -> caption2 - AtomikTypographyType.Footnote -> footnote - else -> fallbackTypography - } -} -*/ diff --git a/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikFontFamily.kt b/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikFontFamily.kt deleted file mode 100644 index c7f81e99..00000000 --- a/atomik/src/iosMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikFontFamily.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.kevinschildhorn.atomik.typography.base - -import androidx.compose.ui.text.font.FontFamily -import platform.UIKit.UIFont - -/** - * A class containing the Font Family of the Design system - * - * This contains a map of UIFonts, based on the weight. Used to reference particular font files. - * - * @property uiFonts a map of UIFonts reference by [AtomikTypographyWeight] - */ -@Suppress("SpellCheckingInspection") -public actual class AtomikFontFamily(private val uiFonts: Map) { - public actual val fontFamily: FontFamily = TODO() -} diff --git a/atomik/src/jvmMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/+Modifier.kt b/atomik/src/jvmMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/+Modifier.kt deleted file mode 100644 index f3bd164b..00000000 --- a/atomik/src/jvmMain/kotlin/com/kevinschildhorn/atomik/atomic/atoms/+Modifier.kt +++ /dev/null @@ -1,18 +0,0 @@ - -@file:Suppress("ktlint:standard:filename") - -package com.kevinschildhorn.atomik.atomic.atoms.compose - -import androidx.compose.foundation.background -import androidx.compose.ui.Modifier -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.ColorAtom -import com.kevinschildhorn.atomik.color.base.composeColor - -/** - * Modifier extension to apply a Color Atom to a composable - * @param colorAtom the ColorAtom that you are applying to the composable - * @return returns a modifier - */ -@Suppress("SpellCheckingInspection") -public fun Modifier.atomikColor(colorAtom: ColorAtom): Modifier = - this.background(colorAtom.color.composeColor) diff --git a/atomik/src/jvmMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikFontFamily.kt b/atomik/src/jvmMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikFontFamily.kt deleted file mode 100644 index 70acf2bc..00000000 --- a/atomik/src/jvmMain/kotlin/com/kevinschildhorn/atomik/typography/base/AtomikFontFamily.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.kevinschildhorn.atomik.typography.base - -import androidx.compose.ui.text.font.FontFamily - -/** - * A class containing the Font Family of the Design system - * - * This is either a group of UIFonts in iOS or a FontFamily in compose. It is needed to use - * platform specific font functionality - */ -@Suppress("SpellCheckingInspection") -public actual class AtomikFontFamily { - public actual val fontFamily: FontFamily - get() = TODO("Not yet implemented") -} diff --git a/build.gradle.kts b/build.gradle.kts index 7d0d9df1..fd995e47 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,6 @@ plugins { alias(libs.plugins.compose.compiler).apply(false) alias(libs.plugins.jetbrains.compose).apply(false) alias(libs.plugins.sqldelight).apply(false) - alias(libs.plugins.resources).apply(false) alias(libs.plugins.serialization).apply(false) alias(libs.plugins.kotlinMultiplatform).apply(false) diff --git a/desktopApp/build.gradle.kts b/desktopApp/build.gradle.kts index 40940c87..4da8219e 100644 --- a/desktopApp/build.gradle.kts +++ b/desktopApp/build.gradle.kts @@ -1,7 +1,9 @@ +import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { kotlin("multiplatform") alias(libs.plugins.compose.compiler) + alias(libs.plugins.jetbrains.compose) } kotlin { @@ -9,7 +11,7 @@ kotlin { sourceSets { val jvmMain by getting { dependencies { - //implementation(compose.desktop.currentOs) + implementation(compose.desktop.currentOs) implementation(libs.koin.core) implementation(libs.kermit) implementation(libs.multiplatform.settings) @@ -19,7 +21,7 @@ kotlin { } } } -/* + compose.desktop { application { mainClass = "MainKt" @@ -30,4 +32,4 @@ compose.desktop { packageVersion = "1.0.0" } } -}*/ +} diff --git a/desktopApp/src/jvmMain/kotlin/Main.kt b/desktopApp/src/jvmMain/kotlin/Main.kt index 61aff3c3..44a8bfbf 100644 --- a/desktopApp/src/jvmMain/kotlin/Main.kt +++ b/desktopApp/src/jvmMain/kotlin/Main.kt @@ -1,5 +1,6 @@ import androidx.compose.ui.window.Window import androidx.compose.ui.window.application +import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.UseCaseFactory import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel @@ -9,12 +10,12 @@ import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel object KoinPurse { val loginViewModel = - LoginViewModel(UseCaseFactory.baseLogger, UseCaseFactory.credentialsRepository) + LoginViewModel(Logger.withTag("LoginViewModel"), UseCaseFactory.credentialsRepository) val directoryViewModel = - DirectoryViewModel(UseCaseFactory.playlistRepository, UseCaseFactory.baseLogger) - val slideshowViewModel = SlideshowViewModel(UseCaseFactory.baseLogger) + DirectoryViewModel(UseCaseFactory.playlistRepository, Logger.withTag("DirectoryViewModel")) + val slideshowViewModel = SlideshowViewModel(Logger.withTag("SlideshowViewModel")) val playlistViewModel = - PlaylistViewModel(UseCaseFactory.playlistRepository, UseCaseFactory.baseLogger) + PlaylistViewModel(UseCaseFactory.playlistRepository, Logger.withTag("PlaylistViewModel")) } fun main() = application { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 57a818b8..a7874c79 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,7 +31,7 @@ sqlite-driver = "2.0.1" turbine = "1.0.0" ## SDK Versions -minSdk = "23" +minSdk = "26" targetSdk = "34" compileSdk = "34" java = "21" @@ -57,8 +57,6 @@ kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serializa ktlint = { module = "com.twitter.compose.rules:ktlint", version.ref = "ktlint" } multiplatform-settings = { module = "com.russhwolf:multiplatform-settings", version.ref = "multiplatform-settings" } multiplatform-settings-test = { module = "com.russhwolf:multiplatform-settings-test", version.ref = "multiplatform-settings-test" } -moko-resource = { module = "dev.icerock.moko:resources", version.ref = "resources-version" } -moko-resource-compose = { module = "dev.icerock.moko:resources-compose", version.ref = "resources-version" } security-crypto = { module = "androidx.security:security-crypto", version.ref = "security-crypto" } smbj = { module = "com.hierynomus:smbj", version.ref = "smbj" } sqlite-driver = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqlite-driver" } @@ -75,8 +73,4 @@ google-services = { id = "com.google.gms.google-services", version.ref = "google crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "crashlytics" } ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint-plugin" } sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" } -resources = { id = "dev.icerock.mobile.multiplatform-resources", version.ref = "resources"} -serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } - -[bundles] -moko-resources = ["moko-resource", "moko-resource-compose"] \ No newline at end of file +serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 8f47dbe6..92c48c3c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,4 +19,3 @@ rootProject.name = "FotoPresenter" include(":androidApp") include(":shared") include(":desktopApp") -include(":atomik") \ No newline at end of file diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 90c337ce..dd964183 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -2,7 +2,6 @@ import org.gradle.kotlin.dsl.get import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi -import kotlin.collections.plusAssign plugins { alias(libs.plugins.kotlinMultiplatform) @@ -12,7 +11,6 @@ plugins { alias(libs.plugins.ktlint) alias(libs.plugins.sqldelight) //alias(libs.plugins.crashlytics) - alias(libs.plugins.resources) alias(libs.plugins.serialization) } @@ -39,7 +37,6 @@ kotlin { val commonMain by getting { dependencies { implementation(kotlin("stdlib-common")) - implementation(project(":atomik")) implementation(compose.runtime) implementation(compose.foundation) implementation(compose.material) @@ -55,7 +52,6 @@ kotlin { implementation(libs.multiplatform.settings) implementation(libs.kotlinx.datetime) implementation(libs.kim) - api(libs.bundles.moko.resources) } } val commonTest by getting { @@ -129,18 +125,14 @@ android { minSdk = libs.versions.minSdk.get().toInt() } compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } kotlin { jvmToolchain(libs.versions.java.get().toInt()) } } -multiplatformResources { - multiplatformResourcesPackage = "com.kevinschildhorn.fotopresenter" // required -} - dependencies { ktlintRuleset(libs.ktlint) } diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt index 275475aa..11070236 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt @@ -26,7 +26,7 @@ actual object SharedImageConverter { val stream = ByteArrayOutputStream() this.compress(Bitmap.CompressFormat.PNG, 100, stream) val byteArray = stream.toByteArray() - if (this != null && !this.isRecycled()) { + if (!this.isRecycled) { this.recycle(); } return byteArray diff --git a/shared/src/commonMain/resources/MR/fonts/Quicksand-Bold.ttf b/shared/src/commonMain/composeResources/font/quicksand_bold.ttf similarity index 100% rename from shared/src/commonMain/resources/MR/fonts/Quicksand-Bold.ttf rename to shared/src/commonMain/composeResources/font/quicksand_bold.ttf diff --git a/shared/src/commonMain/resources/MR/fonts/Quicksand-Light.ttf b/shared/src/commonMain/composeResources/font/quicksand_light.ttf similarity index 100% rename from shared/src/commonMain/resources/MR/fonts/Quicksand-Light.ttf rename to shared/src/commonMain/composeResources/font/quicksand_light.ttf diff --git a/shared/src/commonMain/resources/MR/fonts/Quicksand-Medium.ttf b/shared/src/commonMain/composeResources/font/quicksand_medium.ttf similarity index 100% rename from shared/src/commonMain/resources/MR/fonts/Quicksand-Medium.ttf rename to shared/src/commonMain/composeResources/font/quicksand_medium.ttf diff --git a/shared/src/commonMain/resources/MR/fonts/Quicksand-Regular.ttf b/shared/src/commonMain/composeResources/font/quicksand_regular.ttf similarity index 100% rename from shared/src/commonMain/resources/MR/fonts/Quicksand-Regular.ttf rename to shared/src/commonMain/composeResources/font/quicksand_regular.ttf diff --git a/shared/src/commonMain/resources/MR/fonts/Quicksand-Semibold.ttf b/shared/src/commonMain/composeResources/font/quicksand_semibold.ttf similarity index 100% rename from shared/src/commonMain/resources/MR/fonts/Quicksand-Semibold.ttf rename to shared/src/commonMain/composeResources/font/quicksand_semibold.ttf diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoColors.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoColors.kt index 06208c03..14f3c527 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoColors.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoColors.kt @@ -1,19 +1,33 @@ package com.kevinschildhorn.fotopresenter.ui.atoms -import com.kevinschildhorn.atomik.color.base.AtomikColor +import androidx.compose.foundation.shape.CornerBasedShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Colors +import androidx.compose.material.Shapes +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp -object FotoColors { - val primary = AtomikColor(0xFFA500) - val background = AtomikColor(0xFFFFFF) - val surface = AtomikColor(0xFFFFFF) - val error = AtomikColor(0xFF0000) - val primaryText = AtomikColor(0x402900) - val secondary = AtomikColor(0xFFD383) - val secondaryText = AtomikColor(0xC1872E) - val backgroundText = AtomikColor(0x25231F) - val surfaceText = AtomikColor(0xC2882E) - val errorText = AtomikColor(0x9E1F1F) - val disabled = AtomikColor(0xE0E0E0) +val fotoColors = Colors( + primary = Color(0xFFFFA500), + primaryVariant = Color(0xFFFFA500), + secondary = Color(0xFFFFD383), + secondaryVariant = Color(0xFFFFD383), + background = Color(0xFFFFFFFF), + surface = Color(0xFFFFFFFF), + error = Color(0xFFFF0000), + onPrimary = Color(0xFF402900), + onSecondary = Color(0xFFC1872E), + onBackground = Color(0xFF25231F), + onSurface = Color(0xFFC2882E), + onError = Color(0xFF9E1F1F), + isLight = true +) - val shadow = AtomikColor(r = 0, g = 0, b = 0, a = 0.25f) -} +val disabled = Color(0xE0E0E0) +val shadow = Color(red = 0f, green = 0f, blue = 0f, alpha = 0.25f) + +val fotoShapes = Shapes( + small = RoundedCornerShape(5.dp), + medium = RoundedCornerShape(10.dp), + large = RoundedCornerShape(20.dp), +) \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoTypography.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoTypography.kt index 796af466..05aeca68 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoTypography.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoTypography.kt @@ -1,28 +1,43 @@ package com.kevinschildhorn.fotopresenter.ui.atoms -import com.kevinschildhorn.atomik.typography.base.AtomikTypography -import com.kevinschildhorn.atomik.typography.base.AtomikTypographyWeight -import com.kevinschildhorn.fotopresenter.MR -import dev.icerock.moko.resources.FontResource +import androidx.compose.material.Typography +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp +import fotopresenter.shared.generated.resources.Res +import fotopresenter.shared.generated.resources.quicksand_bold +import fotopresenter.shared.generated.resources.quicksand_light +import fotopresenter.shared.generated.resources.quicksand_medium +import fotopresenter.shared.generated.resources.quicksand_regular +import fotopresenter.shared.generated.resources.quicksand_semibold +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.Font -private val fontregularMoko: FontResource = MR.fonts.Quicksand.regular -private val fontBoldMoko: FontResource = MR.fonts.Quicksand.bold +@OptIn(ExperimentalResourceApi::class) +@Composable +fun QuicksandFontFamily() = FontFamily( + Font(Res.font.quicksand_light, weight = FontWeight.Light), + Font(Res.font.quicksand_regular, weight = FontWeight.Normal), + Font(Res.font.quicksand_medium, weight = FontWeight.Medium), + Font(Res.font.quicksand_semibold, weight = FontWeight.SemiBold), + Font(Res.font.quicksand_bold, weight = FontWeight.Bold) +) -object FotoTypography { - val h1 = - AtomikTypography(size = 96, weight = AtomikTypographyWeight.NORMAL, font = fontregularMoko) - val h2 = - AtomikTypography(size = 48, weight = AtomikTypographyWeight.NORMAL, font = fontregularMoko) - val h3 = - AtomikTypography(size = 36, weight = AtomikTypographyWeight.NORMAL, font = fontregularMoko) - val h4 = - AtomikTypography(size = 24, weight = AtomikTypographyWeight.NORMAL, font = fontregularMoko) - val subtitle = - AtomikTypography(size = 16, weight = AtomikTypographyWeight.NORMAL, font = fontregularMoko) - val button = - AtomikTypography(size = 14, weight = AtomikTypographyWeight.BOLD, font = fontBoldMoko) - val body = - AtomikTypography(size = 16, weight = AtomikTypographyWeight.NORMAL, font = fontregularMoko) - val caption = - AtomikTypography(size = 14, weight = AtomikTypographyWeight.BOLD, font = fontBoldMoko) -} +@Composable +fun FotoTypography() = Typography().run { + val fontFamily = QuicksandFontFamily() + this.copy( + h1 = TextStyle(fontSize = 96.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + h2 = TextStyle(fontSize = 48.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + h3 = TextStyle(fontSize = 36.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + h4 = TextStyle(fontSize = 24.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + subtitle1 = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + subtitle2 = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + button = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Bold, fontFamily = fontFamily), + body1 = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + body2 = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + caption = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Bold, fontFamily = fontFamily), + ) +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/.DS_Store b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..29af7cd6a9166458e14faccf5f6d34befe2d4aae GIT binary patch literal 6148 zcmeHK-AcnS6h3j&wG5#b3W7HQZzry@;l!I#=LVd=H<; zbCPU0+_i|D1Ic%Ce$wQFCOH5g!b$7{cmUvFBNU{p5i+lJZP;Lehz;j>gaQ)0*iR}R!3B{G9prF3;2*3fIBYWCu{E~Ex3oMof UX%@2UbVPm#XhOJS27ZBoFVl!e5C8xG literal 0 HcmV?d00001 diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/.DS_Store b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..cd92b95a296448cd1da410e65b6f69c7a2454935 GIT binary patch literal 6148 zcmeHKQA@)x5WZ~Fbqt{o3gT11*NK~sq4-kf`~z0>L1ngfV6kh)y3vO*=nv38H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Unit, content: @Composable RowScope.() -> Unit, ) { - val molecule = LoginScreenAtoms.primaryButton Button( onClick = onClick, modifier = modifier.height(44.dp), enabled = buttonState.enabled, colors = ButtonDefaults.buttonColors( - backgroundColor = molecule.color.composeColor, - disabledBackgroundColor = molecule.disabledColor.composeColor, + backgroundColor = fotoColors.primary, + disabledBackgroundColor = disabled, ), ) { if (buttonState.loading) { CircularProgressIndicator( modifier = Modifier.width(30.dp), - color = molecule.textAtom.textColor.composeColor, + color = fotoColors.onPrimary, ) } else { content() diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryTextButton.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryTextButton.kt index ec1bc121..7c236463 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryTextButton.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryTextButton.kt @@ -4,8 +4,8 @@ package com.kevinschildhorn.fotopresenter.ui.screens.common.composables import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle -import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreenAtoms +import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors @Composable fun PrimaryTextButton( @@ -14,12 +14,12 @@ fun PrimaryTextButton( buttonState: ButtonState = ButtonState.ENABLED, onClick: () -> Unit, ) { - val molecule = LoginScreenAtoms.primaryButton PrimaryButton(modifier = modifier, buttonState = buttonState, onClick = onClick) { Text( title, - style = molecule.textAtom.textStyle, + style = FotoTypography().button, + color = fotoColors.onPrimary, ) } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/TitleView.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/TitleView.kt index c414599a..fa2463b2 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/TitleView.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/TitleView.kt @@ -2,14 +2,11 @@ package com.kevinschildhorn.fotopresenter.ui.screens.common.composables import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography -import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreenAtoms.title @Composable fun TitleView( value: String, modifier: Modifier = Modifier, ) { - val atom = title(typography = FotoTypography.h3) - AtomikText(value, atom, modifier) + DialogButtonText(value, modifier) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ToastOverlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ToastOverlay.kt index 547b7fba..b47fe337 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ToastOverlay.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ToastOverlay.kt @@ -21,11 +21,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle -import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors import com.kevinschildhorn.fotopresenter.ui.atoms.Padding -import com.kevinschildhorn.fotopresenter.ui.screens.common.CommonAtoms +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors import kotlinx.coroutines.delay @Composable @@ -60,17 +57,15 @@ fun ToastOverlay( Box( modifier = Modifier .clip(RoundedCornerShape(25.dp)) - .background(FotoColors.secondary.composeColor), + .background(fotoColors.secondary), ) { - Text( + ToastMessage( text, modifier = Modifier .padding( horizontal = Padding.STANDARD.dp, vertical = Padding.MEDIUM.dp ), - color = CommonAtoms.toastOverlay.textColor.composeColor, - style = CommonAtoms.toastOverlay.textStyle, ) } Spacer(Modifier.height(25.dp)) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/.DS_Store b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 - get() = listOf(imageAtom, textAtom) - } -} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt index 0345e49d..ab3ee5a1 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt @@ -20,12 +20,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle -import com.kevinschildhorn.atomik.color.base.composeColor import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails import com.kevinschildhorn.fotopresenter.ui.UiState -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors +import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography import com.kevinschildhorn.fotopresenter.ui.atoms.Padding +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors import com.kevinschildhorn.fotopresenter.ui.screens.common.ActionSheetAction import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ActionSheet import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ConfirmationDialog @@ -33,7 +32,6 @@ import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ErrorView import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.FilterDialog import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ImagePreviewOverlay import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.LoadingOverlay -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryAtoms.ImageTicker import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.grid.DirectoryGrid import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.navbar.DirectoryNavigationBar import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.navrail.DirectoryTitleBarButton @@ -111,8 +109,8 @@ fun DirectoryScreen( uiState.imageCountString, modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, - style = ImageTicker.textStyle, - color = ImageTicker.textColor.composeColor + style = FotoTypography().caption, + color = fotoColors.onBackground, ) LinearProgressIndicator( progress = uiState.currentImageCount.toFloat() / uiState.totalImageCount.toFloat(), @@ -120,7 +118,7 @@ fun DirectoryScreen( .height(25.dp) .padding(horizontal = Padding.EXTRA_LARGE.dp, vertical = Padding.SMALL.dp) .clip(RoundedCornerShape(5.dp)), - color = FotoColors.primary.composeColor, + color = fotoColors.primary, ) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGridCell.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGridCell.kt index eda2ef93..8ff22b6f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGridCell.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGridCell.kt @@ -13,15 +13,13 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle -import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryAtoms +import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors @Composable fun DirectoryGridCell( modifier: Modifier = Modifier, - backgroundColor: Color = FotoColors.surface.composeColor, + backgroundColor: Color = fotoColors.surface, content: @Composable BoxScope.() -> Unit, ) { Box( @@ -39,10 +37,10 @@ fun DirectoryGridCellText( text: String, modifier: Modifier = Modifier, ) { - val molecule: DirectoryAtoms.EmptyPhotoMolecule = DirectoryAtoms.emptyDirectory Text( text = text, - style = molecule.textAtom.textStyle, + style = FotoTypography().button, + color = fotoColors.onSurface, textAlign = TextAlign.Center, modifier = modifier diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/FolderDirectoryGridCell.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/FolderDirectoryGridCell.kt index bec09c2f..e244af3e 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/FolderDirectoryGridCell.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/FolderDirectoryGridCell.kt @@ -6,21 +6,23 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.Icon +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Edit import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryAtoms +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors import com.kevinschildhorn.fotopresenter.ui.screens.directory.FolderDirectoryGridCellState +import compose.icons.EvaIcons +import compose.icons.evaicons.Fill +import compose.icons.evaicons.fill.Folder @Composable fun FolderDirectoryGridCell( folderState: FolderDirectoryGridCellState, modifier: Modifier = Modifier, ) { - val molecule: DirectoryAtoms.EmptyPhotoMolecule = DirectoryAtoms.emptyDirectory - DirectoryGridCell(modifier) { Column( modifier = @@ -29,13 +31,13 @@ fun FolderDirectoryGridCell( .padding(5.dp), ) { Icon( - imageVector = molecule.imageAtom.image, + imageVector = EvaIcons.Fill.Folder, contentDescription = "Folder", modifier = Modifier .fillMaxWidth() .fillMaxHeight(0.66f), - tint = molecule.imageAtom.color.composeColor, + tint = fotoColors.onSurface, ) DirectoryGridCellText( folderState.name, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/ImageDirectoryGridCell.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/ImageDirectoryGridCell.kt index 989aaa0a..5b1fc4f2 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/ImageDirectoryGridCell.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/ImageDirectoryGridCell.kt @@ -12,8 +12,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors import com.kevinschildhorn.fotopresenter.ui.screens.directory.ImageDirectoryGridCellState import compose.icons.EvaIcons import compose.icons.evaicons.Fill @@ -30,7 +29,7 @@ fun ImageDirectoryGridCell( bitmap = it, contentDescription = imageContent.name, contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxSize().background(FotoColors.surface.composeColor), + modifier = Modifier.fillMaxSize().background(fotoColors.surface), ) }.onError { Column( @@ -52,7 +51,7 @@ fun ImageDirectoryGridCell( }.onLoading { CircularProgressIndicator( modifier = Modifier.width(33.dp).align(Alignment.Center), - color = FotoColors.primary.composeColor, + color = fotoColors.primary, ) } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationBar.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationBar.kt index f412e9d0..c76e4190 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationBar.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationBar.kt @@ -10,8 +10,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors import compose.icons.EvaIcons import compose.icons.evaicons.Fill import compose.icons.evaicons.fill.ChevronRight @@ -34,7 +33,7 @@ fun DirectoryNavigationBar( itemsIndexed(directories){ index, item -> Icon( EvaIcons.Fill.ChevronRight, - tint = FotoColors.secondaryText.composeColor, + tint = fotoColors.onSecondary, contentDescription = null, modifier = Modifier.height(44.dp) ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationHome.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationHome.kt index 0b0b0d5c..ce1f514e 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationHome.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationHome.kt @@ -6,33 +6,31 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Button import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Icon import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.AtomikIcon -import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.AtomikText -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryAtoms +import com.kevinschildhorn.fotopresenter.ui.atoms.disabled +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors import compose.icons.EvaIcons import compose.icons.evaicons.Fill import compose.icons.evaicons.fill.Home @Composable fun DirectoryNavigationHome(onClick: () -> Unit) { - val molecule = DirectoryAtoms.navigationItem Button( onClick = onClick, - modifier = Modifier.height(44.dp).width(44.dp).clip(RoundedCornerShape(molecule.radius.dp)), + modifier = Modifier.height(44.dp).width(44.dp).clip(RoundedCornerShape(10.dp)), colors = ButtonDefaults.buttonColors( - backgroundColor = molecule.color.composeColor, - disabledBackgroundColor = molecule.disabledColor.composeColor, + backgroundColor = fotoColors.secondary, + disabledBackgroundColor = disabled, ), ) { - AtomikIcon( - EvaIcons.Fill.Home, - atom = molecule.textAtom, + Icon( + imageVector = EvaIcons.Fill.Home, + tint = fotoColors.onSecondary, contentDescription = "Home", modifier = Modifier.size(44.dp) ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationItem.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationItem.kt index 4da17099..f60bb366 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationItem.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationItem.kt @@ -1,8 +1,6 @@ package com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.navbar -import androidx.compose.foundation.background import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Button import androidx.compose.material.ButtonDefaults @@ -10,25 +8,20 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.AtomikText -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryAtoms +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors +import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.DialogButtonText @Composable fun DirectoryNavigationItem(title: String, onClick: () -> Unit) { - val molecule = DirectoryAtoms.navigationItem Button( onClick = onClick, - modifier = Modifier.height(44.dp).clip(RoundedCornerShape(molecule.radius.dp)), + modifier = Modifier.height(44.dp).clip(RoundedCornerShape(10.dp)), colors = ButtonDefaults.buttonColors( - backgroundColor = molecule.color.composeColor, - disabledBackgroundColor = molecule.disabledColor.composeColor, + backgroundColor = fotoColors.secondary, + disabledBackgroundColor = fotoColors.onSecondary, ), ) { - AtomikText( - title, - atom = molecule.textAtom, - ) + DialogButtonText(title) } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/DirectoryTitleBarButton.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/DirectoryTitleBarButton.kt index 52fa5eef..42400840 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/DirectoryTitleBarButton.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/DirectoryTitleBarButton.kt @@ -4,11 +4,10 @@ import androidx.compose.material.Icon import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors import androidx.compose.ui.Modifier import androidx.compose.foundation.layout.size import androidx.compose.ui.graphics.vector.ImageVector +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors @Composable fun DirectoryTitleBarButton( @@ -22,7 +21,7 @@ fun DirectoryTitleBarButton( Icon( imageVector, contentDescription = "Menu", - tint = FotoColors.backgroundText.composeColor + tint = fotoColors.onBackground ) } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/NavigationRailOverlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/NavigationRailOverlay.kt index 9ed096fc..698d2fd0 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/NavigationRailOverlay.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/NavigationRailOverlay.kt @@ -8,8 +8,7 @@ import androidx.compose.material.NavigationRail import androidx.compose.material.NavigationRailItem import androidx.compose.material.Text import androidx.compose.runtime.Composable -import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.Overlay import compose.icons.EvaIcons import compose.icons.evaicons.Fill @@ -33,17 +32,17 @@ fun NavigationRailOverlay( ) { Row { NavigationRail( - backgroundColor = FotoColors.surface.composeColor + backgroundColor = fotoColors.surface ) { NavigationRailItem( label = { - Text("Playlists", color = FotoColors.surfaceText.composeColor) + Text("Playlists", color = fotoColors.onSurface) }, icon = { Icon( EvaIcons.Outline.Monitor, contentDescription = "Playlists", - tint = FotoColors.surfaceText.composeColor + tint = fotoColors.onSurface ) }, selected = true, @@ -51,13 +50,13 @@ fun NavigationRailOverlay( ) NavigationRailItem( label = { - Text("Logout", color = FotoColors.surfaceText.composeColor) + Text("Logout", color = fotoColors.onSurface) }, icon = { Icon( EvaIcons.Fill.LogOut, contentDescription = "Logout", - tint = FotoColors.surfaceText.composeColor + tint = fotoColors.onSurface ) }, selected = true, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/LoginScreenAtoms.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/LoginScreenAtoms.kt deleted file mode 100644 index a3dc66da..00000000 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/LoginScreenAtoms.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.kevinschildhorn.fotopresenter.ui.screens.login - -import com.kevinschildhorn.atomik.atomic.atoms.TextViewAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.SimpleColorAtom -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.SimpleTextAtom -import com.kevinschildhorn.atomik.atomic.molecules.OutlinedTextFieldMolecule -import com.kevinschildhorn.atomik.atomic.molecules.TextButtonMolecule -import com.kevinschildhorn.atomik.color.base.AtomikColor -import com.kevinschildhorn.atomik.typography.base.AtomikTypography -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography -import com.kevinschildhorn.fotopresenter.ui.atoms.Padding - -object LoginScreenAtoms { - fun title( - textColor: AtomikColor = FotoColors.backgroundText, - typography: AtomikTypography = FotoTypography.h1, - ) = SimpleTextAtom( - textColor = textColor, - typography = typography, - fontFamily = null, - ) - - val errorView = - TextViewAtom( - textColor = FotoColors.errorText, - typography = FotoTypography.body, - backgroundColor = FotoColors.error, - paddingHorizontal = Padding.MEDIUM.rawValue, - paddingVertical = Padding.MEDIUM.rawValue, - ) - - val primaryButton = - TextButtonMolecule( - color = FotoColors.primary, - disabledColor = FotoColors.disabled, - radius = 15, - textAtom = - SimpleTextAtom( - textColor = FotoColors.primaryText, - typography = FotoTypography.button, - fontFamily = null, - ), - ) - val textFieldMolecule = - OutlinedTextFieldMolecule( - textAtom = textAtom(FotoColors.primaryText), - backgroundColorAtom = SimpleColorAtom(FotoColors.surface), - hintTextAtom = textAtom(FotoColors.surfaceText), - errorTextAtom = textAtom(FotoColors.errorText), - disabledColorAtom = SimpleColorAtom(FotoColors.surface), - focusedBorderColor = FotoColors.backgroundText, - radius = 5, - ) - - private fun textAtom(color: AtomikColor) = - SimpleTextAtom( - textColor = color, - typography = FotoTypography.subtitle, - fontFamily = null, - ) -} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginPasswordTextField.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginPasswordTextField.kt index e9475a2d..c52f5383 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginPasswordTextField.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginPasswordTextField.kt @@ -3,8 +3,6 @@ package com.kevinschildhorn.fotopresenter.ui.screens.login.composables import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.Icon import androidx.compose.material.IconButton -import androidx.compose.material.OutlinedTextField -import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -14,9 +12,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation -import com.kevinschildhorn.atomik.atomic.atoms.shape -import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle -import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreenAtoms import compose.icons.EvaIcons import compose.icons.evaicons.Fill import compose.icons.evaicons.fill.Eye @@ -29,22 +24,13 @@ fun LoginPasswordTextField( placeholder: String, modifier: Modifier = Modifier, ) { - val molecule = LoginScreenAtoms.textFieldMolecule var passwordVisible by rememberSaveable { mutableStateOf(false) } - OutlinedTextField( + LoginTextField( value = value, onValueChange = onValueChange, + placeholder = placeholder, visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), - placeholder = { - Text( - placeholder, - style = molecule.hintTextAtom?.textStyle ?: molecule.textAtom.textStyle, - ) - }, - colors = molecule.colors(), - shape = molecule.shape, - textStyle = molecule.textAtom.textStyle, modifier = modifier, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), trailingIcon = { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginTextField.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginTextField.kt index 23d4412f..ef4e703f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginTextField.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginTextField.kt @@ -1,12 +1,17 @@ package com.kevinschildhorn.fotopresenter.ui.screens.login.composables +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.text.KeyboardOptions.Companion import androidx.compose.material.OutlinedTextField import androidx.compose.material.Text +import androidx.compose.material.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.kevinschildhorn.atomik.atomic.atoms.shape -import com.kevinschildhorn.atomik.atomic.atoms.compose.textStyle -import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreenAtoms +import androidx.compose.ui.text.input.VisualTransformation +import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography +import com.kevinschildhorn.fotopresenter.ui.atoms.disabled +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoShapes @Composable fun LoginTextField( @@ -14,20 +19,29 @@ fun LoginTextField( onValueChange: (String) -> Unit, placeholder: String, modifier: Modifier = Modifier, + visualTransformation: VisualTransformation = VisualTransformation.None, + keyboardOptions: KeyboardOptions = KeyboardOptions.Default, + trailingIcon: @Composable (() -> Unit)? = null, ) { - val molecule = LoginScreenAtoms.textFieldMolecule OutlinedTextField( value = value, onValueChange = onValueChange, + visualTransformation = visualTransformation, placeholder = { Text( placeholder, - style = molecule.hintTextAtom?.textStyle ?: molecule.textAtom.textStyle, + color = fotoColors.onSurface, + style = FotoTypography().subtitle1, ) }, - colors = molecule.colors(), - shape = molecule.shape, - textStyle = molecule.textAtom.textStyle, + colors = TextFieldDefaults.outlinedTextFieldColors( + textColor = fotoColors.onPrimary, + disabledTextColor = disabled, + ), + shape = fotoShapes.small, + textStyle = FotoTypography().subtitle1, + keyboardOptions = keyboardOptions, + trailingIcon = trailingIcon, modifier = modifier, ) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistScreenAtoms.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistScreenAtoms.kt deleted file mode 100644 index b09a80e5..00000000 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistScreenAtoms.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.kevinschildhorn.fotopresenter.ui.screens.playlist - -import com.kevinschildhorn.atomik.atomic.atoms.interfaces.SimpleTextAtom -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography - -object PlaylistScreenAtoms { - - val title:SimpleTextAtom = SimpleTextAtom( - textColor = FotoColors.secondaryText, - typography = FotoTypography.h4, - fontFamily = null, - ) - - val rowTitle:SimpleTextAtom = SimpleTextAtom( - textColor = FotoColors.secondaryText, - typography = FotoTypography.button, - fontFamily = null, - ) -} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistColumn.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistColumn.kt index fe820d26..caf49a1c 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistColumn.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistColumn.kt @@ -12,12 +12,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp -import com.kevinschildhorn.atomik.color.base.composeColor import com.kevinschildhorn.fotopresenter.data.PlaylistDetails -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors import com.kevinschildhorn.fotopresenter.ui.atoms.Padding -import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.AtomikText -import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistScreenAtoms +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors +import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.DialogButtonText @Composable fun PlaylistColumn( @@ -29,19 +27,15 @@ fun PlaylistColumn( onDelete: (Long) -> Unit, modifier: Modifier = Modifier, ) { - val atom = PlaylistScreenAtoms.title Column( modifier .fillMaxWidth() .padding(Padding.STANDARD.dp) .clip(RoundedCornerShape(10.dp)) - .background(FotoColors.secondary.composeColor) + .background(fotoColors.secondary) ) { Column(Modifier.fillMaxWidth().padding(Padding.MEDIUM.dp)) { - AtomikText( - "Playlists", - atom = atom - ) + DialogButtonText("Playlists") LazyColumn { items(options) { PlaylistScreenPlaylistRow( @@ -62,7 +56,7 @@ fun PlaylistColumn( Divider( startIndent = 0.dp, thickness = 1.dp, - color = FotoColors.secondaryText.composeColor + color = fotoColors.onSecondary ) } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenCreateRow.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenCreateRow.kt index 2967f69a..70cbeee7 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenCreateRow.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenCreateRow.kt @@ -5,15 +5,15 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.width +import androidx.compose.material.Icon import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.kevinschildhorn.fotopresenter.ui.atoms.Padding -import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.AtomikIcon -import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.AtomikText -import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistScreenAtoms +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors +import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.DialogButtonText import compose.icons.EvaIcons import compose.icons.evaicons.Outline import compose.icons.evaicons.outline.PlusCircle @@ -23,7 +23,6 @@ fun PlaylistScreenCreateRow( modifier: Modifier = Modifier, onClick: () -> Unit, ) { - val atom = PlaylistScreenAtoms.rowTitle Row( modifier = modifier.fillMaxWidth().height(55.dp), verticalAlignment = Alignment.CenterVertically, @@ -32,13 +31,13 @@ fun PlaylistScreenCreateRow( modifier = Modifier.fillMaxWidth(), onClick = onClick ) { - AtomikIcon( + Icon( EvaIcons.Outline.PlusCircle, - atom, + tint = fotoColors.onSecondary, contentDescription = "Create", ) Spacer(Modifier.width(Padding.SMALL.dp)) - AtomikText("Create", atom) + DialogButtonText("Create") Spacer(Modifier.fillMaxWidth()) } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenPlaylistRow.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenPlaylistRow.kt index 920f33db..cd4d7fd4 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenPlaylistRow.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenPlaylistRow.kt @@ -8,14 +8,14 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.width +import androidx.compose.material.Icon import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.AtomikIcon -import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.AtomikText -import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistScreenAtoms +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors +import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.DialogButtonText import compose.icons.EvaIcons import compose.icons.evaicons.Outline import compose.icons.evaicons.outline.Edit @@ -30,7 +30,6 @@ fun PlaylistScreenPlaylistRow( onEdit: () -> Unit, onDelete: () -> Unit, ) { - val atom = PlaylistScreenAtoms.rowTitle Row( modifier = Modifier.fillMaxWidth().height(55.dp), verticalAlignment = Alignment.CenterVertically, @@ -40,7 +39,7 @@ fun PlaylistScreenPlaylistRow( onClick = onClick, modifier = Modifier.fillMaxSize(0.7f) ) { - AtomikText(title, atom) + DialogButtonText(title) Spacer(Modifier.fillMaxWidth()) } Row(modifier = Modifier.fillMaxHeight()) { @@ -48,9 +47,9 @@ fun PlaylistScreenPlaylistRow( modifier = Modifier.width(44.dp), onClick = onDetails ) { - AtomikIcon( + Icon( EvaIcons.Outline.Info, - atom, + tint = fotoColors.onSecondary, contentDescription = "Details", ) } @@ -58,9 +57,9 @@ fun PlaylistScreenPlaylistRow( modifier = Modifier.width(44.dp), onClick = onEdit ) { - AtomikIcon( + Icon( EvaIcons.Outline.Edit, - atom, + tint = fotoColors.onSecondary, contentDescription = "Edit", ) } @@ -68,9 +67,9 @@ fun PlaylistScreenPlaylistRow( modifier = Modifier.width(44.dp), onClick = onDelete, ) { - AtomikIcon( + Icon( EvaIcons.Outline.Trash, - atom, + tint = fotoColors.onSecondary, contentDescription = "Trash" ) } diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/KoinTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/KoinTest.kt index 13b5995e..6f12fc5f 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/KoinTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/KoinTest.kt @@ -10,7 +10,7 @@ import com.russhwolf.settings.MapSettings import com.russhwolf.settings.Settings import org.koin.dsl.module -private val baseLogger = Logger(LoggerConfig.default) +private val baseLogger = Logger.withTag("Test") fun testingModule(settings: MapSettings = MapSettings()) = module { diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/domain/SaveCredentialsUseCaseTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/domain/SaveCredentialsUseCaseTest.kt index 396f6628..3c7e0411 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/domain/SaveCredentialsUseCaseTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/domain/SaveCredentialsUseCaseTest.kt @@ -22,7 +22,7 @@ class SaveCredentialsUseCaseTest : KoinTest { @BeforeTest fun startTest() { - val baseLogger = Logger(LoggerConfig.default) + val baseLogger = Logger.withTag("Test") startKoin { modules(testingModule()) From 0e44dafc77d32bccf4d72d2d9e42abd3a95992f4 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 10 Oct 2024 15:11:36 -0400 Subject: [PATCH 05/19] Adding compose navigation --- gradle/libs.versions.toml | 2 + shared/build.gradle.kts | 1 + shared/src/commonMain/kotlin/App.kt | 87 ++++++++++++++++++----------- 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a7874c79..0be4334f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,6 +21,7 @@ ktlint = "0.0.26" ktlint-plugin = "12.1.1" multiplatform-settings = "1.1.1" multiplatform-settings-test = "1.0.0" +navigationCompose = "2.7.0-alpha07" resources-version = "0.23.0" security-crypto = "1.1.0-alpha06" smbj = "0.11.5" @@ -57,6 +58,7 @@ kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serializa ktlint = { module = "com.twitter.compose.rules:ktlint", version.ref = "ktlint" } multiplatform-settings = { module = "com.russhwolf:multiplatform-settings", version.ref = "multiplatform-settings" } multiplatform-settings-test = { module = "com.russhwolf:multiplatform-settings-test", version.ref = "multiplatform-settings-test" } +navigation-compose = { module = "org.jetbrains.androidx.navigation:navigation-compose", version.ref = "navigationCompose" } security-crypto = { module = "androidx.security:security-crypto", version.ref = "security-crypto" } smbj = { module = "com.hierynomus:smbj", version.ref = "smbj" } sqlite-driver = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqlite-driver" } diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index dd964183..5f14d029 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -42,6 +42,7 @@ kotlin { implementation(compose.material) @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) implementation(compose.components.resources) + implementation(libs.navigation.compose) implementation(libs.eva.icons) implementation(libs.cache4k) implementation(libs.kotlinx.serialization.json) diff --git a/shared/src/commonMain/kotlin/App.kt b/shared/src/commonMain/kotlin/App.kt index b0d30305..e0d2632c 100644 --- a/shared/src/commonMain/kotlin/App.kt +++ b/shared/src/commonMain/kotlin/App.kt @@ -1,7 +1,16 @@ +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors +import com.kevinschildhorn.fotopresenter.ui.atoms.fotoShapes import com.kevinschildhorn.fotopresenter.ui.screens.common.Screen import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryScreen import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel @@ -12,49 +21,59 @@ import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowScreen import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel +// The ViewModels need to be passed in here because koin doesn't support Koin @Composable fun App( loginViewModel: LoginViewModel, directoryViewModel: DirectoryViewModel, slideshowViewModel: SlideshowViewModel, playlistViewModel: PlaylistViewModel, + navController: NavHostController = rememberNavController() ) { - val currentScreen = remember { mutableStateOf(Screen.LOGIN) } + MaterialTheme( + colors = fotoColors, + typography = FotoTypography(), + shapes = fotoShapes, + ) { - MaterialTheme { - when (currentScreen.value) { - Screen.LOGIN -> - LoginScreen(loginViewModel) { - directoryViewModel.setLoggedIn() - currentScreen.value = Screen.DIRECTORY + Scaffold { innerPadding -> + NavHost( + navController = navController, + startDestination = Screen.LOGIN.name, + modifier = Modifier.fillMaxSize().padding(innerPadding) + ) { + composable(route = Screen.LOGIN.name) { + LoginScreen(loginViewModel) { + navController.navigate(Screen.DIRECTORY.name) + } } - - Screen.DIRECTORY -> - DirectoryScreen( - directoryViewModel, - onLogout = { - loginViewModel.setLoggedOut() - currentScreen.value = Screen.LOGIN - }, - onStartSlideshow = { - slideshowViewModel.setSlideshow(it) - directoryViewModel.clearSlideshow() - currentScreen.value = Screen.SLIDESHOW - }, - onShowPlaylists = { - currentScreen.value = Screen.PLAYLIST + composable(route = Screen.DIRECTORY.name) { + DirectoryScreen( + directoryViewModel, + onLogout = { + loginViewModel.setLoggedOut() + navController.navigate(Screen.LOGIN.name) + }, + onStartSlideshow = { + slideshowViewModel.setSlideshow(it) + directoryViewModel.clearSlideshow() + navController.navigate(Screen.SLIDESHOW.name) + }, + onShowPlaylists = { + navController.navigate(Screen.PLAYLIST.name) + } + ) + } + composable(route = Screen.SLIDESHOW.name) { + SlideshowScreen(slideshowViewModel) { + navController.navigate(Screen.DIRECTORY.name) } - ) - - Screen.SLIDESHOW -> - SlideshowScreen(slideshowViewModel) { - currentScreen.value = Screen.DIRECTORY } - - Screen.PLAYLIST -> { - PlaylistScreen(playlistViewModel, overlaid = false) { - slideshowViewModel.setSlideshowFromPlaylist(it) - currentScreen.value = Screen.SLIDESHOW + composable(route = Screen.PLAYLIST.name) { + PlaylistScreen(playlistViewModel, overlaid = false) { + slideshowViewModel.setSlideshowFromPlaylist(it) + navController.navigate(Screen.SLIDESHOW.name) + } } } } From 933fe8c590da7ef05b46bf7005faa95720c0a2a8 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Fri, 11 Oct 2024 11:07:18 -0400 Subject: [PATCH 06/19] adding temp code --- .../com/kevinschildhorn/MainActivity.kt | 3 +- desktopApp/src/jvmMain/kotlin/Main.kt | 17 +++- shared/src/androidMain/kotlin/Main.android.kt | 3 +- shared/src/commonMain/kotlin/App.kt | 5 +- .../com/kevinschildhorn/fotopresenter/Koin.kt | 7 +- .../fotopresenter/data/Directory.kt | 2 + .../fotopresenter/data/DirectoryEtc.kt | 82 ++++++++++++++++ .../data/repositories/DirectoryRepository.kt | 7 +- .../data/repositories/ImageRepository.kt | 1 + .../domain/image/RetrieveImageUseCase.kt | 2 +- .../ui/screens/directory/DirectoryScreen.kt | 43 ++++---- .../screens/directory/DirectoryViewModel.kt | 72 ++++++++------ .../directory/DirectoryViewModelTwo.kt | 97 +++++++++++++++++++ .../fotopresenter/ui/shared/SharedImage.kt | 3 +- shared/src/desktopMain/kotlin/Main.desktop.kt | 3 +- .../fotopresenter/UseCaseFactoryDesktop.kt | 6 +- .../fotopresenter/ui/shared/SharedImage.kt | 5 +- .../fotopresenter/ui/shared/SharedImage.kt | 3 +- .../fotopresenter/data/network/SMBJHandler.kt | 3 +- .../fotopresenter/ui/shared/SharedImage.kt | 5 +- 20 files changed, 304 insertions(+), 65 deletions(-) create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryEtc.kt create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModelTwo.kt diff --git a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt index b9d912e0..35c02d18 100644 --- a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt +++ b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt @@ -6,6 +6,7 @@ import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import com.kevinschildhorn.fotopresenter.startKoin import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -15,7 +16,7 @@ import org.koin.core.component.KoinComponent class MainActivity : AppCompatActivity(), KoinComponent { private val loginViewModel by viewModel() - private val directoryViewModel by viewModel() + private val directoryViewModel by viewModel() private val slideshowViewModel by viewModel() private val playlistViewModel by viewModel() diff --git a/desktopApp/src/jvmMain/kotlin/Main.kt b/desktopApp/src/jvmMain/kotlin/Main.kt index 44a8bfbf..7c563025 100644 --- a/desktopApp/src/jvmMain/kotlin/Main.kt +++ b/desktopApp/src/jvmMain/kotlin/Main.kt @@ -3,6 +3,7 @@ import androidx.compose.ui.window.application import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.UseCaseFactory import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -12,7 +13,19 @@ object KoinPurse { val loginViewModel = LoginViewModel(Logger.withTag("LoginViewModel"), UseCaseFactory.credentialsRepository) val directoryViewModel = - DirectoryViewModel(UseCaseFactory.playlistRepository, Logger.withTag("DirectoryViewModel")) + DirectoryViewModel( + UseCaseFactory.playlistRepository, + Logger.withTag("DirectoryViewModel"), + UseCaseFactory.directoryRepository, + UseCaseFactory.directoryEtc, + ) + val directoryViewModelTwo = + DirectoryViewModelTwo( + UseCaseFactory.playlistRepository, + Logger.withTag("DirectoryViewModel"), + UseCaseFactory.directoryRepository, + UseCaseFactory.directoryEtc, + ) val slideshowViewModel = SlideshowViewModel(Logger.withTag("SlideshowViewModel")) val playlistViewModel = PlaylistViewModel(UseCaseFactory.playlistRepository, Logger.withTag("PlaylistViewModel")) @@ -25,7 +38,7 @@ fun main() = application { ) { MainView( KoinPurse.loginViewModel, - KoinPurse.directoryViewModel, + KoinPurse.directoryViewModelTwo, KoinPurse.slideshowViewModel, KoinPurse.playlistViewModel, ) diff --git a/shared/src/androidMain/kotlin/Main.android.kt b/shared/src/androidMain/kotlin/Main.android.kt index fd25cda6..758a5f37 100644 --- a/shared/src/androidMain/kotlin/Main.android.kt +++ b/shared/src/androidMain/kotlin/Main.android.kt @@ -1,5 +1,6 @@ import androidx.compose.runtime.Composable import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -9,7 +10,7 @@ actual fun getPlatformName(): String = "Android" @Composable fun MainView( loginViewModel: LoginViewModel, - directoryViewModel: DirectoryViewModel, + directoryViewModel: DirectoryViewModelTwo, slideshowViewModel: SlideshowViewModel, playlistViewModel: PlaylistViewModel, ) = App(loginViewModel, directoryViewModel, slideshowViewModel, playlistViewModel) diff --git a/shared/src/commonMain/kotlin/App.kt b/shared/src/commonMain/kotlin/App.kt index e0d2632c..a38533f0 100644 --- a/shared/src/commonMain/kotlin/App.kt +++ b/shared/src/commonMain/kotlin/App.kt @@ -14,6 +14,7 @@ import com.kevinschildhorn.fotopresenter.ui.atoms.fotoShapes import com.kevinschildhorn.fotopresenter.ui.screens.common.Screen import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryScreen import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreen import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistScreen @@ -25,7 +26,7 @@ import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @Composable fun App( loginViewModel: LoginViewModel, - directoryViewModel: DirectoryViewModel, + directoryViewModel: DirectoryViewModelTwo, slideshowViewModel: SlideshowViewModel, playlistViewModel: PlaylistViewModel, navController: NavHostController = rememberNavController() @@ -56,7 +57,7 @@ fun App( }, onStartSlideshow = { slideshowViewModel.setSlideshow(it) - directoryViewModel.clearSlideshow() + //directoryViewModel.clearSlideshow() navController.navigate(Screen.SLIDESHOW.name) }, onShowPlaylists = { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt index 27543619..f1a6ab74 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt @@ -2,6 +2,7 @@ package com.kevinschildhorn.fotopresenter import co.touchlab.kermit.Logger import co.touchlab.kermit.LoggerConfig +import com.kevinschildhorn.fotopresenter.data.DirectoryEtc import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource @@ -24,6 +25,7 @@ import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageUseCase import com.kevinschildhorn.fotopresenter.domain.image.RetrieveSlideshowFromPlaylistUseCase import com.kevinschildhorn.fotopresenter.domain.image.SaveMetadataForPathUseCase import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -45,6 +47,8 @@ val commonModule = single { CredentialsRepository(get()) } single { DirectoryDataSource(get(), baseLogger.withTag("DirectoryDataSource")) } single { DirectoryRepository(get(), get()) } + single { DirectoryEtc(get(), get(), baseLogger.withTag("DirectoryEtc")) } + single { ImageRemoteDataSource(get()) } single { ImageRepository(get()) } single { ImageCacheDataSource(get(), get(), baseLogger.withTag("ImageCacheDataSource")) } @@ -83,7 +87,8 @@ val commonModule = factory { SaveMetadataForPathUseCase(get()) } // UI single { LoginViewModel(baseLogger.withTag("LoginViewModel"), get()) } - single { DirectoryViewModel(get(), baseLogger.withTag("DirectoryViewModel")) } + single { DirectoryViewModel(get(), baseLogger.withTag("DirectoryViewModel"), get(), get()) } + single { DirectoryViewModelTwo(get(), baseLogger.withTag("DirectoryViewModel"), get(), get())} single { SlideshowViewModel(baseLogger.withTag("SlideshowViewModel")) } single { PlaylistViewModel(get(), baseLogger.withTag("PlaylistViewModel")) } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt index f663b314..94a1a95d 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt @@ -1,5 +1,6 @@ package com.kevinschildhorn.fotopresenter.data +import androidx.compose.ui.graphics.ImageBitmap import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.ui.SortingType import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage @@ -29,6 +30,7 @@ data class ImageDirectory( override val details: NetworkDirectoryDetails, val metaData: MetadataFileDetails?, val image: SharedImage? = null, + val imageBitmap: ImageBitmap? = null, ) : Directory { override fun toString(): String = "(I:${details.fullPath}:${details.id})" } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryEtc.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryEtc.kt new file mode 100644 index 00000000..22806af3 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryEtc.kt @@ -0,0 +1,82 @@ +package com.kevinschildhorn.fotopresenter.data + +import co.touchlab.kermit.Logger +import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository +import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext + +class DirectoryEtc( + private val imageRepository: ImageRepository, + private val directoryRepository: DirectoryRepository, + private val logger: Logger, +) { + + private val _directoryContentsFlow = MutableStateFlow(DirectoryContents()) + private val _imageDirectoryList = MutableStateFlow>(emptyList()) + + val directoryFlow: Flow = + combine(_directoryContentsFlow, _imageDirectoryList) { directory, images -> + directory.copy(images = images) + } + + fun refreshDirectories(path: String, coroutineScope: CoroutineScope) { + coroutineScope.launch(Dispatchers.Default) { + // Retrieve File Data + var directoryContents = directoryRepository.getDirectoryContents(path) + _directoryContentsFlow.emit(directoryContents) + _imageDirectoryList.emit(directoryContents.images) + + // For each image, get the Byte Array + val images = directoryContents + .images + //.take(10) + .toMutableList() + + images.chunked(10).forEach { imageChunk -> + logger.i("Starting Jobs!") + runBlocking { + imageChunk.forEachIndexed { index, image -> + coroutineScope.launch { + processItemAsync(index, image) + } + } + } + logger.i("Joined!") + } + + logger.i { "Finished!" } + } + } + + suspend fun processItemAsync( + index: Int, + item: ImageDirectory, + ) { + var mutableItemDirectory = item + val itemWithBytes = withContext(Dispatchers.IO) { + val sharedImage = imageRepository.getImage(item.details) + mutableItemDirectory.copy(image = sharedImage) + } + updateImageList(index, itemWithBytes) + val itemWithBitmap = withContext(Dispatchers.IO) { + val bitmap = itemWithBytes.image?.getImageBitmap(256) + itemWithBytes.copy(imageBitmap = bitmap) + } + updateImageList(index, itemWithBitmap) + item.image?.close() + } + + private fun updateImageList(index: Int, item: ImageDirectory) { + val items = _imageDirectoryList.value.toMutableList() + items[index] = item + _imageDirectoryList.update { items } + } +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt index 7bf66afa..52265801 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt @@ -12,21 +12,22 @@ class DirectoryRepository( private val directoryDataSource: DirectoryDataSource, private val metadataDataSource: ImageMetadataDataSource, ) { + // Retrieves [NetworkDirectoryDetails] for folders and directories. Contains no bitmap data suspend fun getDirectoryContents(path: String): DirectoryContents { val folderDirectories: List = directoryDataSource.getFolderDirectories(path) val imageDirectories: List = directoryDataSource.getImageDirectories(path) - val metaData = metadataDataSource.importMetaData() - + //val metaData = metadataDataSource.importMetaData() return DirectoryContents( folders = folderDirectories.map { FolderDirectory(it) }, images = imageDirectories.map { networkDetails -> ImageDirectory( networkDetails, - metaData = metaData.files.find { networkDetails.fullPath == it.filePath } + metaData = null, //metaData.files.find { networkDetails.fullPath == it.filePath } + image = null, ) }, ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt index ddbc81b9..df91ac04 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt @@ -7,5 +7,6 @@ import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage class ImageRepository( private val remoteDataSource: ImageRemoteDataSource, ) { + // Gets Image ByteArray from a Remote Data Source suspend fun getImage(directory: NetworkDirectoryDetails): SharedImage? = remoteDataSource.getImage(directory) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt index cc2efaa8..dc9bd540 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt @@ -14,7 +14,7 @@ class RetrieveImageUseCase( private val logger: Logger, ) { - suspend operator fun invoke( + operator fun invoke( directory: ImageDirectory, imageSize: Int, ): ImageBitmap? { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt index ab3ee5a1..a173e716 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import com.kevinschildhorn.fotopresenter.baseLogger import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails import com.kevinschildhorn.fotopresenter.ui.UiState import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography @@ -56,23 +57,24 @@ enum class DirectoryOverlay { @Composable fun DirectoryScreen( - viewModel: DirectoryViewModel, + viewModel: DirectoryViewModelTwo, onLogout: () -> Unit, onStartSlideshow: (ImageSlideshowDetails) -> Unit, onShowPlaylists: () -> Unit, ) { LaunchedEffect(Unit) { + baseLogger.i { "Launched Effect" } viewModel.refreshScreen() } - val uiState by viewModel.uiState.collectAsState() - val imageUiState by viewModel.imageUiState.collectAsState() + val uiState by viewModel.uiState.collectAsState(DirectoryScreenStateTwo()) + //val imageUiState by viewModel.imageUiState.collectAsState() var overlayVisible by remember { mutableStateOf(DirectoryOverlay.NONE) } // Navigation - if (!uiState.loggedIn) onLogout() - uiState.slideshowDetails?.let { - onStartSlideshow(it) - } + //if (!uiState.loggedIn) onLogout() + //uiState.slideshowDetails?.let { + // onStartSlideshow(it) + //} //region UI Column { @@ -97,13 +99,14 @@ fun DirectoryScreen( DirectoryNavigationBar( directories = uiState.currentPathList, onHome = { - viewModel.navigateToFolder(-1) + //viewModel.navigateToFolder(-1) }, onItem = { - viewModel.navigateToFolder(it) + //viewModel.navigateToFolder(it) }, modifier = Modifier.padding(Padding.SMALL.dp) ) + /* if (uiState.imageCountString.isNotEmpty()) { Text( uiState.imageCountString, @@ -121,18 +124,18 @@ fun DirectoryScreen( color = fotoColors.primary, ) - } + }*/ DirectoryGrid( uiState.directoryGridState, onFolderPressed = { - viewModel.changeDirectory(it) + //viewModel.changeDirectory(it) }, onImageDirectoryPressed = { - viewModel.setSelectedImageById(it) + //viewModel.setSelectedImageById(it) overlayVisible = DirectoryOverlay.IMAGE }, onActionSheet = { - viewModel.setSelectedDirectory(it) + //viewModel.setSelectedDirectory(it) overlayVisible = DirectoryOverlay.ACTION_SHEET }, ) @@ -142,6 +145,7 @@ fun DirectoryScreen( // Overlays //region ActionSheet + /* ActionSheet( visible = overlayVisible == DirectoryOverlay.ACTION_SHEET, offset = 200, @@ -173,9 +177,9 @@ fun DirectoryScreen( overlayVisible = DirectoryOverlay.NONE viewModel.setSelectedDirectory(null) }, - ) + )*/ //endregion - +/* //region Selected Image imageUiState.selectedImage?.let { ImagePreviewOverlay( @@ -192,7 +196,7 @@ fun DirectoryScreen( viewModel.showNextImage() }, ) - } + }*/ //endregion //region Loading @@ -223,7 +227,7 @@ fun DirectoryScreen( overlayVisible = DirectoryOverlay.NONE }, onConfirmation = { - viewModel.logout() + //viewModel.logout() overlayVisible = DirectoryOverlay.NONE }, ) @@ -237,12 +241,13 @@ fun DirectoryScreen( overlayVisible = DirectoryOverlay.NONE }, onConfirmation = { - viewModel.setFilterType(it) + //viewModel.setFilterType(it) } ) } //region Playlist + /* if (overlayVisible == DirectoryOverlay.PLAYLIST) { PlaylistScreen( viewModel, @@ -269,5 +274,5 @@ fun DirectoryScreen( viewModel.setSelectedDirectory(null) overlayVisible = DirectoryOverlay.NONE }) - } + }*/ } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt index 4be35edf..828d31b8 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt @@ -4,13 +4,14 @@ import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.UseCaseFactory import com.kevinschildhorn.fotopresenter.data.Directory import com.kevinschildhorn.fotopresenter.data.DirectoryContents +import com.kevinschildhorn.fotopresenter.data.DirectoryEtc import com.kevinschildhorn.fotopresenter.data.FolderDirectory import com.kevinschildhorn.fotopresenter.data.ImageDirectory -import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails import com.kevinschildhorn.fotopresenter.data.MetadataFileDetails import com.kevinschildhorn.fotopresenter.data.PlaylistDetails import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException +import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository import com.kevinschildhorn.fotopresenter.data.repositories.PlaylistRepository import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageUseCase import com.kevinschildhorn.fotopresenter.extension.addPath @@ -26,10 +27,10 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.cancelChildren -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.last import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.plus @@ -39,6 +40,8 @@ import org.koin.core.component.KoinComponent class DirectoryViewModel( private val playlistRepository: PlaylistRepository, private val logger: Logger, + private val directoryRepository: DirectoryRepository, + private val directoryEtc:DirectoryEtc, ) : PlaylistViewModel(playlistRepository, logger), ImageViewModel by DefaultImageViewModel(logger), KoinComponent { @@ -49,7 +52,7 @@ class DirectoryViewModel( private val _uiState = MutableStateFlow(DirectoryScreenState()) val uiState: StateFlow = _uiState.asStateFlow() - private val _directoryContentsState = MutableStateFlow(DirectoryContents()) + private val _directoryContentsState = directoryEtc.directoryFlow // Indexes of all Downloaded images private val downloadedImageSet: MutableSet = mutableSetOf() @@ -75,7 +78,7 @@ class DirectoryViewModel( //region Connection fun setLoggedIn() { - _uiState.update { it.copy(loggedIn = true) } + //_uiState.update { it.copy(loggedIn = true) } } fun logout() { @@ -85,7 +88,7 @@ class DirectoryViewModel( val logoutUseCase = UseCaseFactory.disconnectFromServerUseCase logoutUseCase() logger.d { "Setting loggedIn state to false" } - _uiState.update { it.copy(loggedIn = false) } + //_uiState.update { it.copy(loggedIn = false) } } } @@ -99,13 +102,15 @@ class DirectoryViewModel( logger.d { "Checking for Selected Directory" } uiState.value.selectedDirectory?.id?.let { id -> logger.d { "Finding Folder" } - _directoryContentsState.value.folders.find { it.id == id }?.let { - logger.d { "Folder found, starting to retrieve images" } - slideshowScope.launch { - val retrieveImagesUseCase = UseCaseFactory.retrieveImageDirectoriesUseCase - val images = retrieveImagesUseCase(it.details) - logger.v { "Retrieved images, copying them to state" } - _uiState.update { it.copy(slideshowDetails = ImageSlideshowDetails(images)) } + viewModelScope.launch { + _directoryContentsState.last().folders.find { it.id == id }?.let { + logger.d { "Folder found, starting to retrieve images" } + slideshowScope.launch { + val retrieveImagesUseCase = UseCaseFactory.retrieveImageDirectoriesUseCase + val images = retrieveImagesUseCase(it.details) + logger.v { "Retrieved images, copying them to state" } + //_uiState.update { it.copy(slideshowDetails = ImageSlideshowDetails(images)) } + } } } } ?: run { @@ -114,7 +119,7 @@ class DirectoryViewModel( } fun clearSlideshow() { - _uiState.update { it.copy(slideshowDetails = null) } + //_uiState.update { it.copy(slideshowDetails = null) } } fun setSelectedImageById(imageId: Int?) { @@ -143,8 +148,10 @@ class DirectoryViewModel( } fun changeDirectory(id: Int) { - _directoryContentsState.value.allDirectories.find { it.id == id }?.let { - changeDirectoryToPath(currentPath.addPath(it.details.name)) + viewModelScope.launch { + _directoryContentsState.last().allDirectories.find { it.id == id }?.let { + changeDirectoryToPath(currentPath.addPath(it.details.name)) + } } } @@ -188,14 +195,23 @@ class DirectoryViewModel( logger.i { "Updating Directories" } _uiState.update { it.copy(state = UiState.LOADING) } viewModelScope.launch(Dispatchers.Default) { - val retrieveDirectoryUseCase = UseCaseFactory.retrieveDirectoryContentsUseCase + + // Use Pagination + // Get first ten images + //val retrieveDirectoryUseCase = UseCaseFactory.retrieveDirectoryContentsUseCase + viewModelScope.launch(Dispatchers.IO) { + + val directoryContents = directoryRepository.getDirectoryContents(currentPath) + //directoryEtc.todo(currentPath) + } + logger.i { "Getting Directory Contents" } - val directoryContents = retrieveDirectoryUseCase(currentPath) - logger.i { "Got Directory Contents: ${directoryContents.allDirectories.count()}" } - _directoryContentsState.update { directoryContents } + //val directoryContents = retrieveDirectoryUseCase(currentPath) + //logger.i { "Got Directory Contents: ${directoryContents.allDirectories.count()}" } + //_directoryContentsState.update { directoryContents } - updateGrid() + //updateGrid() logger.i { "Current State ${uiState.value.state}" } updatePhotos() } @@ -240,7 +256,7 @@ class DirectoryViewModel( // TODO: STORE LARGEST IMAGES IN CHUNKS } } - +/* private fun updateGrid() = with(_directoryContentsState.value) { logger.i { "Updating State to Success" } logger.i { "Setting Directories: $this" } @@ -253,7 +269,7 @@ class DirectoryViewModel( state = UiState.SUCCESS, ) } - } + }*/ private val DirectoryContents.asDirectoryGridState: DirectoryGridState get() = @@ -274,6 +290,7 @@ class DirectoryViewModel( //region Playlist fun addSelectedDirectoryToPlaylist(playlist: PlaylistDetails) { + /* uiState.value.selectedDirectory?.let { selectedDirectory -> with(_directoryContentsState.value) { logger.i { "Inserting Playlist Image ${playlist.id} as ${uiState.value.selectedDirectory}" } @@ -291,7 +308,7 @@ class DirectoryViewModel( } } ?: run { logger.w { "Selected Directory Not found" } - } + }*/ } //endregion @@ -306,10 +323,11 @@ class DirectoryViewModel( fun setFilterType(sortingType: SortingType) { logger.i { "Setting Filter Type" } + /* _directoryContentsState.update { it.sorted(sortingType) - } - updateGrid() + }*/ + //updateGrid() } private fun cancelJobs() { @@ -324,12 +342,12 @@ class DirectoryViewModel( private fun findSelectedFolderDirectory(): FolderDirectory? = uiState.value.selectedDirectory?.id?.let { id -> logger.d { "Finding Selected Directory" } - return _directoryContentsState.value.folders.find { it.id == id } + return null// _directoryContentsState.value.folders.find { it.id == id } } private fun findSelectedImageDirectory(): ImageDirectory? = uiState.value.selectedDirectory?.id?.let { id -> logger.d { "Finding Selected Directory" } - return _directoryContentsState.value.images.find { it.id == id } + return null//_directoryContentsState.value.images.find { it.id == id } } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModelTwo.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModelTwo.kt new file mode 100644 index 00000000..2206ff00 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModelTwo.kt @@ -0,0 +1,97 @@ +package com.kevinschildhorn.fotopresenter.ui.screens.directory + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import co.touchlab.kermit.Logger +import com.kevinschildhorn.fotopresenter.data.DirectoryEtc +import com.kevinschildhorn.fotopresenter.data.FolderDirectory +import com.kevinschildhorn.fotopresenter.data.ImageDirectory +import com.kevinschildhorn.fotopresenter.data.State +import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository +import com.kevinschildhorn.fotopresenter.data.repositories.PlaylistRepository +import com.kevinschildhorn.fotopresenter.ui.SortingType +import com.kevinschildhorn.fotopresenter.ui.UiState +import com.kevinschildhorn.fotopresenter.ui.screens.common.ScreenState +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch +import org.koin.core.component.KoinComponent +import kotlin.String + +data class DirectoryScreenStateTwo( + val currentPath: String = "", + val directoryGridState: DirectoryGridState = DirectoryGridState(emptyList(), mutableListOf()), + val selectedDirectory: DirectoryGridCellState? = null, + val currentImageCount: Int = 0, + val totalImageCount: Int = 0, + val sortingType: SortingType = SortingType.NAME_ASC, + override val state: UiState = UiState.IDLE, +) : ScreenState { + + val currentPathList: List + get() = currentPath.split("\\").filter { it.isNotEmpty() } +} + +class DirectoryViewModelTwo( + private val playlistRepository: PlaylistRepository, + private val logger: Logger, + private val directoryRepository: DirectoryRepository, + private val directoryEtc: DirectoryEtc, +) : ViewModel(), KoinComponent { + + private var currentPath: String = "" + + private val _directoryContentsState = directoryEtc.directoryFlow + val directoryGridStateFlow: Flow = + _directoryContentsState.map { directory -> + DirectoryGridState( + folderStates = directory.folders.map { it.asCellState }, + imageStates = directory.images.map { it.asCellState }, + ) + } + + private var selectedDirectory: DirectoryGridCellState? = null + private var sortingType: SortingType = SortingType.NAME_ASC + private var state: UiState = UiState.IDLE + + + val uiState: Flow = directoryGridStateFlow.map { + logger.v{ it.toString() } + DirectoryScreenStateTwo( + currentPath = currentPath, + directoryGridState = it, + selectedDirectory = selectedDirectory, + currentImageCount = 0, + totalImageCount = 0, + sortingType = sortingType, + state = UiState.SUCCESS, + ) + } + + fun refreshScreen(){ + if(state != UiState.LOADING) { + currentPath = "Camera Uploads/Camera" + updateDirectories() + } + } + + private fun updateDirectories() { + logger.i { "Updating Directories" } + state = UiState.LOADING + directoryEtc.refreshDirectories(currentPath, viewModelScope) + } + + private val FolderDirectory.asCellState: FolderDirectoryGridCellState + get() = FolderDirectoryGridCellState(name = name, id = id) + + private val ImageDirectory.asCellState: ImageDirectoryGridCellState + get() { + val imageState = when{ + (imageBitmap != null) -> State.SUCCESS(imageBitmap) + image != null -> State.ERROR("") + else -> State.IDLE + } + return ImageDirectoryGridCellState(imageState = imageState, name = name, id = id) + } +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index 14dd76ef..e645707a 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -3,6 +3,7 @@ package com.kevinschildhorn.fotopresenter.ui.shared import androidx.compose.ui.graphics.ImageBitmap expect class SharedImage { - fun getImageBitmap(size: Int): ImageBitmap? val byteArray: ByteArray + fun getImageBitmap(size: Int): ImageBitmap? + fun close() } diff --git a/shared/src/desktopMain/kotlin/Main.desktop.kt b/shared/src/desktopMain/kotlin/Main.desktop.kt index 868146ed..8d84ac39 100644 --- a/shared/src/desktopMain/kotlin/Main.desktop.kt +++ b/shared/src/desktopMain/kotlin/Main.desktop.kt @@ -1,5 +1,6 @@ import androidx.compose.runtime.Composable import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -9,7 +10,7 @@ actual fun getPlatformName(): String = "Desktop" @Composable fun MainView( loginViewModel: LoginViewModel, - directoryViewModel: DirectoryViewModel, + directoryViewModel: DirectoryViewModelTwo, slideshowViewModel: SlideshowViewModel, playlistViewModel: PlaylistViewModel, ) = App(loginViewModel, directoryViewModel, slideshowViewModel, playlistViewModel) diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt index 460b0abf..dff24c4a 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt @@ -2,6 +2,7 @@ package com.kevinschildhorn.fotopresenter import co.touchlab.kermit.Logger import co.touchlab.kermit.LoggerConfig +import com.kevinschildhorn.fotopresenter.data.DirectoryEtc import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource @@ -46,12 +47,15 @@ actual object UseCaseFactory { networkHandler = networkHandler, logger = baseLogger.withTag("imageMetadataDataSource") ) - private val directoryRepository = DirectoryRepository(directoryDataSource, imageMetadataDataSource) + val directoryRepository = DirectoryRepository(directoryDataSource, imageMetadataDataSource) + private val imageRepository = ImageRepository(ImageRemoteDataSource(networkHandler)) private val playlistSQLDataSource = PlaylistSQLDataSource( sqlDriver, com.kevinschildhorn.fotopresenter.baseLogger ) + val directoryEtc = DirectoryEtc(imageRepository, directoryRepository, baseLogger) + private val playlistFileDataSource = PlaylistFileDataSource( baseLogger.withTag("playlistFileDataSource"), diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index feda2259..022ad298 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -3,7 +3,8 @@ package com.kevinschildhorn.fotopresenter.ui.shared import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.res.loadImageBitmap import com.hierynomus.smbj.share.File +import java.io.InputStream -actual fun getBitmapFromFile(file: File, size:Int): ImageBitmap? = - file.inputStream.buffered().use(::loadImageBitmap) +actual fun getBitmapFromFile(inputStream: InputStream, size:Int): ImageBitmap? = + inputStream.buffered().use(::loadImageBitmap) diff --git a/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index 744138ab..16f0f21a 100644 --- a/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -3,6 +3,7 @@ package com.kevinschildhorn.fotopresenter.ui import androidx.compose.ui.graphics.ImageBitmap actual class SharedImage { - actual fun getImageBitmap(size:Int): ImageBitmap? = null actual val byteArray: ByteArray = ByteArray() + actual fun getImageBitmap(size:Int): ImageBitmap? = null + actual fun close() {} } diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt index 63033d22..8aad463e 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt @@ -63,6 +63,7 @@ object SMBJHandler : NetworkHandler { } } catch (e: Exception) { logger.e(e) { "Failed To Connect" } + logger.e(e.localizedMessage) disconnect() return false } @@ -107,7 +108,7 @@ object SMBJHandler : NetworkHandler { override suspend fun openImage(path: String): SharedImage? = getFile(path)?.let { val sharedImage = SharedImage(it) - it.close() + //it.close() TODO sharedImage } ?: run { null } diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index 2a95e3f1..5a7c7d03 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -4,8 +4,11 @@ import androidx.compose.ui.graphics.ImageBitmap import com.hierynomus.smbj.share.File actual open class SharedImage(val file: File) { - actual fun getImageBitmap(size: Int): ImageBitmap? = getBitmapFromFile(file, size) actual val byteArray: ByteArray = file.inputStream.readAllBytes() + actual fun getImageBitmap(size: Int): ImageBitmap? = getBitmapFromFile(file, size) + actual fun close(){ + file.close() + } } expect fun getBitmapFromFile(file: File, size: Int): ImageBitmap? From e48b40535aeb15f53ea36600e24473e89ab4c38b Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Fri, 11 Oct 2024 13:23:51 -0400 Subject: [PATCH 07/19] updating to use coil --- androidApp/build.gradle.kts | 2 + .../com/kevinschildhorn/MainActivity.kt | 13 +++- gradle/libs.versions.toml | 2 + shared/build.gradle.kts | 2 + .../fotopresenter/SMBJFetcher.kt | 73 +++++++++++++++++++ .../data/repositories/DirectoryRepository.kt | 4 +- .../ui/screens/directory/DirectoryScreen.kt | 8 +- .../screens/directory/DirectoryViewModel.kt | 42 +++-------- .../grid/ImageDirectoryGridCell.kt | 8 +- .../fotopresenter/data/network/SMBJHandler.kt | 1 - 10 files changed, 115 insertions(+), 40 deletions(-) create mode 100644 shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index d536b274..1d80406e 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -1,4 +1,5 @@ import org.gradle.kotlin.dsl.get +import org.gradle.kotlin.dsl.implementation import org.gradle.kotlin.dsl.java plugins { @@ -18,6 +19,7 @@ kotlin { implementation(project(":shared")) implementation(libs.koin.android) implementation(libs.firebase.crashlytics) + implementation(libs.coil) } } } diff --git a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt index b9d912e0..3a42c8ea 100644 --- a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt +++ b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt @@ -4,6 +4,9 @@ import MainView import android.os.Bundle import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity +import coil3.ImageLoader +import coil3.compose.setSingletonImageLoaderFactory +import com.kevinschildhorn.fotopresenter.SMBJFetcher import com.kevinschildhorn.fotopresenter.startKoin import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel @@ -22,8 +25,16 @@ class MainActivity : AppCompatActivity(), KoinComponent { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) startKoin(this) - + setContent { + setSingletonImageLoaderFactory { context -> + ImageLoader.Builder(context) + .components { + add(SMBJFetcher.Factory()) + } + .build() + } + MainView(loginViewModel, directoryViewModel, slideshowViewModel, playlistViewModel) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a7874c79..1f474617 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,6 +4,7 @@ agp = "8.5.2" appcompat = "1.7.0" atomik = "0.0.6" cache4k = "0.12.0" +coil = "3.0.0-rc01" core-ktx = "1.13.1" eva-icons = "1.1.0" firebase-crashlytics = "19.2.0" @@ -48,6 +49,7 @@ firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics", ve kermit = { module = "co.touchlab:kermit", version.ref = "kermit" } kermit-koin = { module = "co.touchlab:kermit-koin", version.ref = "kermit-koin" } kim = { module = "com.ashampoo:kim", version.ref = "kim" } +coil = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" } koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin-core" } koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin-core" } koin-test = { module = "io.insert-koin:koin-test", version.ref = "koin-test" } diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index dd964183..c5e78e59 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -52,6 +52,8 @@ kotlin { implementation(libs.multiplatform.settings) implementation(libs.kotlinx.datetime) implementation(libs.kim) + implementation(libs.coil) + } } val commonTest by getting { diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt new file mode 100644 index 00000000..20242768 --- /dev/null +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt @@ -0,0 +1,73 @@ +package com.kevinschildhorn.fotopresenter + +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import coil3.ImageLoader +import coil3.asImage +import coil3.decode.DataSource +import coil3.fetch.FetchResult +import coil3.fetch.Fetcher +import coil3.fetch.ImageFetchResult +import coil3.request.Options +import com.hierynomus.smbj.share.File +import com.kevinschildhorn.fotopresenter.data.network.SMBJHandler +import com.kevinschildhorn.fotopresenter.ui.screens.directory.PhotoData +import com.kevinschildhorn.fotopresenter.ui.shared.getScaledDimensions +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class SMBJFetcher( + private val photoData: PhotoData, +) : Fetcher { + + override suspend fun fetch(): FetchResult? { + return withContext(Dispatchers.IO) { + if (SMBJHandler.isConnected) { + val image = SMBJHandler.openImage(path = photoData.path) + val file = image?.file + if(file != null) { + val bitmap = getBitmapFromFile(file, 256) + if (bitmap != null) { + file.close() + ImageFetchResult( + image = bitmap.asImage(), + isSampled = true, + dataSource = DataSource.NETWORK, + ) + } else { + throw Exception("Failed to fetch image from FTP") + } + } else { + throw Exception("Failed to fetch image from FTP") + } + } else { + throw Exception("Failed to fetch image from FTP") + } + } + } + + private fun getBitmapFromFile(file: File, size: Int): Bitmap? { + + val options = BitmapFactory.Options() + options.inJustDecodeBounds = true + BitmapFactory.decodeStream(file.inputStream, null, options) + + val height: Int = options.outHeight + val width: Int = options.outWidth + val dimensions = getScaledDimensions(width, height, size) + val heightRatio: Int = Math.round(height.toFloat() / dimensions.second.toFloat()) + val widthRatio: Int = Math.round(width.toFloat() / dimensions.first.toFloat()) + options.inSampleSize = if (heightRatio < widthRatio) heightRatio else widthRatio + + options.inJustDecodeBounds = false + return BitmapFactory.decodeStream(file.inputStream, null, options) + } + + class Factory() : Fetcher.Factory { + override fun create( + data: PhotoData, + options: Options, + imageLoader: ImageLoader + ): Fetcher? = SMBJFetcher(data) + } +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt index 7bf66afa..e4aea211 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt @@ -18,7 +18,7 @@ class DirectoryRepository( val imageDirectories: List = directoryDataSource.getImageDirectories(path) - val metaData = metadataDataSource.importMetaData() + //val metaData = metadataDataSource.importMetaData() return DirectoryContents( @@ -26,7 +26,7 @@ class DirectoryRepository( images = imageDirectories.map { networkDetails -> ImageDirectory( networkDetails, - metaData = metaData.files.find { networkDetails.fullPath == it.filePath } + metaData = null,// metaData.files.find { networkDetails.fullPath == it.filePath } ) }, ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt index ab3ee5a1..40380317 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt @@ -69,10 +69,10 @@ fun DirectoryScreen( var overlayVisible by remember { mutableStateOf(DirectoryOverlay.NONE) } // Navigation - if (!uiState.loggedIn) onLogout() - uiState.slideshowDetails?.let { - onStartSlideshow(it) - } + //if (!uiState.loggedIn) onLogout() + //uiState.slideshowDetails?.let { + // onStartSlideshow(it) + //} //region UI Column { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt index 4be35edf..491862a5 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt @@ -75,7 +75,7 @@ class DirectoryViewModel( //region Connection fun setLoggedIn() { - _uiState.update { it.copy(loggedIn = true) } + //_uiState.update { it.copy(loggedIn = true) } } fun logout() { @@ -85,7 +85,7 @@ class DirectoryViewModel( val logoutUseCase = UseCaseFactory.disconnectFromServerUseCase logoutUseCase() logger.d { "Setting loggedIn state to false" } - _uiState.update { it.copy(loggedIn = false) } + //_uiState.update { it.copy(loggedIn = false) } } } @@ -105,7 +105,7 @@ class DirectoryViewModel( val retrieveImagesUseCase = UseCaseFactory.retrieveImageDirectoriesUseCase val images = retrieveImagesUseCase(it.details) logger.v { "Retrieved images, copying them to state" } - _uiState.update { it.copy(slideshowDetails = ImageSlideshowDetails(images)) } + //_uiState.update { it.copy(slideshowDetails = ImageSlideshowDetails(images)) } } } } ?: run { @@ -114,7 +114,7 @@ class DirectoryViewModel( } fun clearSlideshow() { - _uiState.update { it.copy(slideshowDetails = null) } + // _uiState.update { it.copy(slideshowDetails = null) } } fun setSelectedImageById(imageId: Int?) { @@ -208,35 +208,17 @@ class DirectoryViewModel( imageScope.launch { val startTime = Clock.System.now().toEpochMilliseconds() logger.i { "Updating Photos" } - val retrieveImagesUseCase: RetrieveImageUseCase = UseCaseFactory.retrieveImageUseCase val imageDirectories: List = imageUiState.value.imageDirectories imageDirectories.mapIndexed { index, imageDirectory -> - async { - retrieveImagesUseCase( - imageDirectory, - imageSize = 512, // TODO: Change - )?.let { newImage -> - logger.i { "Downloaded Image at index $index" } - downloadedImageSet.add(index) - - _uiState.update { - it.copyImageState( - imageDirectory.id, - state = State.SUCCESS(newImage), - ).copy( - currentImageCount = downloadedImageSet.size - ) - } - - if (_uiState.value.currentImageCount == _uiState.value.totalImageCount) { - val endTime = Clock.System.now().toEpochMilliseconds() - val difference: Float = (endTime.toFloat() - startTime.toFloat()) / 1000 - logger.i { "Downloading all images took $difference seconds" } - } - } + _uiState.update { + it.copyImageState( + imageDirectory.id, + state = State.SUCCESS(PhotoData(imageDirectory.details.fullPath)), + ).copy( + currentImageCount = downloadedImageSet.size + ) } - }.awaitAll() - + } // TODO: STORE LARGEST IMAGES IN CHUNKS } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/ImageDirectoryGridCell.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/ImageDirectoryGridCell.kt index 5b1fc4f2..ab3b6b0a 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/ImageDirectoryGridCell.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/ImageDirectoryGridCell.kt @@ -12,6 +12,9 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.dp +import coil3.compose.AsyncImage +import coil3.compose.LocalPlatformContext +import coil3.request.ImageRequest import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors import com.kevinschildhorn.fotopresenter.ui.screens.directory.ImageDirectoryGridCellState import compose.icons.EvaIcons @@ -23,10 +26,11 @@ fun ImageDirectoryGridCell( imageContent: ImageDirectoryGridCellState, modifier: Modifier = Modifier, ) { + DirectoryGridCell(modifier) { imageContent.imageState.onSuccess { - Image( - bitmap = it, + AsyncImage( + model = it, contentDescription = imageContent.name, contentScale = ContentScale.Crop, modifier = Modifier.fillMaxSize().background(fotoColors.surface), diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt index 63033d22..9f7aa7c0 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt @@ -107,7 +107,6 @@ object SMBJHandler : NetworkHandler { override suspend fun openImage(path: String): SharedImage? = getFile(path)?.let { val sharedImage = SharedImage(it) - it.close() sharedImage } ?: run { null } From 9356282646cb2c0e6e02973415c8cd1b192ec252 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Fri, 11 Oct 2024 13:26:21 -0400 Subject: [PATCH 08/19] cleaning up --- .../ui/screens/directory/DirectoryViewModel.kt | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt index 491862a5..42209d32 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt @@ -6,13 +6,11 @@ import com.kevinschildhorn.fotopresenter.data.Directory import com.kevinschildhorn.fotopresenter.data.DirectoryContents import com.kevinschildhorn.fotopresenter.data.FolderDirectory import com.kevinschildhorn.fotopresenter.data.ImageDirectory -import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails import com.kevinschildhorn.fotopresenter.data.MetadataFileDetails import com.kevinschildhorn.fotopresenter.data.PlaylistDetails import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException import com.kevinschildhorn.fotopresenter.data.repositories.PlaylistRepository -import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageUseCase import com.kevinschildhorn.fotopresenter.extension.addPath import com.kevinschildhorn.fotopresenter.extension.navigateBackToPathAtIndex import com.kevinschildhorn.fotopresenter.ui.SortingType @@ -23,10 +21,7 @@ import com.kevinschildhorn.fotopresenter.ui.screens.common.ImageViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll import kotlinx.coroutines.cancelChildren -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -37,7 +32,7 @@ import kotlinx.datetime.Clock import org.koin.core.component.KoinComponent class DirectoryViewModel( - private val playlistRepository: PlaylistRepository, + playlistRepository: PlaylistRepository, private val logger: Logger, ) : PlaylistViewModel(playlistRepository, logger), ImageViewModel by DefaultImageViewModel(logger), @@ -60,7 +55,6 @@ class DirectoryViewModel( val actionSheetContexts: List get() = uiState.value.selectedDirectory?.actionSheetContexts ?: emptyList() - val selectedMetadata: MetadataFileDetails? get() = findSelectedImageDirectory()?.metaData @@ -114,7 +108,7 @@ class DirectoryViewModel( } fun clearSlideshow() { - // _uiState.update { it.copy(slideshowDetails = null) } + // _uiState.update { it.copy(slideshowDetails = null) } } fun setSelectedImageById(imageId: Int?) { From b8e51af5c47f59e1920c33c3a83c688837e44216 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Fri, 11 Oct 2024 13:26:46 -0400 Subject: [PATCH 09/19] Revert "adding temp code" This reverts commit 933fe8c590da7ef05b46bf7005faa95720c0a2a8. --- .../com/kevinschildhorn/MainActivity.kt | 3 +- desktopApp/src/jvmMain/kotlin/Main.kt | 17 +--- shared/src/androidMain/kotlin/Main.android.kt | 3 +- shared/src/commonMain/kotlin/App.kt | 5 +- .../com/kevinschildhorn/fotopresenter/Koin.kt | 7 +- .../fotopresenter/data/Directory.kt | 2 - .../fotopresenter/data/DirectoryEtc.kt | 82 ---------------- .../data/repositories/DirectoryRepository.kt | 7 +- .../data/repositories/ImageRepository.kt | 1 - .../domain/image/RetrieveImageUseCase.kt | 2 +- .../ui/screens/directory/DirectoryScreen.kt | 43 ++++---- .../screens/directory/DirectoryViewModel.kt | 72 ++++++-------- .../directory/DirectoryViewModelTwo.kt | 97 ------------------- .../fotopresenter/ui/shared/SharedImage.kt | 3 +- shared/src/desktopMain/kotlin/Main.desktop.kt | 3 +- .../fotopresenter/UseCaseFactoryDesktop.kt | 6 +- .../fotopresenter/ui/shared/SharedImage.kt | 5 +- .../fotopresenter/ui/shared/SharedImage.kt | 3 +- .../fotopresenter/data/network/SMBJHandler.kt | 3 +- .../fotopresenter/ui/shared/SharedImage.kt | 5 +- 20 files changed, 65 insertions(+), 304 deletions(-) delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryEtc.kt delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModelTwo.kt diff --git a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt index 35c02d18..b9d912e0 100644 --- a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt +++ b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt @@ -6,7 +6,6 @@ import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import com.kevinschildhorn.fotopresenter.startKoin import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -16,7 +15,7 @@ import org.koin.core.component.KoinComponent class MainActivity : AppCompatActivity(), KoinComponent { private val loginViewModel by viewModel() - private val directoryViewModel by viewModel() + private val directoryViewModel by viewModel() private val slideshowViewModel by viewModel() private val playlistViewModel by viewModel() diff --git a/desktopApp/src/jvmMain/kotlin/Main.kt b/desktopApp/src/jvmMain/kotlin/Main.kt index 7c563025..44a8bfbf 100644 --- a/desktopApp/src/jvmMain/kotlin/Main.kt +++ b/desktopApp/src/jvmMain/kotlin/Main.kt @@ -3,7 +3,6 @@ import androidx.compose.ui.window.application import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.UseCaseFactory import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -13,19 +12,7 @@ object KoinPurse { val loginViewModel = LoginViewModel(Logger.withTag("LoginViewModel"), UseCaseFactory.credentialsRepository) val directoryViewModel = - DirectoryViewModel( - UseCaseFactory.playlistRepository, - Logger.withTag("DirectoryViewModel"), - UseCaseFactory.directoryRepository, - UseCaseFactory.directoryEtc, - ) - val directoryViewModelTwo = - DirectoryViewModelTwo( - UseCaseFactory.playlistRepository, - Logger.withTag("DirectoryViewModel"), - UseCaseFactory.directoryRepository, - UseCaseFactory.directoryEtc, - ) + DirectoryViewModel(UseCaseFactory.playlistRepository, Logger.withTag("DirectoryViewModel")) val slideshowViewModel = SlideshowViewModel(Logger.withTag("SlideshowViewModel")) val playlistViewModel = PlaylistViewModel(UseCaseFactory.playlistRepository, Logger.withTag("PlaylistViewModel")) @@ -38,7 +25,7 @@ fun main() = application { ) { MainView( KoinPurse.loginViewModel, - KoinPurse.directoryViewModelTwo, + KoinPurse.directoryViewModel, KoinPurse.slideshowViewModel, KoinPurse.playlistViewModel, ) diff --git a/shared/src/androidMain/kotlin/Main.android.kt b/shared/src/androidMain/kotlin/Main.android.kt index 758a5f37..fd25cda6 100644 --- a/shared/src/androidMain/kotlin/Main.android.kt +++ b/shared/src/androidMain/kotlin/Main.android.kt @@ -1,6 +1,5 @@ import androidx.compose.runtime.Composable import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -10,7 +9,7 @@ actual fun getPlatformName(): String = "Android" @Composable fun MainView( loginViewModel: LoginViewModel, - directoryViewModel: DirectoryViewModelTwo, + directoryViewModel: DirectoryViewModel, slideshowViewModel: SlideshowViewModel, playlistViewModel: PlaylistViewModel, ) = App(loginViewModel, directoryViewModel, slideshowViewModel, playlistViewModel) diff --git a/shared/src/commonMain/kotlin/App.kt b/shared/src/commonMain/kotlin/App.kt index a38533f0..e0d2632c 100644 --- a/shared/src/commonMain/kotlin/App.kt +++ b/shared/src/commonMain/kotlin/App.kt @@ -14,7 +14,6 @@ import com.kevinschildhorn.fotopresenter.ui.atoms.fotoShapes import com.kevinschildhorn.fotopresenter.ui.screens.common.Screen import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryScreen import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreen import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistScreen @@ -26,7 +25,7 @@ import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @Composable fun App( loginViewModel: LoginViewModel, - directoryViewModel: DirectoryViewModelTwo, + directoryViewModel: DirectoryViewModel, slideshowViewModel: SlideshowViewModel, playlistViewModel: PlaylistViewModel, navController: NavHostController = rememberNavController() @@ -57,7 +56,7 @@ fun App( }, onStartSlideshow = { slideshowViewModel.setSlideshow(it) - //directoryViewModel.clearSlideshow() + directoryViewModel.clearSlideshow() navController.navigate(Screen.SLIDESHOW.name) }, onShowPlaylists = { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt index f1a6ab74..27543619 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt @@ -2,7 +2,6 @@ package com.kevinschildhorn.fotopresenter import co.touchlab.kermit.Logger import co.touchlab.kermit.LoggerConfig -import com.kevinschildhorn.fotopresenter.data.DirectoryEtc import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource @@ -25,7 +24,6 @@ import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageUseCase import com.kevinschildhorn.fotopresenter.domain.image.RetrieveSlideshowFromPlaylistUseCase import com.kevinschildhorn.fotopresenter.domain.image.SaveMetadataForPathUseCase import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -47,8 +45,6 @@ val commonModule = single { CredentialsRepository(get()) } single { DirectoryDataSource(get(), baseLogger.withTag("DirectoryDataSource")) } single { DirectoryRepository(get(), get()) } - single { DirectoryEtc(get(), get(), baseLogger.withTag("DirectoryEtc")) } - single { ImageRemoteDataSource(get()) } single { ImageRepository(get()) } single { ImageCacheDataSource(get(), get(), baseLogger.withTag("ImageCacheDataSource")) } @@ -87,8 +83,7 @@ val commonModule = factory { SaveMetadataForPathUseCase(get()) } // UI single { LoginViewModel(baseLogger.withTag("LoginViewModel"), get()) } - single { DirectoryViewModel(get(), baseLogger.withTag("DirectoryViewModel"), get(), get()) } - single { DirectoryViewModelTwo(get(), baseLogger.withTag("DirectoryViewModel"), get(), get())} + single { DirectoryViewModel(get(), baseLogger.withTag("DirectoryViewModel")) } single { SlideshowViewModel(baseLogger.withTag("SlideshowViewModel")) } single { PlaylistViewModel(get(), baseLogger.withTag("PlaylistViewModel")) } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt index 94a1a95d..f663b314 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt @@ -1,6 +1,5 @@ package com.kevinschildhorn.fotopresenter.data -import androidx.compose.ui.graphics.ImageBitmap import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.ui.SortingType import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage @@ -30,7 +29,6 @@ data class ImageDirectory( override val details: NetworkDirectoryDetails, val metaData: MetadataFileDetails?, val image: SharedImage? = null, - val imageBitmap: ImageBitmap? = null, ) : Directory { override fun toString(): String = "(I:${details.fullPath}:${details.id})" } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryEtc.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryEtc.kt deleted file mode 100644 index 22806af3..00000000 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryEtc.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.kevinschildhorn.fotopresenter.data - -import co.touchlab.kermit.Logger -import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository -import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withContext - -class DirectoryEtc( - private val imageRepository: ImageRepository, - private val directoryRepository: DirectoryRepository, - private val logger: Logger, -) { - - private val _directoryContentsFlow = MutableStateFlow(DirectoryContents()) - private val _imageDirectoryList = MutableStateFlow>(emptyList()) - - val directoryFlow: Flow = - combine(_directoryContentsFlow, _imageDirectoryList) { directory, images -> - directory.copy(images = images) - } - - fun refreshDirectories(path: String, coroutineScope: CoroutineScope) { - coroutineScope.launch(Dispatchers.Default) { - // Retrieve File Data - var directoryContents = directoryRepository.getDirectoryContents(path) - _directoryContentsFlow.emit(directoryContents) - _imageDirectoryList.emit(directoryContents.images) - - // For each image, get the Byte Array - val images = directoryContents - .images - //.take(10) - .toMutableList() - - images.chunked(10).forEach { imageChunk -> - logger.i("Starting Jobs!") - runBlocking { - imageChunk.forEachIndexed { index, image -> - coroutineScope.launch { - processItemAsync(index, image) - } - } - } - logger.i("Joined!") - } - - logger.i { "Finished!" } - } - } - - suspend fun processItemAsync( - index: Int, - item: ImageDirectory, - ) { - var mutableItemDirectory = item - val itemWithBytes = withContext(Dispatchers.IO) { - val sharedImage = imageRepository.getImage(item.details) - mutableItemDirectory.copy(image = sharedImage) - } - updateImageList(index, itemWithBytes) - val itemWithBitmap = withContext(Dispatchers.IO) { - val bitmap = itemWithBytes.image?.getImageBitmap(256) - itemWithBytes.copy(imageBitmap = bitmap) - } - updateImageList(index, itemWithBitmap) - item.image?.close() - } - - private fun updateImageList(index: Int, item: ImageDirectory) { - val items = _imageDirectoryList.value.toMutableList() - items[index] = item - _imageDirectoryList.update { items } - } -} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt index 52265801..7bf66afa 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt @@ -12,22 +12,21 @@ class DirectoryRepository( private val directoryDataSource: DirectoryDataSource, private val metadataDataSource: ImageMetadataDataSource, ) { - // Retrieves [NetworkDirectoryDetails] for folders and directories. Contains no bitmap data suspend fun getDirectoryContents(path: String): DirectoryContents { val folderDirectories: List = directoryDataSource.getFolderDirectories(path) val imageDirectories: List = directoryDataSource.getImageDirectories(path) - //val metaData = metadataDataSource.importMetaData() + val metaData = metadataDataSource.importMetaData() + return DirectoryContents( folders = folderDirectories.map { FolderDirectory(it) }, images = imageDirectories.map { networkDetails -> ImageDirectory( networkDetails, - metaData = null, //metaData.files.find { networkDetails.fullPath == it.filePath } - image = null, + metaData = metaData.files.find { networkDetails.fullPath == it.filePath } ) }, ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt index df91ac04..ddbc81b9 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt @@ -7,6 +7,5 @@ import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage class ImageRepository( private val remoteDataSource: ImageRemoteDataSource, ) { - // Gets Image ByteArray from a Remote Data Source suspend fun getImage(directory: NetworkDirectoryDetails): SharedImage? = remoteDataSource.getImage(directory) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt index dc9bd540..cc2efaa8 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt @@ -14,7 +14,7 @@ class RetrieveImageUseCase( private val logger: Logger, ) { - operator fun invoke( + suspend operator fun invoke( directory: ImageDirectory, imageSize: Int, ): ImageBitmap? { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt index a173e716..ab3ee5a1 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt @@ -20,7 +20,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import com.kevinschildhorn.fotopresenter.baseLogger import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails import com.kevinschildhorn.fotopresenter.ui.UiState import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography @@ -57,24 +56,23 @@ enum class DirectoryOverlay { @Composable fun DirectoryScreen( - viewModel: DirectoryViewModelTwo, + viewModel: DirectoryViewModel, onLogout: () -> Unit, onStartSlideshow: (ImageSlideshowDetails) -> Unit, onShowPlaylists: () -> Unit, ) { LaunchedEffect(Unit) { - baseLogger.i { "Launched Effect" } viewModel.refreshScreen() } - val uiState by viewModel.uiState.collectAsState(DirectoryScreenStateTwo()) - //val imageUiState by viewModel.imageUiState.collectAsState() + val uiState by viewModel.uiState.collectAsState() + val imageUiState by viewModel.imageUiState.collectAsState() var overlayVisible by remember { mutableStateOf(DirectoryOverlay.NONE) } // Navigation - //if (!uiState.loggedIn) onLogout() - //uiState.slideshowDetails?.let { - // onStartSlideshow(it) - //} + if (!uiState.loggedIn) onLogout() + uiState.slideshowDetails?.let { + onStartSlideshow(it) + } //region UI Column { @@ -99,14 +97,13 @@ fun DirectoryScreen( DirectoryNavigationBar( directories = uiState.currentPathList, onHome = { - //viewModel.navigateToFolder(-1) + viewModel.navigateToFolder(-1) }, onItem = { - //viewModel.navigateToFolder(it) + viewModel.navigateToFolder(it) }, modifier = Modifier.padding(Padding.SMALL.dp) ) - /* if (uiState.imageCountString.isNotEmpty()) { Text( uiState.imageCountString, @@ -124,18 +121,18 @@ fun DirectoryScreen( color = fotoColors.primary, ) - }*/ + } DirectoryGrid( uiState.directoryGridState, onFolderPressed = { - //viewModel.changeDirectory(it) + viewModel.changeDirectory(it) }, onImageDirectoryPressed = { - //viewModel.setSelectedImageById(it) + viewModel.setSelectedImageById(it) overlayVisible = DirectoryOverlay.IMAGE }, onActionSheet = { - //viewModel.setSelectedDirectory(it) + viewModel.setSelectedDirectory(it) overlayVisible = DirectoryOverlay.ACTION_SHEET }, ) @@ -145,7 +142,6 @@ fun DirectoryScreen( // Overlays //region ActionSheet - /* ActionSheet( visible = overlayVisible == DirectoryOverlay.ACTION_SHEET, offset = 200, @@ -177,9 +173,9 @@ fun DirectoryScreen( overlayVisible = DirectoryOverlay.NONE viewModel.setSelectedDirectory(null) }, - )*/ + ) //endregion -/* + //region Selected Image imageUiState.selectedImage?.let { ImagePreviewOverlay( @@ -196,7 +192,7 @@ fun DirectoryScreen( viewModel.showNextImage() }, ) - }*/ + } //endregion //region Loading @@ -227,7 +223,7 @@ fun DirectoryScreen( overlayVisible = DirectoryOverlay.NONE }, onConfirmation = { - //viewModel.logout() + viewModel.logout() overlayVisible = DirectoryOverlay.NONE }, ) @@ -241,13 +237,12 @@ fun DirectoryScreen( overlayVisible = DirectoryOverlay.NONE }, onConfirmation = { - //viewModel.setFilterType(it) + viewModel.setFilterType(it) } ) } //region Playlist - /* if (overlayVisible == DirectoryOverlay.PLAYLIST) { PlaylistScreen( viewModel, @@ -274,5 +269,5 @@ fun DirectoryScreen( viewModel.setSelectedDirectory(null) overlayVisible = DirectoryOverlay.NONE }) - }*/ + } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt index 828d31b8..4be35edf 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt @@ -4,14 +4,13 @@ import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.UseCaseFactory import com.kevinschildhorn.fotopresenter.data.Directory import com.kevinschildhorn.fotopresenter.data.DirectoryContents -import com.kevinschildhorn.fotopresenter.data.DirectoryEtc import com.kevinschildhorn.fotopresenter.data.FolderDirectory import com.kevinschildhorn.fotopresenter.data.ImageDirectory +import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails import com.kevinschildhorn.fotopresenter.data.MetadataFileDetails import com.kevinschildhorn.fotopresenter.data.PlaylistDetails import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException -import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository import com.kevinschildhorn.fotopresenter.data.repositories.PlaylistRepository import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageUseCase import com.kevinschildhorn.fotopresenter.extension.addPath @@ -27,10 +26,10 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.cancelChildren +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.last import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.plus @@ -40,8 +39,6 @@ import org.koin.core.component.KoinComponent class DirectoryViewModel( private val playlistRepository: PlaylistRepository, private val logger: Logger, - private val directoryRepository: DirectoryRepository, - private val directoryEtc:DirectoryEtc, ) : PlaylistViewModel(playlistRepository, logger), ImageViewModel by DefaultImageViewModel(logger), KoinComponent { @@ -52,7 +49,7 @@ class DirectoryViewModel( private val _uiState = MutableStateFlow(DirectoryScreenState()) val uiState: StateFlow = _uiState.asStateFlow() - private val _directoryContentsState = directoryEtc.directoryFlow + private val _directoryContentsState = MutableStateFlow(DirectoryContents()) // Indexes of all Downloaded images private val downloadedImageSet: MutableSet = mutableSetOf() @@ -78,7 +75,7 @@ class DirectoryViewModel( //region Connection fun setLoggedIn() { - //_uiState.update { it.copy(loggedIn = true) } + _uiState.update { it.copy(loggedIn = true) } } fun logout() { @@ -88,7 +85,7 @@ class DirectoryViewModel( val logoutUseCase = UseCaseFactory.disconnectFromServerUseCase logoutUseCase() logger.d { "Setting loggedIn state to false" } - //_uiState.update { it.copy(loggedIn = false) } + _uiState.update { it.copy(loggedIn = false) } } } @@ -102,15 +99,13 @@ class DirectoryViewModel( logger.d { "Checking for Selected Directory" } uiState.value.selectedDirectory?.id?.let { id -> logger.d { "Finding Folder" } - viewModelScope.launch { - _directoryContentsState.last().folders.find { it.id == id }?.let { - logger.d { "Folder found, starting to retrieve images" } - slideshowScope.launch { - val retrieveImagesUseCase = UseCaseFactory.retrieveImageDirectoriesUseCase - val images = retrieveImagesUseCase(it.details) - logger.v { "Retrieved images, copying them to state" } - //_uiState.update { it.copy(slideshowDetails = ImageSlideshowDetails(images)) } - } + _directoryContentsState.value.folders.find { it.id == id }?.let { + logger.d { "Folder found, starting to retrieve images" } + slideshowScope.launch { + val retrieveImagesUseCase = UseCaseFactory.retrieveImageDirectoriesUseCase + val images = retrieveImagesUseCase(it.details) + logger.v { "Retrieved images, copying them to state" } + _uiState.update { it.copy(slideshowDetails = ImageSlideshowDetails(images)) } } } } ?: run { @@ -119,7 +114,7 @@ class DirectoryViewModel( } fun clearSlideshow() { - //_uiState.update { it.copy(slideshowDetails = null) } + _uiState.update { it.copy(slideshowDetails = null) } } fun setSelectedImageById(imageId: Int?) { @@ -148,10 +143,8 @@ class DirectoryViewModel( } fun changeDirectory(id: Int) { - viewModelScope.launch { - _directoryContentsState.last().allDirectories.find { it.id == id }?.let { - changeDirectoryToPath(currentPath.addPath(it.details.name)) - } + _directoryContentsState.value.allDirectories.find { it.id == id }?.let { + changeDirectoryToPath(currentPath.addPath(it.details.name)) } } @@ -195,23 +188,14 @@ class DirectoryViewModel( logger.i { "Updating Directories" } _uiState.update { it.copy(state = UiState.LOADING) } viewModelScope.launch(Dispatchers.Default) { - - // Use Pagination - // Get first ten images - //val retrieveDirectoryUseCase = UseCaseFactory.retrieveDirectoryContentsUseCase - viewModelScope.launch(Dispatchers.IO) { - - val directoryContents = directoryRepository.getDirectoryContents(currentPath) - //directoryEtc.todo(currentPath) - } - + val retrieveDirectoryUseCase = UseCaseFactory.retrieveDirectoryContentsUseCase logger.i { "Getting Directory Contents" } - //val directoryContents = retrieveDirectoryUseCase(currentPath) - //logger.i { "Got Directory Contents: ${directoryContents.allDirectories.count()}" } - //_directoryContentsState.update { directoryContents } + val directoryContents = retrieveDirectoryUseCase(currentPath) + logger.i { "Got Directory Contents: ${directoryContents.allDirectories.count()}" } + _directoryContentsState.update { directoryContents } - //updateGrid() + updateGrid() logger.i { "Current State ${uiState.value.state}" } updatePhotos() } @@ -256,7 +240,7 @@ class DirectoryViewModel( // TODO: STORE LARGEST IMAGES IN CHUNKS } } -/* + private fun updateGrid() = with(_directoryContentsState.value) { logger.i { "Updating State to Success" } logger.i { "Setting Directories: $this" } @@ -269,7 +253,7 @@ class DirectoryViewModel( state = UiState.SUCCESS, ) } - }*/ + } private val DirectoryContents.asDirectoryGridState: DirectoryGridState get() = @@ -290,7 +274,6 @@ class DirectoryViewModel( //region Playlist fun addSelectedDirectoryToPlaylist(playlist: PlaylistDetails) { - /* uiState.value.selectedDirectory?.let { selectedDirectory -> with(_directoryContentsState.value) { logger.i { "Inserting Playlist Image ${playlist.id} as ${uiState.value.selectedDirectory}" } @@ -308,7 +291,7 @@ class DirectoryViewModel( } } ?: run { logger.w { "Selected Directory Not found" } - }*/ + } } //endregion @@ -323,11 +306,10 @@ class DirectoryViewModel( fun setFilterType(sortingType: SortingType) { logger.i { "Setting Filter Type" } - /* _directoryContentsState.update { it.sorted(sortingType) - }*/ - //updateGrid() + } + updateGrid() } private fun cancelJobs() { @@ -342,12 +324,12 @@ class DirectoryViewModel( private fun findSelectedFolderDirectory(): FolderDirectory? = uiState.value.selectedDirectory?.id?.let { id -> logger.d { "Finding Selected Directory" } - return null// _directoryContentsState.value.folders.find { it.id == id } + return _directoryContentsState.value.folders.find { it.id == id } } private fun findSelectedImageDirectory(): ImageDirectory? = uiState.value.selectedDirectory?.id?.let { id -> logger.d { "Finding Selected Directory" } - return null//_directoryContentsState.value.images.find { it.id == id } + return _directoryContentsState.value.images.find { it.id == id } } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModelTwo.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModelTwo.kt deleted file mode 100644 index 2206ff00..00000000 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModelTwo.kt +++ /dev/null @@ -1,97 +0,0 @@ -package com.kevinschildhorn.fotopresenter.ui.screens.directory - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import co.touchlab.kermit.Logger -import com.kevinschildhorn.fotopresenter.data.DirectoryEtc -import com.kevinschildhorn.fotopresenter.data.FolderDirectory -import com.kevinschildhorn.fotopresenter.data.ImageDirectory -import com.kevinschildhorn.fotopresenter.data.State -import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository -import com.kevinschildhorn.fotopresenter.data.repositories.PlaylistRepository -import com.kevinschildhorn.fotopresenter.ui.SortingType -import com.kevinschildhorn.fotopresenter.ui.UiState -import com.kevinschildhorn.fotopresenter.ui.screens.common.ScreenState -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.launch -import org.koin.core.component.KoinComponent -import kotlin.String - -data class DirectoryScreenStateTwo( - val currentPath: String = "", - val directoryGridState: DirectoryGridState = DirectoryGridState(emptyList(), mutableListOf()), - val selectedDirectory: DirectoryGridCellState? = null, - val currentImageCount: Int = 0, - val totalImageCount: Int = 0, - val sortingType: SortingType = SortingType.NAME_ASC, - override val state: UiState = UiState.IDLE, -) : ScreenState { - - val currentPathList: List - get() = currentPath.split("\\").filter { it.isNotEmpty() } -} - -class DirectoryViewModelTwo( - private val playlistRepository: PlaylistRepository, - private val logger: Logger, - private val directoryRepository: DirectoryRepository, - private val directoryEtc: DirectoryEtc, -) : ViewModel(), KoinComponent { - - private var currentPath: String = "" - - private val _directoryContentsState = directoryEtc.directoryFlow - val directoryGridStateFlow: Flow = - _directoryContentsState.map { directory -> - DirectoryGridState( - folderStates = directory.folders.map { it.asCellState }, - imageStates = directory.images.map { it.asCellState }, - ) - } - - private var selectedDirectory: DirectoryGridCellState? = null - private var sortingType: SortingType = SortingType.NAME_ASC - private var state: UiState = UiState.IDLE - - - val uiState: Flow = directoryGridStateFlow.map { - logger.v{ it.toString() } - DirectoryScreenStateTwo( - currentPath = currentPath, - directoryGridState = it, - selectedDirectory = selectedDirectory, - currentImageCount = 0, - totalImageCount = 0, - sortingType = sortingType, - state = UiState.SUCCESS, - ) - } - - fun refreshScreen(){ - if(state != UiState.LOADING) { - currentPath = "Camera Uploads/Camera" - updateDirectories() - } - } - - private fun updateDirectories() { - logger.i { "Updating Directories" } - state = UiState.LOADING - directoryEtc.refreshDirectories(currentPath, viewModelScope) - } - - private val FolderDirectory.asCellState: FolderDirectoryGridCellState - get() = FolderDirectoryGridCellState(name = name, id = id) - - private val ImageDirectory.asCellState: ImageDirectoryGridCellState - get() { - val imageState = when{ - (imageBitmap != null) -> State.SUCCESS(imageBitmap) - image != null -> State.ERROR("") - else -> State.IDLE - } - return ImageDirectoryGridCellState(imageState = imageState, name = name, id = id) - } -} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index e645707a..14dd76ef 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -3,7 +3,6 @@ package com.kevinschildhorn.fotopresenter.ui.shared import androidx.compose.ui.graphics.ImageBitmap expect class SharedImage { - val byteArray: ByteArray fun getImageBitmap(size: Int): ImageBitmap? - fun close() + val byteArray: ByteArray } diff --git a/shared/src/desktopMain/kotlin/Main.desktop.kt b/shared/src/desktopMain/kotlin/Main.desktop.kt index 8d84ac39..868146ed 100644 --- a/shared/src/desktopMain/kotlin/Main.desktop.kt +++ b/shared/src/desktopMain/kotlin/Main.desktop.kt @@ -1,6 +1,5 @@ import androidx.compose.runtime.Composable import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -10,7 +9,7 @@ actual fun getPlatformName(): String = "Desktop" @Composable fun MainView( loginViewModel: LoginViewModel, - directoryViewModel: DirectoryViewModelTwo, + directoryViewModel: DirectoryViewModel, slideshowViewModel: SlideshowViewModel, playlistViewModel: PlaylistViewModel, ) = App(loginViewModel, directoryViewModel, slideshowViewModel, playlistViewModel) diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt index dff24c4a..460b0abf 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt @@ -2,7 +2,6 @@ package com.kevinschildhorn.fotopresenter import co.touchlab.kermit.Logger import co.touchlab.kermit.LoggerConfig -import com.kevinschildhorn.fotopresenter.data.DirectoryEtc import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource @@ -47,15 +46,12 @@ actual object UseCaseFactory { networkHandler = networkHandler, logger = baseLogger.withTag("imageMetadataDataSource") ) - val directoryRepository = DirectoryRepository(directoryDataSource, imageMetadataDataSource) - + private val directoryRepository = DirectoryRepository(directoryDataSource, imageMetadataDataSource) private val imageRepository = ImageRepository(ImageRemoteDataSource(networkHandler)) private val playlistSQLDataSource = PlaylistSQLDataSource( sqlDriver, com.kevinschildhorn.fotopresenter.baseLogger ) - val directoryEtc = DirectoryEtc(imageRepository, directoryRepository, baseLogger) - private val playlistFileDataSource = PlaylistFileDataSource( baseLogger.withTag("playlistFileDataSource"), diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index 022ad298..feda2259 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -3,8 +3,7 @@ package com.kevinschildhorn.fotopresenter.ui.shared import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.res.loadImageBitmap import com.hierynomus.smbj.share.File -import java.io.InputStream -actual fun getBitmapFromFile(inputStream: InputStream, size:Int): ImageBitmap? = - inputStream.buffered().use(::loadImageBitmap) +actual fun getBitmapFromFile(file: File, size:Int): ImageBitmap? = + file.inputStream.buffered().use(::loadImageBitmap) diff --git a/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index 16f0f21a..744138ab 100644 --- a/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -3,7 +3,6 @@ package com.kevinschildhorn.fotopresenter.ui import androidx.compose.ui.graphics.ImageBitmap actual class SharedImage { - actual val byteArray: ByteArray = ByteArray() actual fun getImageBitmap(size:Int): ImageBitmap? = null - actual fun close() {} + actual val byteArray: ByteArray = ByteArray() } diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt index 8aad463e..63033d22 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt @@ -63,7 +63,6 @@ object SMBJHandler : NetworkHandler { } } catch (e: Exception) { logger.e(e) { "Failed To Connect" } - logger.e(e.localizedMessage) disconnect() return false } @@ -108,7 +107,7 @@ object SMBJHandler : NetworkHandler { override suspend fun openImage(path: String): SharedImage? = getFile(path)?.let { val sharedImage = SharedImage(it) - //it.close() TODO + it.close() sharedImage } ?: run { null } diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index 5a7c7d03..2a95e3f1 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -4,11 +4,8 @@ import androidx.compose.ui.graphics.ImageBitmap import com.hierynomus.smbj.share.File actual open class SharedImage(val file: File) { - actual val byteArray: ByteArray = file.inputStream.readAllBytes() actual fun getImageBitmap(size: Int): ImageBitmap? = getBitmapFromFile(file, size) - actual fun close(){ - file.close() - } + actual val byteArray: ByteArray = file.inputStream.readAllBytes() } expect fun getBitmapFromFile(file: File, size: Int): ImageBitmap? From 93ee04cda874573e7cb21ea4b5f49f9066b4ad0a Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Fri, 11 Oct 2024 13:30:48 -0400 Subject: [PATCH 10/19] removing loggedIn --- .../fotopresenter/ui/screens/directory/DirectoryScreen.kt | 1 - .../ui/screens/directory/DirectoryScreenState.kt | 1 - .../ui/screens/directory/DirectoryViewModel.kt | 6 ------ .../fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt | 4 ---- 4 files changed, 12 deletions(-) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt index ab3ee5a1..277bafb4 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt @@ -69,7 +69,6 @@ fun DirectoryScreen( var overlayVisible by remember { mutableStateOf(DirectoryOverlay.NONE) } // Navigation - if (!uiState.loggedIn) onLogout() uiState.slideshowDetails?.let { onStartSlideshow(it) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt index 7c4062f1..f2ee82b1 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt @@ -13,7 +13,6 @@ data class DirectoryScreenState( val currentPath: String = "", var directoryGridState: DirectoryGridState = DirectoryGridState(emptyList(), mutableListOf()), val slideshowDetails: ImageSlideshowDetails? = null, - val loggedIn: Boolean = true, val selectedDirectory: DirectoryGridCellState? = null, val currentImageCount: Int = 0, val totalImageCount: Int = 0, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt index 4be35edf..04b60cef 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt @@ -74,18 +74,12 @@ class DirectoryViewModel( //region Connection - fun setLoggedIn() { - _uiState.update { it.copy(loggedIn = true) } - } - fun logout() { cancelJobs() viewModelScope.launch(Dispatchers.Default) { logger.i { "Logging Out" } val logoutUseCase = UseCaseFactory.disconnectFromServerUseCase logoutUseCase() - logger.d { "Setting loggedIn state to false" } - _uiState.update { it.copy(loggedIn = false) } } } diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt index 336393b7..4c08a34b 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt @@ -54,7 +54,6 @@ class DirectoryViewModelTest : KoinTest { fun `Refresh Screen`() = runTest(testDispatcher) { val viewModel: DirectoryViewModel by inject() - assertTrue(viewModel.uiState.value.loggedIn) viewModel.uiState.test { viewModel.refreshScreen() @@ -68,7 +67,6 @@ class DirectoryViewModelTest : KoinTest { state = awaitItem() assertEquals(UiState.SUCCESS, state.state) assertEquals("", state.currentPath) - assertTrue(state.loggedIn) assertEquals(2, state.directoryGridState.imageStates.count()) assertEquals(2, state.directoryGridState.folderStates.count()) cancelAndIgnoreRemainingEvents() @@ -79,12 +77,10 @@ class DirectoryViewModelTest : KoinTest { fun logout() = runTest(testDispatcher) { val viewModel: DirectoryViewModel by inject() - assertTrue(viewModel.uiState.value.loggedIn) viewModel.uiState.test { var state = awaitItem() viewModel.logout() state = awaitItem() - assertFalse(state.loggedIn) cancelAndIgnoreRemainingEvents() } } From 20d82a8bc0a04f2cd593c1a56f5f08c95b0ded1d Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Fri, 11 Oct 2024 14:24:51 -0400 Subject: [PATCH 11/19] Getting Fetcher working --- .../fotopresenter/SMBJFetcher.kt | 28 +++++-- .../ui/compose/DirectoryPreviews.kt | 13 ++-- shared/src/commonMain/kotlin/App.kt | 1 - .../data/network/NetworkDirectoryDetails.kt | 6 ++ .../RetrieveDirectoryContentsUseCase.kt | 18 +---- .../ui/screens/directory/DirectoryScreen.kt | 21 +---- .../screens/directory/DirectoryScreenState.kt | 77 ++++--------------- .../screens/directory/DirectoryViewModel.kt | 64 ++++----------- .../composables/grid/DirectoryGrid.kt | 24 +++--- .../grid/FolderDirectoryGridCell.kt | 6 +- .../grid/ImageDirectoryGridCell.kt | 53 ++----------- 11 files changed, 87 insertions(+), 224 deletions(-) diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt index 20242768..0ed96bad 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt @@ -1,5 +1,6 @@ package com.kevinschildhorn.fotopresenter +import android.content.Context import android.graphics.Bitmap import android.graphics.BitmapFactory import coil3.ImageLoader @@ -10,23 +11,34 @@ import coil3.fetch.Fetcher import coil3.fetch.ImageFetchResult import coil3.request.Options import com.hierynomus.smbj.share.File +import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.network.SMBJHandler -import com.kevinschildhorn.fotopresenter.ui.screens.directory.PhotoData +import com.kevinschildhorn.fotopresenter.ui.shared.DriverFactory +import com.kevinschildhorn.fotopresenter.ui.shared.SharedCache import com.kevinschildhorn.fotopresenter.ui.shared.getScaledDimensions import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext class SMBJFetcher( - private val photoData: PhotoData, + private val directoryDetails: NetworkDirectoryDetails, + context: Context, ) : Fetcher { + val imageCacheDataSource = ImageCacheDataSource( + cache = SharedCache, + driver = DriverFactory(context).createDriver(), + logger = baseLogger.withTag("ImageCacheDataSource") + ) + override suspend fun fetch(): FetchResult? { return withContext(Dispatchers.IO) { + imageCacheDataSource.getImage(directoryDetails) if (SMBJHandler.isConnected) { - val image = SMBJHandler.openImage(path = photoData.path) + val image = SMBJHandler.openImage(path = directoryDetails.fullPath) val file = image?.file - if(file != null) { - val bitmap = getBitmapFromFile(file, 256) + if (file != null) { + val bitmap = getBitmapFromFile(file, 64) if (bitmap != null) { file.close() ImageFetchResult( @@ -63,11 +75,11 @@ class SMBJFetcher( return BitmapFactory.decodeStream(file.inputStream, null, options) } - class Factory() : Fetcher.Factory { + class Factory() : Fetcher.Factory { override fun create( - data: PhotoData, + data: NetworkDirectoryDetails, options: Options, imageLoader: ImageLoader - ): Fetcher? = SMBJFetcher(data) + ): Fetcher? = SMBJFetcher(data, options.context) } } \ No newline at end of file diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt index 630aad00..d6fddee5 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt @@ -3,13 +3,14 @@ package com.kevinschildhorn.fotopresenter.ui.compose import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview -import com.kevinschildhorn.fotopresenter.data.State +import com.kevinschildhorn.fotopresenter.data.network.DefaultNetworkDirectoryDetails +import com.kevinschildhorn.fotopresenter.data.network.MockNetworkDirectoryDetails +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryGridCellState import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.grid.DirectoryGridCell import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.grid.DirectoryGrid import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.grid.FolderDirectoryGridCell import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryGridState -import com.kevinschildhorn.fotopresenter.ui.screens.directory.FolderDirectoryGridCellState -import com.kevinschildhorn.fotopresenter.ui.screens.directory.ImageDirectoryGridCellState import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.navbar.DirectoryNavigationBar import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.navbar.DirectoryNavigationItem @@ -25,7 +26,7 @@ fun BaseDirectoryPreview() { @Composable fun FolderDirectoryEmptyPreview() { Column { - FolderDirectoryGridCell(FolderDirectoryGridCellState("Hello",0)) + FolderDirectoryGridCell(DirectoryGridCellState.Folder("Hello",0)) } } @@ -35,10 +36,10 @@ fun DirectoryGridPreview() { DirectoryGrid( directoryContent = DirectoryGridState( folderStates = listOf( - FolderDirectoryGridCellState("Hello",0), + DirectoryGridCellState.Folder("Hello",0), ), imageStates = mutableListOf( - ImageDirectoryGridCellState(State.IDLE,"Hello", 1) + DirectoryGridCellState.Image(MockNetworkDirectoryDetails(),"Hello", 1) ) ), onFolderPressed = {}, diff --git a/shared/src/commonMain/kotlin/App.kt b/shared/src/commonMain/kotlin/App.kt index e0d2632c..aed9a377 100644 --- a/shared/src/commonMain/kotlin/App.kt +++ b/shared/src/commonMain/kotlin/App.kt @@ -35,7 +35,6 @@ fun App( typography = FotoTypography(), shapes = fotoShapes, ) { - Scaffold { innerPadding -> NavHost( navController = navController, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectoryDetails.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectoryDetails.kt index 40cb6568..5a9fd98f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectoryDetails.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectoryDetails.kt @@ -28,3 +28,9 @@ class DefaultNetworkDirectoryDetails( override val id: Int, override val dateMillis: Long = Clock.System.now().toEpochMilliseconds() ) : NetworkDirectoryDetails + +class MockNetworkDirectoryDetails( + override val fullPath: String = "", + override val id: Int = 0, + override val dateMillis: Long = Clock.System.now().toEpochMilliseconds() +) : NetworkDirectoryDetails diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt index a50bec8d..8f88a152 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt @@ -18,22 +18,6 @@ class RetrieveDirectoryContentsUseCase( ) { suspend operator fun invoke(path: String): DirectoryContents { logger.i { "Getting directory Contents at path $path" } - val directoryContents = directoryRepository.getDirectoryContents(path) - return directoryContents.updateImages { - logger.i { "Updating Image File ${it.name}" } - imageRepository.getImage(it) - } + return directoryRepository.getDirectoryContents(path) } } - -private suspend fun DirectoryContents.updateImages(block: suspend (NetworkDirectoryDetails) -> SharedImage?): DirectoryContents = - this.copy( - images = - images.map { - ImageDirectory( - it.details, - it.metaData, - image = block(it.details) - ) - }, - ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt index 6fc74670..18def33b 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt @@ -58,6 +58,7 @@ enum class DirectoryOverlay { fun DirectoryScreen( viewModel: DirectoryViewModel, onLogout: () -> Unit, + onStartSlideshow: (ImageSlideshowDetails) -> Unit, onShowPlaylists: () -> Unit, ) { LaunchedEffect(Unit) { @@ -97,24 +98,6 @@ fun DirectoryScreen( }, modifier = Modifier.padding(Padding.SMALL.dp) ) - if (uiState.imageCountString.isNotEmpty()) { - Text( - uiState.imageCountString, - modifier = Modifier.fillMaxWidth(), - textAlign = TextAlign.Center, - style = FotoTypography().caption, - color = fotoColors.onBackground, - ) - LinearProgressIndicator( - progress = uiState.currentImageCount.toFloat() / uiState.totalImageCount.toFloat(), - modifier = Modifier.fillMaxWidth() - .height(25.dp) - .padding(horizontal = Padding.EXTRA_LARGE.dp, vertical = Padding.SMALL.dp) - .clip(RoundedCornerShape(5.dp)), - color = fotoColors.primary, - ) - - } DirectoryGrid( uiState.directoryGridState, onFolderPressed = { @@ -143,6 +126,7 @@ fun DirectoryScreen( when (it.action) { ActionSheetAction.START_SLIDESHOW -> { viewModel.startSlideshow() + onStartSlideshow(uiState.slideshowDetails!!) overlayVisible = DirectoryOverlay.NONE viewModel.setSelectedDirectory(null) } @@ -217,6 +201,7 @@ fun DirectoryScreen( }, onConfirmation = { viewModel.logout() + onLogout() overlayVisible = DirectoryOverlay.NONE }, ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt index f2ee82b1..d7e4e6e0 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt @@ -1,8 +1,7 @@ package com.kevinschildhorn.fotopresenter.ui.screens.directory -import androidx.compose.ui.graphics.ImageBitmap import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails -import com.kevinschildhorn.fotopresenter.data.State +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.ui.SortingType import com.kevinschildhorn.fotopresenter.ui.UiState import com.kevinschildhorn.fotopresenter.ui.screens.common.ActionSheetAction @@ -14,49 +13,20 @@ data class DirectoryScreenState( var directoryGridState: DirectoryGridState = DirectoryGridState(emptyList(), mutableListOf()), val slideshowDetails: ImageSlideshowDetails? = null, val selectedDirectory: DirectoryGridCellState? = null, - val currentImageCount: Int = 0, - val totalImageCount: Int = 0, val sortingType: SortingType = SortingType.NAME_ASC, override val state: UiState = UiState.IDLE, ) : ScreenState { - fun copyImageState( - id: Int, - state: State, - ): DirectoryScreenState { - val list = directoryGridState.imageStates.toMutableList() - val index = list.indexOfFirst { it.id == id } - if (index != -1) { - val element = list[index] - list[index] = - element.copy( - imageState = state, - ) - } - return this.copy( - directoryGridState = - directoryGridState.copy( - imageStates = list, - ), - ) - } fun getImageIndexFromId(id: Int): Int = directoryGridState.imageStates.indexOfFirst { it.id == id } val currentPathList: List get() = currentPath.split("\\").filter { it.isNotEmpty() } - - val imageCountString: String - get() = - if (totalImageCount != 0 && currentImageCount < totalImageCount) - "$currentImageCount of $totalImageCount downloaded" - else "" - } data class DirectoryGridState( - val folderStates: List, - val imageStates: List, + val folderStates: List, + val imageStates: List, ) { val allStates: List get() = folderStates + imageStates @@ -71,41 +41,24 @@ data class DirectoryGridState( """ } -data class FolderDirectoryGridCellState( - override val name: String, - override val id: Int, -) : DirectoryGridCellState { - override val actionSheetContexts: List - get() = listOf( +sealed class DirectoryGridCellState( + val name: String, + val id: Int, + val actionSheetContexts: List + +) { + class Folder(name: String, id: Int) : DirectoryGridCellState( + name, id, listOf( ActionSheetContext(ActionSheetAction.START_SLIDESHOW, 1), ActionSheetContext(ActionSheetAction.ADD_DYNAMIC_LOCATION, 2), ) + ) - override fun toString(): String = "(F:$name:$id)" -} - -data class ImageDirectoryGridCellState( - val imageState: State, - override val name: String, - override val id: Int, -) : DirectoryGridCellState { - override val actionSheetContexts: List - get() = listOf( + class Image(val directoryDetails: NetworkDirectoryDetails, name: String, id: Int) : DirectoryGridCellState( + name, id, listOf( ActionSheetContext(ActionSheetAction.ADD_STATIC_LOCATION, 1), ActionSheetContext(ActionSheetAction.ADD_METADATA, 2), ) - + ) override fun toString(): String = "(I:$name:$id)" } - -interface DirectoryGridCellState { - val name: String - val id: Int - val actionSheetContexts: List - - val isFolderGridCell: Boolean - get() = (this is FolderDirectoryGridCellState) - - val isImageGridCell: Boolean - get() = (this is ImageDirectoryGridCellState) -} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt index 0bd7134b..62a6cd77 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt @@ -8,7 +8,6 @@ import com.kevinschildhorn.fotopresenter.data.FolderDirectory import com.kevinschildhorn.fotopresenter.data.ImageDirectory import com.kevinschildhorn.fotopresenter.data.MetadataFileDetails import com.kevinschildhorn.fotopresenter.data.PlaylistDetails -import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException import com.kevinschildhorn.fotopresenter.data.repositories.PlaylistRepository import com.kevinschildhorn.fotopresenter.extension.addPath @@ -28,7 +27,6 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.plus -import kotlinx.datetime.Clock import org.koin.core.component.KoinComponent class DirectoryViewModel( @@ -41,14 +39,10 @@ class DirectoryViewModel( private val slideshowScope: CoroutineScope = viewModelScope + Dispatchers.IO private val imageScope: CoroutineScope = viewModelScope + Dispatchers.IO + private val _directoryContentsState = MutableStateFlow(DirectoryContents()) private val _uiState = MutableStateFlow(DirectoryScreenState()) val uiState: StateFlow = _uiState.asStateFlow() - private val _directoryContentsState = MutableStateFlow(DirectoryContents()) - - // Indexes of all Downloaded images - private val downloadedImageSet: MutableSet = mutableSetOf() - private val currentPath: String get() = uiState.value.currentPath @@ -102,7 +96,7 @@ class DirectoryViewModel( } fun clearSlideshow() { - // _uiState.update { it.copy(slideshowDetails = null) } + _uiState.update { it.copy(slideshowDetails = null) } } fun setSelectedImageById(imageId: Int?) { @@ -140,7 +134,7 @@ class DirectoryViewModel( logger.i { "Changing directory to path $path" } cancelJobs() - slideshowScope.launch(Dispatchers.Default) { + viewModelScope.launch(Dispatchers.Default) { val changeDirectoryUseCase = UseCaseFactory.changeDirectoryUseCase try { logger.i { "Getting New Path" } @@ -152,21 +146,13 @@ class DirectoryViewModel( logger.e(e) { "Error Occurred Getting new path" } _uiState.update { it.copy( - state = - UiState.ERROR( - e.message ?: "An Unknown Network Error Occurred", - ), + state = UiState.ERROR(e.message ?: "An Unknown Network Error Occurred"), ) } } catch (e: Exception) { logger.e(e) { "Something went wrong" } _uiState.update { - it.copy( - state = - UiState.ERROR( - e.message ?: "Something Went Wrong", - ), - ) + it.copy(state = UiState.ERROR(e.message ?: "Something Went Wrong")) } } } @@ -185,29 +171,6 @@ class DirectoryViewModel( updateGrid() logger.i { "Current State ${uiState.value.state}" } - updatePhotos() - } - } - - private fun updatePhotos() { - val count = imageUiState.value.imageDirectories.count() - downloadedImageSet.clear() - _uiState.update { it.copy(totalImageCount = count, currentImageCount = 0) } - imageScope.launch { - val startTime = Clock.System.now().toEpochMilliseconds() - logger.i { "Updating Photos" } - val imageDirectories: List = imageUiState.value.imageDirectories - imageDirectories.mapIndexed { index, imageDirectory -> - _uiState.update { - it.copyImageState( - imageDirectory.id, - state = State.SUCCESS(PhotoData(imageDirectory.details.fullPath)), - ).copy( - currentImageCount = downloadedImageSet.size - ) - } - } - // TODO: STORE LARGEST IMAGES IN CHUNKS } } @@ -228,11 +191,15 @@ class DirectoryViewModel( private val DirectoryContents.asDirectoryGridState: DirectoryGridState get() = DirectoryGridState( - folderStates = this.folders.map { FolderDirectoryGridCellState(it.name, it.id) }, - imageStates = - this.images.map { - ImageDirectoryGridCellState( - State.IDLE, + folderStates = folders.map { + DirectoryGridCellState.Folder( + it.name, + it.id + ) + }, + imageStates = images.map { + DirectoryGridCellState.Image( + it.details, it.name, it.id, ) @@ -249,7 +216,7 @@ class DirectoryViewModel( logger.i { "Inserting Playlist Image ${playlist.id} as ${uiState.value.selectedDirectory}" } val states: List = - if (selectedDirectory.isImageGridCell) this.images + if (selectedDirectory is DirectoryGridCellState.Image) this.images else this.folders states.find { it.id == selectedDirectory.id } @@ -288,7 +255,6 @@ class DirectoryViewModel( slideshowScope.coroutineContext.cancelChildren() imageScope.coroutineContext.cancelChildren() logger.v { "Finished Cancelling Jobs!" } - } private fun findSelectedFolderDirectory(): FolderDirectory? = diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGrid.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGrid.kt index 366b8702..1cf3745e 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGrid.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGrid.kt @@ -17,8 +17,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryGridCellState import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryGridState -import com.kevinschildhorn.fotopresenter.ui.screens.directory.FolderDirectoryGridCellState -import com.kevinschildhorn.fotopresenter.ui.screens.directory.ImageDirectoryGridCellState @OptIn(ExperimentalFoundationApi::class) @Composable @@ -44,7 +42,8 @@ fun DirectoryGrid( awaitPointerEventScope { val event = awaitPointerEvent() if (event.type == PointerEventType.Press && - event.buttons.isSecondaryPressed) { + event.buttons.isSecondaryPressed + ) { event.changes.forEach { e -> e.consume() } onActionSheet(state) } @@ -52,10 +51,9 @@ fun DirectoryGrid( } .combinedClickable( onClick = { - (state as? ImageDirectoryGridCellState)?.let { imageContent -> - onImageDirectoryPressed(imageContent.id) - } ?: run { - onFolderPressed(state.id) + when (state) { + is DirectoryGridCellState.Folder -> onFolderPressed(state.id) + is DirectoryGridCellState.Image -> onImageDirectoryPressed(state.id) } }, onLongClick = { @@ -64,15 +62,13 @@ fun DirectoryGrid( }, onLongClickLabel = "Action Sheet", ) - (state as? FolderDirectoryGridCellState)?.let { folderContent -> - FolderDirectoryGridCell( - folderContent, + when (state) { + is DirectoryGridCellState.Folder -> FolderDirectoryGridCell( + state, modifier = directoryItemModifier, ) - } - (state as? ImageDirectoryGridCellState)?.let { imageContent -> - ImageDirectoryGridCell( - imageContent, + is DirectoryGridCellState.Image -> ImageDirectoryGridCell( + state, modifier = directoryItemModifier, ) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/FolderDirectoryGridCell.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/FolderDirectoryGridCell.kt index e244af3e..7457d889 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/FolderDirectoryGridCell.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/FolderDirectoryGridCell.kt @@ -6,21 +6,19 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.Icon -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Edit import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors -import com.kevinschildhorn.fotopresenter.ui.screens.directory.FolderDirectoryGridCellState +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryGridCellState import compose.icons.EvaIcons import compose.icons.evaicons.Fill import compose.icons.evaicons.fill.Folder @Composable fun FolderDirectoryGridCell( - folderState: FolderDirectoryGridCellState, + folderState: DirectoryGridCellState, modifier: Modifier = Modifier, ) { DirectoryGridCell(modifier) { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/ImageDirectoryGridCell.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/ImageDirectoryGridCell.kt index ab3b6b0a..566d3f72 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/ImageDirectoryGridCell.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/ImageDirectoryGridCell.kt @@ -1,62 +1,25 @@ package com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.grid -import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.material.CircularProgressIndicator import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage -import coil3.compose.LocalPlatformContext -import coil3.request.ImageRequest import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors -import com.kevinschildhorn.fotopresenter.ui.screens.directory.ImageDirectoryGridCellState -import compose.icons.EvaIcons -import compose.icons.evaicons.Fill -import compose.icons.evaicons.fill.QuestionMark +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryGridCellState @Composable fun ImageDirectoryGridCell( - imageContent: ImageDirectoryGridCellState, + imageContent: DirectoryGridCellState.Image, modifier: Modifier = Modifier, ) { - DirectoryGridCell(modifier) { - imageContent.imageState.onSuccess { - AsyncImage( - model = it, - contentDescription = imageContent.name, - contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxSize().background(fotoColors.surface), - ) - }.onError { - Column( - modifier = - Modifier - .fillMaxSize() - .padding(5.dp), - ) { - Image( - imageVector = EvaIcons.Fill.QuestionMark, - contentDescription = "Question Mark", - modifier = Modifier.align(Alignment.CenterHorizontally), - ) - DirectoryGridCellText( - imageContent.name, - modifier = Modifier.align(Alignment.CenterHorizontally), - ) - } - }.onLoading { - CircularProgressIndicator( - modifier = Modifier.width(33.dp).align(Alignment.Center), - color = fotoColors.primary, - ) - } + AsyncImage( + model = imageContent.directoryDetails, + contentDescription = imageContent.name, + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxSize().background(fotoColors.surface), + ) } } From 1ad69363cf9e365fcb9713f483888cce6cb957a0 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Fri, 11 Oct 2024 14:30:46 -0400 Subject: [PATCH 12/19] updating code --- .../kotlin/com/kevinschildhorn/MainActivity.kt | 5 ++++- .../kevinschildhorn/fotopresenter/SMBJFetcher.kt | 16 +++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt index 3a42c8ea..9a0a6233 100644 --- a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt +++ b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt @@ -7,6 +7,7 @@ import androidx.appcompat.app.AppCompatActivity import coil3.ImageLoader import coil3.compose.setSingletonImageLoaderFactory import com.kevinschildhorn.fotopresenter.SMBJFetcher +import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler import com.kevinschildhorn.fotopresenter.startKoin import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel @@ -14,6 +15,7 @@ import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.core.component.KoinComponent +import org.koin.core.component.inject class MainActivity : AppCompatActivity(), KoinComponent { @@ -21,6 +23,7 @@ class MainActivity : AppCompatActivity(), KoinComponent { private val directoryViewModel by viewModel() private val slideshowViewModel by viewModel() private val playlistViewModel by viewModel() + private val networkHandler: NetworkHandler by inject() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -30,7 +33,7 @@ class MainActivity : AppCompatActivity(), KoinComponent { setSingletonImageLoaderFactory { context -> ImageLoader.Builder(context) .components { - add(SMBJFetcher.Factory()) + add(SMBJFetcher.Factory(networkHandler)) } .build() } diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt index 0ed96bad..30e7299c 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt @@ -13,15 +13,17 @@ import coil3.request.Options import com.hierynomus.smbj.share.File import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails -import com.kevinschildhorn.fotopresenter.data.network.SMBJHandler +import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler import com.kevinschildhorn.fotopresenter.ui.shared.DriverFactory import com.kevinschildhorn.fotopresenter.ui.shared.SharedCache import com.kevinschildhorn.fotopresenter.ui.shared.getScaledDimensions import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import kotlin.math.roundToInt class SMBJFetcher( private val directoryDetails: NetworkDirectoryDetails, + private val networkHandler: NetworkHandler, context: Context, ) : Fetcher { @@ -34,8 +36,8 @@ class SMBJFetcher( override suspend fun fetch(): FetchResult? { return withContext(Dispatchers.IO) { imageCacheDataSource.getImage(directoryDetails) - if (SMBJHandler.isConnected) { - val image = SMBJHandler.openImage(path = directoryDetails.fullPath) + if (networkHandler.isConnected) { + val image = networkHandler.openImage(path = directoryDetails.fullPath) val file = image?.file if (file != null) { val bitmap = getBitmapFromFile(file, 64) @@ -67,19 +69,19 @@ class SMBJFetcher( val height: Int = options.outHeight val width: Int = options.outWidth val dimensions = getScaledDimensions(width, height, size) - val heightRatio: Int = Math.round(height.toFloat() / dimensions.second.toFloat()) - val widthRatio: Int = Math.round(width.toFloat() / dimensions.first.toFloat()) + val heightRatio: Int = (height.toFloat() / dimensions.second.toFloat()).roundToInt() + val widthRatio: Int = (width.toFloat() / dimensions.first.toFloat()).roundToInt() options.inSampleSize = if (heightRatio < widthRatio) heightRatio else widthRatio options.inJustDecodeBounds = false return BitmapFactory.decodeStream(file.inputStream, null, options) } - class Factory() : Fetcher.Factory { + class Factory(private val networkHandler: NetworkHandler) : Fetcher.Factory { override fun create( data: NetworkDirectoryDetails, options: Options, imageLoader: ImageLoader - ): Fetcher? = SMBJFetcher(data, options.context) + ): Fetcher? = SMBJFetcher(data, networkHandler, options.context) } } \ No newline at end of file From 68906d5fe3d17f2a3433578522263784da002ff4 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Fri, 11 Oct 2024 14:32:47 -0400 Subject: [PATCH 13/19] Update DirectoryScreenState.kt --- .../ui/screens/directory/DirectoryScreenState.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt index d7e4e6e0..9d717074 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt @@ -25,8 +25,8 @@ data class DirectoryScreenState( } data class DirectoryGridState( - val folderStates: List, - val imageStates: List, + val folderStates: List, + val imageStates: List, ) { val allStates: List get() = folderStates + imageStates From c50ac13ef877ec76a80b6c1ebe2f98aaebfe29b4 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Mon, 14 Oct 2024 12:13:38 -0400 Subject: [PATCH 14/19] Updating Queries --- .gitignore | 2 +- .../com/kevinschildhorn/MainActivity.kt | 8 +- .../fotopresenter/SMBJFetcher.kt | 87 ------------------ .../ui/shared/SharedImageAndroid.kt | 32 +++---- .../ui/shared/SharedImageConverter.kt | 34 ------- .../com/kevinschildhorn/fotopresenter/Koin.kt | 16 ++-- .../data/datasources/ImageCacheDataSource.kt | 48 ---------- .../data/datasources/ImageRemoteDataSource.kt | 19 ---- .../image/CachedImageDataSource.kt | 60 +++++++++++++ .../image/NetworkImageDataSource.kt | 12 +++ .../data/repositories/ImageRepository.kt | 27 ++++-- .../RetrieveDirectoryContentsUseCase.kt | 5 -- .../domain/image/RetrieveImageUseCase.kt | 15 ++-- .../fotopresenter/ui/ByteArrayFetcher.kt | 42 +++++++++ .../ui/screens/common/ImageScreenState.kt | 4 +- .../ui/screens/common/ImageViewModel.kt | 7 +- .../common/composables/ImagePreviewOverlay.kt | 16 ++-- .../ui/screens/directory/DirectoryScreen.kt | 10 --- .../ui/screens/slideshow/SlideshowScreen.kt | 7 +- .../fotopresenter/ui/shared/SharedCache.kt | 27 +++--- .../fotopresenter/ui/shared/SharedImage.kt | 26 +++++- .../ui/shared/SharedImageConverter.kt | 28 ------ ...st.kt => ImageFileRemoteDataSourceTest.kt} | 6 +- .../data/repositories/ImageRepositoryTest.kt | 89 ------------------- .../fotopresenter/UseCaseFactoryDesktop.kt | 14 +-- .../fotopresenter/ui/shared/SharedImage.kt | 9 -- .../ui/shared/SharedImageConverter.kt | 18 ---- .../ui/shared/SharedImageDesktop.kt | 10 +++ .../{SharedImage.kt => SharedImageIos.kt} | 0 .../fotopresenter/data/network/SMBJHandler.kt | 6 +- .../fotopresenter/ui/SMBJFetcher.kt | 43 +++++++++ .../fotopresenter/ui/shared/SharedImage.kt | 12 --- 32 files changed, 288 insertions(+), 451 deletions(-) delete mode 100644 shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt delete mode 100644 shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageCacheDataSource.kt delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSource.kt create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/NetworkImageDataSource.kt create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt rename shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/{ImageRemoteDataSourceTest.kt => ImageFileRemoteDataSourceTest.kt} (93%) delete mode 100644 shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepositoryTest.kt delete mode 100644 shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt delete mode 100644 shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt create mode 100644 shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt rename shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/{SharedImage.kt => SharedImageIos.kt} (100%) create mode 100644 shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt delete mode 100644 shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt diff --git a/.gitignore b/.gitignore index aef2159a..b1984842 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Compiled class file *.class +*.DS_STORE # Log file *.log @@ -34,7 +35,6 @@ ios/FotoPresenter.xcworkspace/xcuserdata/kevinschildhorn.xcuserdatad/xcdebugger/ ios/FotoPresenter.xcworkspace/xcuserdata/kevinschildhorn.xcuserdatad/UserInterfaceState.xcuserstate *.hprof ios/FotoPresenter.xcworkspace/xcuserdata/kevinschildhorn.xcuserdatad/UserInterfaceState.xcuserstate -ios/FotoPresenter.xcworkspace/xcuserdata/kevinschildhorn.xcuserdatad/UserInterfaceState.xcuserstate common/src/commonMain/kotlin/me/kevinschildhorn/common/network/ftps/TestingLoginInfo.kt androidApp/build/kotlin/compileDebugKotlinAndroid/cacheable/caches-jvm/lookups/lookups.tab_i.len diff --git a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt index 9a0a6233..4e9ea81a 100644 --- a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt +++ b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt @@ -6,8 +6,10 @@ import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import coil3.ImageLoader import coil3.compose.setSingletonImageLoaderFactory -import com.kevinschildhorn.fotopresenter.SMBJFetcher +import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource +import com.kevinschildhorn.fotopresenter.ui.SMBJFetcher import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler +import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository import com.kevinschildhorn.fotopresenter.startKoin import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel @@ -23,7 +25,7 @@ class MainActivity : AppCompatActivity(), KoinComponent { private val directoryViewModel by viewModel() private val slideshowViewModel by viewModel() private val playlistViewModel by viewModel() - private val networkHandler: NetworkHandler by inject() + private val imageRepository: ImageRepository by inject() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -33,7 +35,7 @@ class MainActivity : AppCompatActivity(), KoinComponent { setSingletonImageLoaderFactory { context -> ImageLoader.Builder(context) .components { - add(SMBJFetcher.Factory(networkHandler)) + add(SMBJFetcher.Factory(imageRepository)) } .build() } diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt deleted file mode 100644 index 30e7299c..00000000 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/SMBJFetcher.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.kevinschildhorn.fotopresenter - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import coil3.ImageLoader -import coil3.asImage -import coil3.decode.DataSource -import coil3.fetch.FetchResult -import coil3.fetch.Fetcher -import coil3.fetch.ImageFetchResult -import coil3.request.Options -import com.hierynomus.smbj.share.File -import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails -import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler -import com.kevinschildhorn.fotopresenter.ui.shared.DriverFactory -import com.kevinschildhorn.fotopresenter.ui.shared.SharedCache -import com.kevinschildhorn.fotopresenter.ui.shared.getScaledDimensions -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import kotlin.math.roundToInt - -class SMBJFetcher( - private val directoryDetails: NetworkDirectoryDetails, - private val networkHandler: NetworkHandler, - context: Context, -) : Fetcher { - - val imageCacheDataSource = ImageCacheDataSource( - cache = SharedCache, - driver = DriverFactory(context).createDriver(), - logger = baseLogger.withTag("ImageCacheDataSource") - ) - - override suspend fun fetch(): FetchResult? { - return withContext(Dispatchers.IO) { - imageCacheDataSource.getImage(directoryDetails) - if (networkHandler.isConnected) { - val image = networkHandler.openImage(path = directoryDetails.fullPath) - val file = image?.file - if (file != null) { - val bitmap = getBitmapFromFile(file, 64) - if (bitmap != null) { - file.close() - ImageFetchResult( - image = bitmap.asImage(), - isSampled = true, - dataSource = DataSource.NETWORK, - ) - } else { - throw Exception("Failed to fetch image from FTP") - } - } else { - throw Exception("Failed to fetch image from FTP") - } - } else { - throw Exception("Failed to fetch image from FTP") - } - } - } - - private fun getBitmapFromFile(file: File, size: Int): Bitmap? { - - val options = BitmapFactory.Options() - options.inJustDecodeBounds = true - BitmapFactory.decodeStream(file.inputStream, null, options) - - val height: Int = options.outHeight - val width: Int = options.outWidth - val dimensions = getScaledDimensions(width, height, size) - val heightRatio: Int = (height.toFloat() / dimensions.second.toFloat()).roundToInt() - val widthRatio: Int = (width.toFloat() / dimensions.first.toFloat()).roundToInt() - options.inSampleSize = if (heightRatio < widthRatio) heightRatio else widthRatio - - options.inJustDecodeBounds = false - return BitmapFactory.decodeStream(file.inputStream, null, options) - } - - class Factory(private val networkHandler: NetworkHandler) : Fetcher.Factory { - override fun create( - data: NetworkDirectoryDetails, - options: Options, - imageLoader: ImageLoader - ): Fetcher? = SMBJFetcher(data, networkHandler, options.context) - } -} \ No newline at end of file diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt index 0452f5b1..fd201678 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt @@ -2,23 +2,25 @@ package com.kevinschildhorn.fotopresenter.ui.shared import android.graphics.Bitmap import android.graphics.BitmapFactory -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.asImageBitmap -import com.hierynomus.smbj.share.File +import coil3.Image +import coil3.asImage -actual fun getBitmapFromFile(file: File, size: Int): ImageBitmap? { +actual open class SharedImage actual constructor(actual val byteArray: ByteArray) { + actual fun getCoilImage(size: Int): Image? = getAndroidBitmap(byteArray, size)?.asImage() - val options = BitmapFactory.Options() - options.inJustDecodeBounds = true - BitmapFactory.decodeStream(file.inputStream, null, options) + private fun getAndroidBitmap(byteArray: ByteArray, size: Int): Bitmap? { + val options = BitmapFactory.Options() + options.inJustDecodeBounds = true + BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options) - val height: Int = options.outHeight - val width: Int = options.outWidth - val dimensions = getScaledDimensions(width, height, size) - val heightRatio: Int = Math.round(height.toFloat() / dimensions.second.toFloat()) - val widthRatio: Int = Math.round(width.toFloat() / dimensions.first.toFloat()) - options.inSampleSize = if (heightRatio < widthRatio) heightRatio else widthRatio + val height: Int = options.outHeight + val width: Int = options.outWidth + val dimensions = getScaledDimensions(width, height, size) + val heightRatio: Int = Math.round(height.toFloat() / dimensions.second.toFloat()) + val widthRatio: Int = Math.round(width.toFloat() / dimensions.first.toFloat()) + options.inSampleSize = if (heightRatio < widthRatio) heightRatio else widthRatio - options.inJustDecodeBounds = false - return BitmapFactory.decodeStream(file.inputStream, null, options)?.asImageBitmap() + options.inJustDecodeBounds = false + return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options) + } } \ No newline at end of file diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt deleted file mode 100644 index 11070236..00000000 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.kevinschildhorn.fotopresenter.ui.shared - -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.asAndroidBitmap -import androidx.compose.ui.graphics.asImageBitmap -import java.io.ByteArrayOutputStream - - -actual object SharedImageConverter { - actual fun convertBytes(byteArray: ByteArray): ImageBitmap { - val bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size) - return bmp.asImageBitmap() - } - - actual fun convertImage(imageBitmap: ImageBitmap): ByteArray { - val bitmap = imageBitmap.asAndroidBitmap() - val stream = ByteArrayOutputStream() - bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream) - val byteArray = stream.toByteArray() - return byteArray - } - - private fun Bitmap.convertToByteArray(): ByteArray { - val stream = ByteArrayOutputStream() - this.compress(Bitmap.CompressFormat.PNG, 100, stream) - val byteArray = stream.toByteArray() - if (!this.isRecycled) { - this.recycle(); - } - return byteArray - } -} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt index 27543619..5a83b919 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt @@ -1,14 +1,13 @@ package com.kevinschildhorn.fotopresenter import co.touchlab.kermit.Logger -import co.touchlab.kermit.LoggerConfig import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource -import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource +import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource import com.kevinschildhorn.fotopresenter.data.datasources.ImageMetadataDataSource -import com.kevinschildhorn.fotopresenter.data.datasources.ImageRemoteDataSource import com.kevinschildhorn.fotopresenter.data.datasources.PlaylistFileDataSource import com.kevinschildhorn.fotopresenter.data.datasources.PlaylistSQLDataSource +import com.kevinschildhorn.fotopresenter.data.datasources.image.NetworkImageDataSource import com.kevinschildhorn.fotopresenter.data.repositories.CredentialsRepository import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository @@ -28,7 +27,7 @@ import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel import com.kevinschildhorn.fotopresenter.ui.shared.CacheInterface -import com.kevinschildhorn.fotopresenter.ui.shared.SharedCache +import com.kevinschildhorn.fotopresenter.ui.shared.SharedInMemoryCache import org.koin.core.module.Module import org.koin.dsl.module @@ -40,18 +39,18 @@ val commonModule = module { // Data - single { SharedCache } + single { SharedInMemoryCache } + single { NetworkImageDataSource(get()) } single { CredentialsDataSource(get()) } single { CredentialsRepository(get()) } single { DirectoryDataSource(get(), baseLogger.withTag("DirectoryDataSource")) } single { DirectoryRepository(get(), get()) } - single { ImageRemoteDataSource(get()) } - single { ImageRepository(get()) } - single { ImageCacheDataSource(get(), get(), baseLogger.withTag("ImageCacheDataSource")) } + single { CachedImageDataSource(get(), get(), baseLogger.withTag("ImageCacheDataSource")) } single { PlaylistFileDataSource(baseLogger.withTag("PlaylistDataSource"), get()) } single { PlaylistSQLDataSource(get(), baseLogger.withTag("PlaylistDataSource")) } single { PlaylistRepository(get(), get()) } factory { ImageMetadataDataSource(baseLogger.withTag("ImageMetadataDataSource"), get()) } + single { ImageRepository(get(), get(), baseLogger.withTag("ImageRepository")) } // Domain factory { ConnectToServerUseCase(get(), baseLogger.withTag("ConnectToServerUseCase")) } @@ -74,7 +73,6 @@ val commonModule = } factory { RetrieveDirectoryContentsUseCase( - get(), get(), baseLogger.withTag("RetrieveDirectoryContentsUseCase"), ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageCacheDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageCacheDataSource.kt deleted file mode 100644 index ad99df89..00000000 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageCacheDataSource.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.kevinschildhorn.fotopresenter.data.datasources - -import androidx.compose.ui.graphics.ImageBitmap -import app.cash.sqldelight.db.SqlDriver -import co.touchlab.kermit.Logger -import com.kevinschildhorn.fotopresenter.PlaylistDatabase -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails -import com.kevinschildhorn.fotopresenter.ui.shared.CacheInterface -import com.kevinschildhorn.fotopresenter.ui.shared.SharedImageConverter - -class ImageCacheDataSource( - private val cache: CacheInterface, - driver: SqlDriver, - private val logger: Logger -) { - private val database = PlaylistDatabase(driver) - - - fun getImage(directory: NetworkDirectoryDetails): ImageBitmap? { - logger.i { "Getting Image from Cache ${directory.cacheId}" } - return try { - val image = database.imageQueries.selectImageByName(directory.cacheId).executeAsOne() - SharedImageConverter.convertBytes(image.image) - } catch (e: Exception) { - logger.e(e) { "Image NOT found" } - - null - } - //return cache.getImage(directory.cacheId) - } - - fun saveImage( - directory: NetworkDirectoryDetails, - bitmap: ImageBitmap, - ) { - logger.i { "Saving Image To Cache ${directory.cacheId}" } - database.imageQueries.insertImage( - directory.cacheId, - SharedImageConverter.convertImage(bitmap) - ) - logger.i { "Image Saved" } - - //DiscCache.storeFile(directory.cacheId, bitmap) - } - - private val NetworkDirectoryDetails.cacheId: String - get() = "$name.$id" -} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSource.kt deleted file mode 100644 index e132203d..00000000 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSource.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.kevinschildhorn.fotopresenter.data.datasources - -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails -import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler -import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerError -import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException -import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage -import kotlin.coroutines.cancellation.CancellationException - -/** -Fetches Photos from a NAS - **/ -class ImageRemoteDataSource(private val networkHandler: NetworkHandler) { - @Throws(NetworkHandlerException::class, CancellationException::class) - suspend fun getImage(directory: NetworkDirectoryDetails): SharedImage? { - if (!networkHandler.isConnected) throw NetworkHandlerException(NetworkHandlerError.NOT_CONNECTED) - return networkHandler.openImage(directory.fullPath) - } -} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt new file mode 100644 index 00000000..3988dda7 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt @@ -0,0 +1,60 @@ +package com.kevinschildhorn.fotopresenter.data.datasources.image + +import androidx.collection.size +import app.cash.sqldelight.db.SqlDriver +import co.touchlab.kermit.Logger +import com.kevinschildhorn.fotopresenter.Image as SQLImage +import com.kevinschildhorn.fotopresenter.PlaylistDatabase +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails +import com.kevinschildhorn.fotopresenter.ui.shared.CacheInterface +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage +import java.io.InputStream + +class CachedImageDataSource( + private val cache: CacheInterface, + driver: SqlDriver, + private val logger: Logger +) { + private val database = PlaylistDatabase(driver) + + fun getImage(directory: NetworkDirectoryDetails): SharedImage? { + logger.i { "Getting Image from Cache ${directory.cacheId}" } + return try { + val image: SQLImage = database.imageQueries.selectImageByName(directory.cacheId).executeAsOne() + SharedImage(image.image) + } catch (e: Exception) { + logger.e(e) { "Image NOT found" } + null + } + } + + fun saveImage(directory: NetworkDirectoryDetails, image: SharedImage) { + logger.i { "Saving Image To Cache ${directory.cacheId}" } + database.imageQueries.insertImage( + directory.cacheId, + image.byteArray, + ) + logger.i { "Image Saved" } + //cache.cacheImage(directory.cacheId, image) TODO + } + + private val NetworkDirectoryDetails.cacheId: String + get() = "$name.$id" + + + fun readBlobInChunks(cursor: Cursor, columnIndex: Int): InputStream { + return object : InputStream() { + private var pos = 0 + private val blob = cursor.getBlob(columnIndex) + + override fun read(): Int { + if (pos >= blob.size) { + return -1 + } + return blob[pos++].toInt() and 0xFF + } + + // Implement other methods of InputStream if needed + } + } +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/NetworkImageDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/NetworkImageDataSource.kt new file mode 100644 index 00000000..0809b27e --- /dev/null +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/NetworkImageDataSource.kt @@ -0,0 +1,12 @@ +package com.kevinschildhorn.fotopresenter.data.datasources.image + +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails +import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage + +class NetworkImageDataSource(private val networkHandler: NetworkHandler) { + suspend fun getImage(directory: NetworkDirectoryDetails): SharedImage? = + if (networkHandler.isConnected) { + networkHandler.openImage(path = directory.fullPath) + } else null +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt index ddbc81b9..afb06f1d 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt @@ -1,11 +1,28 @@ package com.kevinschildhorn.fotopresenter.data.repositories -import com.kevinschildhorn.fotopresenter.data.datasources.ImageRemoteDataSource +import co.touchlab.kermit.Logger +import coil3.Image +import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource +import com.kevinschildhorn.fotopresenter.data.datasources.image.NetworkImageDataSource import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails -import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage class ImageRepository( - private val remoteDataSource: ImageRemoteDataSource, + private val remoteImageDataSource: NetworkImageDataSource, + private val localImageDataSource: CachedImageDataSource, + private val logger: Logger?, ) { - suspend fun getImage(directory: NetworkDirectoryDetails): SharedImage? = remoteDataSource.getImage(directory) -} + + suspend fun getCoilImage(directoryDetails: NetworkDirectoryDetails, size: Int): Image? { + logger?.i { "Getting Image from Cache" } + val cachedImage = localImageDataSource.getImage(directoryDetails) + if (cachedImage != null) return cachedImage.getCoilImage(size) + + logger?.i { "No cached image found, getting image from directory" } + val image = remoteImageDataSource.getImage(directoryDetails) + if(image != null) { + logger?.i { "Storing image in cache" } + localImageDataSource.saveImage(directoryDetails, image) + } + return image?.getCoilImage(size) + } +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt index 8f88a152..869f0697 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt @@ -2,18 +2,13 @@ package com.kevinschildhorn.fotopresenter.domain import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.data.DirectoryContents -import com.kevinschildhorn.fotopresenter.data.ImageDirectory -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository -import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository -import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage /** Retrieving Directory Contents from Path **/ class RetrieveDirectoryContentsUseCase( private val directoryRepository: DirectoryRepository, - private val imageRepository: ImageRepository, private val logger: Logger, ) { suspend operator fun invoke(path: String): DirectoryContents { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt index cc2efaa8..6638bccc 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt @@ -1,36 +1,35 @@ package com.kevinschildhorn.fotopresenter.domain.image -import androidx.compose.ui.graphics.ImageBitmap import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.data.ImageDirectory -import com.kevinschildhorn.fotopresenter.data.State -import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource +import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage /** Retrieving Image Bitmap **/ class RetrieveImageUseCase( - private val imageCacheDataSource: ImageCacheDataSource, + private val cachedImageDataSource: CachedImageDataSource, private val logger: Logger, ) { suspend operator fun invoke( directory: ImageDirectory, imageSize: Int, - ): ImageBitmap? { + ): SharedImage? { val imageName = "\"${directory.details.fullPath}\"" logger.i { "Starting to get Image $imageName" } - imageCacheDataSource.getImage(directory.details)?.let { + cachedImageDataSource.getImage(directory.details)?.let { logger.i { "$imageName found in cache, using that" } return it } logger.i { "Getting Image Bitmap from File ${directory.name}" } - val imageBitmap: ImageBitmap? = directory.image?.getImageBitmap(imageSize) + val imageBitmap: SharedImage? = directory.image imageBitmap?.let { logger.i { "Caching new Image ${directory.name}" } - imageCacheDataSource.saveImage(directory.details, it) + cachedImageDataSource.saveImage(directory.details, it) } return imageBitmap } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt new file mode 100644 index 00000000..070daf5f --- /dev/null +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt @@ -0,0 +1,42 @@ +package com.kevinschildhorn.fotopresenter.ui + +import coil3.ImageLoader +import coil3.decode.DataSource +import coil3.fetch.FetchResult +import coil3.fetch.Fetcher +import coil3.fetch.ImageFetchResult +import coil3.request.Options +import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage + +class ByteArrayFetcher( + private val byteArray: ByteArray, + private val networkHandler: NetworkHandler, +) : Fetcher { + + override suspend fun fetch(): FetchResult? { + return withContext(Dispatchers.IO) { + val image = SharedImage(byteArray) + val coilImage = image.getCoilImage(64) + if (coilImage != null) { + ImageFetchResult( + image = coilImage, + isSampled = true, + dataSource = DataSource.NETWORK, + ) + } else { + throw Exception("Failed to fetch image from FTP") + } + } + } + + class Factory(private val networkHandler: NetworkHandler) : Fetcher.Factory { + override fun create( + data: ByteArray, + options: Options, + imageLoader: ImageLoader + ): Fetcher = ByteArrayFetcher(data, networkHandler) + } +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/ImageScreenState.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/ImageScreenState.kt index fbe2814d..b8a6297f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/ImageScreenState.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/ImageScreenState.kt @@ -1,12 +1,12 @@ package com.kevinschildhorn.fotopresenter.ui.screens.common -import androidx.compose.ui.graphics.ImageBitmap import com.kevinschildhorn.fotopresenter.data.ImageDirectory +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage data class ImageScreenState( val imageDirectories: List = emptyList(), val selectedImageIndex: Int? = null, - val selectedImage: ImageBitmap? = null, + val selectedImage: SharedImage? = null, ) { val selectedImageDirectory: ImageDirectory? get() = diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/ImageViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/ImageViewModel.kt index 37f3400d..5dee6c8a 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/ImageViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/ImageViewModel.kt @@ -1,22 +1,19 @@ package com.kevinschildhorn.fotopresenter.ui.screens.common -import androidx.compose.ui.graphics.ImageBitmap import co.touchlab.kermit.Logger +import com.kevinschildhorn.fotopresenter.UseCaseFactory import com.kevinschildhorn.fotopresenter.data.ImageDirectory -import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.extension.getNextIndex import com.kevinschildhorn.fotopresenter.extension.getPreviousIndex import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job +import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent -import com.kevinschildhorn.fotopresenter.UseCaseFactory -import kotlinx.coroutines.cancelChildren interface ImageViewModel { var scope: CoroutineScope? diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ImagePreviewOverlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ImagePreviewOverlay.kt index 36921b5f..0fe2e779 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ImagePreviewOverlay.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ImagePreviewOverlay.kt @@ -1,9 +1,5 @@ package com.kevinschildhorn.fotopresenter.ui.screens.common.composables -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -12,23 +8,21 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material.Button -import androidx.compose.material.ButtonDefaults -import androidx.compose.material.Icon import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.unit.dp +import coil3.compose.AsyncImage import com.kevinschildhorn.fotopresenter.ui.atoms.Padding import compose.icons.EvaIcons import compose.icons.evaicons.Fill import compose.icons.evaicons.fill.ArrowLeft import compose.icons.evaicons.fill.ArrowRight +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage @Composable fun ImagePreviewOverlay( - image: ImageBitmap, + image: SharedImage, visible: Boolean, onDismiss: () -> Unit, onBack: () -> Unit, @@ -45,8 +39,8 @@ fun ImagePreviewOverlay( verticalArrangement = Arrangement.SpaceBetween, ) { // imageState.onSuccess { - Image( - bitmap = image, + AsyncImage( + model = image, contentDescription = null, modifier = Modifier diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt index 18def33b..9202b58f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt @@ -3,12 +3,7 @@ package com.kevinschildhorn.fotopresenter.ui.screens.directory import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.LinearProgressIndicator -import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState @@ -17,14 +12,9 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails import com.kevinschildhorn.fotopresenter.ui.UiState -import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography import com.kevinschildhorn.fotopresenter.ui.atoms.Padding -import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors import com.kevinschildhorn.fotopresenter.ui.screens.common.ActionSheetAction import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ActionSheet import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ConfirmationDialog diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowScreen.kt index 3fafd7bc..a7878dee 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowScreen.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import coil3.compose.AsyncImage import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.LoadingOverlay import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.Overlay import compose.icons.EvaIcons @@ -59,10 +60,10 @@ fun SlideshowScreen( } Box(modifier = Modifier.fillMaxSize().background(Color.Black)) { - imageState.selectedImage?.let { bitmap -> + imageState.selectedImage?.let { sharedImage -> Crossfade(imageState.selectedImageIndex, animationSpec = tween(500)){ - Image( - bitmap = bitmap, + AsyncImage( + model = sharedImage, contentDescription = null, modifier = Modifier.fillMaxSize(), ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt index 697f19e8..52c02f14 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt @@ -1,39 +1,42 @@ package com.kevinschildhorn.fotopresenter.ui.shared -import androidx.compose.ui.graphics.ImageBitmap import io.github.reactivecircus.cache4k.Cache interface CacheInterface { - fun getImage(id: String): ImageBitmap? + fun getImage(id: String): SharedImage? fun cacheImage( id: String, - imageBitmap: ImageBitmap, + image: SharedImage, ) } -object SharedCache : CacheInterface { - private val imageCache = Cache.Builder().build() +object SharedInMemoryCache : CacheInterface { + private val imageCache = Cache.Builder().build() - override fun getImage(id: String): ImageBitmap? = imageCache.get(id) + override fun getImage(id: String): SharedImage? = imageCache.get(id)?.let { + SharedImage(it) + } override fun cacheImage( id: String, - imageBitmap: ImageBitmap, + image: SharedImage, ) { - imageCache.put(id, imageBitmap) + imageCache.put(id, image.byteArray) } } class MockSharedCache : CacheInterface { - val contents = mutableMapOf() + private val contents = mutableMapOf() override fun cacheImage( id: String, - imageBitmap: ImageBitmap, + image: SharedImage, ) { - contents[id] = imageBitmap + contents[id] = image.byteArray } - override fun getImage(id: String): ImageBitmap? = contents[id] + override fun getImage(id: String): SharedImage? = contents[id]?.let { + SharedImage(it) + } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index 14dd76ef..2ed8c1b6 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -1,8 +1,28 @@ package com.kevinschildhorn.fotopresenter.ui.shared -import androidx.compose.ui.graphics.ImageBitmap +import coil3.Image + +expect class SharedImage(byteArray: ByteArray) { -expect class SharedImage { - fun getImageBitmap(size: Int): ImageBitmap? val byteArray: ByteArray + fun getCoilImage(size: Int): Image? } + +fun getScaledDimensions( + width: Int, + height: Int, + minSize: Int, +): Pair { + val newWidth: Float + val newHeight: Float + if (height < width) { + newHeight = minSize.toFloat() + val ratio: Float = (newHeight / height) + newWidth = width * ratio + } else { + newWidth = minSize.toFloat() + val ratio: Float = (newWidth / width) + newHeight = height * ratio + } + return Pair(newWidth.toInt(), newHeight.toInt()) +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt deleted file mode 100644 index 6eae73a1..00000000 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.kevinschildhorn.fotopresenter.ui.shared - -import androidx.compose.ui.graphics.ImageBitmap - -expect object SharedImageConverter { - fun convertBytes(byteArray: ByteArray): ImageBitmap - - fun convertImage(imageBitmap: ImageBitmap): ByteArray -} - -fun getScaledDimensions( - width: Int, - height: Int, - minSize: Int, -): Pair { - val newWidth: Float - val newHeight: Float - if (height < width) { - newHeight = minSize.toFloat() - val ratio: Float = (newHeight / height) - newWidth = width * ratio - } else { - newWidth = minSize.toFloat() - val ratio: Float = (newWidth / width) - newHeight = height * ratio - } - return Pair(newWidth.toInt(), newHeight.toInt()) -} diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSourceTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageFileRemoteDataSourceTest.kt similarity index 93% rename from shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSourceTest.kt rename to shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageFileRemoteDataSourceTest.kt index 4f7acf8f..09f9e084 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSourceTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageFileRemoteDataSourceTest.kt @@ -13,11 +13,11 @@ import kotlin.test.assertNull import kotlin.test.fail /** -Testing [ImageRemoteDataSource] +Testing [ImageFileRemoteDataSource] **/ -class ImageRemoteDataSourceTest { +class ImageFileRemoteDataSourceTest { private val networkHandler: MockNetworkHandler = MockNetworkHandler - private val dataSource = ImageRemoteDataSource(networkHandler) + private val dataSource = ImageFileRemoteDataSource(networkHandler) @BeforeTest fun startTest() = diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepositoryTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepositoryTest.kt deleted file mode 100644 index 2babcf5b..00000000 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepositoryTest.kt +++ /dev/null @@ -1,89 +0,0 @@ -package com.kevinschildhorn.fotopresenter.data.repositories - -import com.kevinschildhorn.fotopresenter.data.network.DefaultNetworkDirectoryDetails -import com.kevinschildhorn.fotopresenter.data.network.MockNetworkHandler -import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerError -import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException -import com.kevinschildhorn.fotopresenter.testingModule -import kotlinx.coroutines.runBlocking -import org.koin.core.context.startKoin -import org.koin.core.context.stopKoin -import org.koin.test.KoinTest -import org.koin.test.inject -import kotlin.test.AfterTest -import kotlin.test.BeforeTest -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNull -import kotlin.test.fail - -/** -Testing [ImageRepository] - **/ -class ImageRepositoryTest : KoinTest { - private val networkHandler: MockNetworkHandler = MockNetworkHandler - private val repository: ImageRepository by inject() - - @BeforeTest - fun startTest() = - runBlocking { - startKoin { - modules(testingModule()) - } - networkHandler.connectSuccessfully() - } - - @AfterTest - fun tearDown() = - runBlocking { - stopKoin() - networkHandler.disconnect() - } - - @Test - fun `get Image Success`() = - runBlocking { - try { - val result = - repository.getImage( - DefaultNetworkDirectoryDetails( - fullPath = "Photos/Success.png", - id = 1, - ), - ) - } catch (e: Exception) { - assertEquals("Success", e.message) - } - } - - @Test - fun `get Image Failure`() = - runBlocking { - val result = - repository.getImage( - DefaultNetworkDirectoryDetails( - fullPath = "Photos/nonExistant.png", - id = 1, - ), - ) - assertNull(result) - } - - @Test - fun `get Image Disconnected`() = - runBlocking { - networkHandler.disconnect() - try { - val result = - repository.getImage( - DefaultNetworkDirectoryDetails( - fullPath = "Photos/nonExistant.png", - id = 1, - ), - ) - fail("Should Throw Exception") - } catch (e: NetworkHandlerException) { - assertEquals(e.message, NetworkHandlerError.NOT_CONNECTED.message) - } - } -} diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt index 460b0abf..d621ec4b 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt @@ -1,19 +1,15 @@ package com.kevinschildhorn.fotopresenter -import co.touchlab.kermit.Logger -import co.touchlab.kermit.LoggerConfig import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource -import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource +import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource import com.kevinschildhorn.fotopresenter.data.datasources.ImageMetadataDataSource -import com.kevinschildhorn.fotopresenter.data.datasources.ImageRemoteDataSource import com.kevinschildhorn.fotopresenter.data.datasources.PlaylistFileDataSource import com.kevinschildhorn.fotopresenter.data.datasources.PlaylistSQLDataSource import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler import com.kevinschildhorn.fotopresenter.data.network.SMBJHandler import com.kevinschildhorn.fotopresenter.data.repositories.CredentialsRepository import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository -import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository import com.kevinschildhorn.fotopresenter.data.repositories.PlaylistRepository import com.kevinschildhorn.fotopresenter.domain.RetrieveDirectoryContentsUseCase import com.kevinschildhorn.fotopresenter.domain.connection.AutoConnectUseCase @@ -26,7 +22,7 @@ import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageUseCase import com.kevinschildhorn.fotopresenter.domain.image.RetrieveSlideshowFromPlaylistUseCase import com.kevinschildhorn.fotopresenter.domain.image.SaveMetadataForPathUseCase import com.kevinschildhorn.fotopresenter.ui.shared.DriverFactory -import com.kevinschildhorn.fotopresenter.ui.shared.SharedCache +import com.kevinschildhorn.fotopresenter.ui.shared.SharedInMemoryCache import com.russhwolf.settings.PreferencesSettings import java.util.prefs.Preferences @@ -47,7 +43,6 @@ actual object UseCaseFactory { logger = baseLogger.withTag("imageMetadataDataSource") ) private val directoryRepository = DirectoryRepository(directoryDataSource, imageMetadataDataSource) - private val imageRepository = ImageRepository(ImageRemoteDataSource(networkHandler)) private val playlistSQLDataSource = PlaylistSQLDataSource( sqlDriver, com.kevinschildhorn.fotopresenter.baseLogger @@ -101,13 +96,12 @@ actual object UseCaseFactory { actual val retrieveDirectoryContentsUseCase: RetrieveDirectoryContentsUseCase get() = RetrieveDirectoryContentsUseCase( directoryRepository = directoryRepository, - imageRepository = imageRepository, logger = baseLogger.withTag("RetrieveDirectoryContentsUseCase") ) actual val retrieveImageUseCase: RetrieveImageUseCase get() = RetrieveImageUseCase( - imageCacheDataSource = ImageCacheDataSource( - cache = SharedCache, + cachedImageDataSource = CachedImageDataSource( + cache = SharedInMemoryCache, driver = sqlDriver, logger = baseLogger.withTag("ImageCacheDataSource") ), diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt deleted file mode 100644 index feda2259..00000000 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.kevinschildhorn.fotopresenter.ui.shared - -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.res.loadImageBitmap -import com.hierynomus.smbj.share.File - -actual fun getBitmapFromFile(file: File, size:Int): ImageBitmap? = - file.inputStream.buffered().use(::loadImageBitmap) - diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt deleted file mode 100644 index eac3ecad..00000000 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageConverter.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.kevinschildhorn.fotopresenter.ui.shared - -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.asSkiaBitmap -import androidx.compose.ui.graphics.toComposeImageBitmap -import org.jetbrains.skia.Image -import kotlin.jvm.Throws - -actual object SharedImageConverter { - actual fun convertBytes(byteArray: ByteArray): ImageBitmap { - return Image.makeFromEncoded(byteArray).toComposeImageBitmap() - } - - @Throws(Exception::class) - actual fun convertImage(imageBitmap: ImageBitmap): ByteArray { - return Image.makeFromBitmap(imageBitmap.asSkiaBitmap()).encodeToData()?.bytes!! - } -} \ No newline at end of file diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt new file mode 100644 index 00000000..f0aca7c0 --- /dev/null +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt @@ -0,0 +1,10 @@ +package com.kevinschildhorn.fotopresenter.ui.shared + +import coil3.Image + + +actual open class SharedImage actual constructor(actual val byteArray: ByteArray) { + // TODO + actual fun getCoilImage(size: Int): Image? = null +} + diff --git a/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageIos.kt similarity index 100% rename from shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt rename to shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageIos.kt diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt index 9f7aa7c0..422f7a4e 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt @@ -105,8 +105,10 @@ object SMBJHandler : NetworkHandler { } override suspend fun openImage(path: String): SharedImage? = - getFile(path)?.let { - val sharedImage = SharedImage(it) + getFile(path)?.let { file -> + val byteArray = file.inputStream.readAllBytes() + file.close() + val sharedImage = SharedImage(byteArray) sharedImage } ?: run { null } diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt new file mode 100644 index 00000000..ba19b311 --- /dev/null +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt @@ -0,0 +1,43 @@ +package com.kevinschildhorn.fotopresenter.ui + +import coil3.ImageLoader +import coil3.decode.DataSource +import coil3.fetch.FetchResult +import coil3.fetch.Fetcher +import coil3.fetch.ImageFetchResult +import coil3.request.Options +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails +import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +// ImageRepository +class SMBJFetcher( + private val directoryDetails: NetworkDirectoryDetails, + private val imageRepository: ImageRepository, +) : Fetcher { + + override suspend fun fetch(): FetchResult? { + return withContext(Dispatchers.IO) { + val image = imageRepository.getCoilImage(directoryDetails, 64) + if(image != null) { + ImageFetchResult( + image = image, + isSampled = true, + dataSource = DataSource.NETWORK, + ) + } else { + null + } + } + } + + class Factory(private val imageRepository: ImageRepository) : + Fetcher.Factory { + override fun create( + data: NetworkDirectoryDetails, + options: Options, + imageLoader: ImageLoader + ): Fetcher = SMBJFetcher(data, imageRepository) + } +} \ No newline at end of file diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt deleted file mode 100644 index 2a95e3f1..00000000 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.kevinschildhorn.fotopresenter.ui.shared - -import androidx.compose.ui.graphics.ImageBitmap -import com.hierynomus.smbj.share.File - -actual open class SharedImage(val file: File) { - actual fun getImageBitmap(size: Int): ImageBitmap? = getBitmapFromFile(file, size) - actual val byteArray: ByteArray = file.inputStream.readAllBytes() -} - -expect fun getBitmapFromFile(file: File, size: Int): ImageBitmap? - From a7be9567c496906af31a017570e266110d56b74f Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Wed, 16 Oct 2024 13:44:09 -0400 Subject: [PATCH 15/19] Updating how we get images --- androidApp/build.gradle.kts | 4 +- .../com/kevinschildhorn/MainActivity.kt | 30 ++++++-- desktopApp/src/jvmMain/kotlin/Main.kt | 31 +++++++++ gradle/libs.versions.toml | 6 +- shared/build.gradle.kts | 4 +- .../fotopresenter/KoinAndroid.kt | 6 ++ .../ui/shared/SharedImageAndroid.kt | 16 ++++- .../com/kevinschildhorn/fotopresenter/Koin.kt | 9 ++- .../image/CachedImageDataSource.kt | 42 ++++-------- .../data/repositories/ImageRepository.kt | 23 +++++-- .../fotopresenter/ui/ByteArrayFetcher.kt | 22 +++--- .../fotopresenter/ui/shared/SharedCache.kt | 68 +++++++++++++++++-- .../fotopresenter/ui/shared/SharedImage.kt | 4 +- .../ui/shared/SharedImageDesktop.kt | 22 +++++- .../fotopresenter/ui/SMBJFetcher.kt | 28 ++++---- 15 files changed, 227 insertions(+), 88 deletions(-) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 1d80406e..e6475ce4 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -19,7 +19,9 @@ kotlin { implementation(project(":shared")) implementation(libs.koin.android) implementation(libs.firebase.crashlytics) - implementation(libs.coil) + implementation(libs.accompanist.permissions) + implementation(libs.kermit) + } } } diff --git a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt index 4e9ea81a..2cd0d8ea 100644 --- a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt +++ b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt @@ -1,16 +1,25 @@ package com.kevinschildhorn import MainView +import android.Manifest import android.os.Bundle import androidx.activity.compose.setContent +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity +import co.touchlab.kermit.Logger import coil3.ImageLoader import coil3.compose.setSingletonImageLoaderFactory -import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource -import com.kevinschildhorn.fotopresenter.ui.SMBJFetcher -import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler +import coil3.disk.DiskCache +import coil3.disk.directory +import coil3.memory.MemoryCache +import com.google.accompanist.permissions.ExperimentalPermissionsApi +import com.google.accompanist.permissions.rememberPermissionState +import com.kevinschildhorn.fotopresenter.baseLogger +import com.kevinschildhorn.fotopresenter.data.network.SMBJHandler import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository import com.kevinschildhorn.fotopresenter.startKoin +import com.kevinschildhorn.fotopresenter.ui.ByteArrayFetcher +import com.kevinschildhorn.fotopresenter.ui.SMBJFetcher import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel @@ -32,10 +41,23 @@ class MainActivity : AppCompatActivity(), KoinComponent { startKoin(this) setContent { + setSingletonImageLoaderFactory { context -> ImageLoader.Builder(context) .components { - add(SMBJFetcher.Factory(imageRepository)) + add(SMBJFetcher.Factory(imageRepository, baseLogger)) + add(ByteArrayFetcher.Factory(Logger.withTag("ByteArrayFetcher"))) + } + .memoryCache { + MemoryCache.Builder() + .maxSizePercent(context,0.25) + .build() + } + .diskCache { + DiskCache.Builder() + .directory(context.cacheDir.resolve("image_cache")) + .maxSizePercent(0.02) + .build() } .build() } diff --git a/desktopApp/src/jvmMain/kotlin/Main.kt b/desktopApp/src/jvmMain/kotlin/Main.kt index 44a8bfbf..823b05cb 100644 --- a/desktopApp/src/jvmMain/kotlin/Main.kt +++ b/desktopApp/src/jvmMain/kotlin/Main.kt @@ -1,14 +1,29 @@ +import KoinPurse.imageRepository import androidx.compose.ui.window.Window import androidx.compose.ui.window.application import co.touchlab.kermit.Logger +import coil3.ImageLoader import com.kevinschildhorn.fotopresenter.UseCaseFactory +import com.kevinschildhorn.fotopresenter.baseLogger +import com.kevinschildhorn.fotopresenter.ui.SMBJFetcher import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel +import coil3.compose.setSingletonImageLoaderFactory +import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource +import com.kevinschildhorn.fotopresenter.data.datasources.image.NetworkImageDataSource +import com.kevinschildhorn.fotopresenter.data.network.SMBJHandler +import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository +import com.kevinschildhorn.fotopresenter.ui.ByteArrayFetcher +import com.kevinschildhorn.fotopresenter.ui.shared.SharedFileCache object KoinPurse { + private val remoteImageDataSource: NetworkImageDataSource = NetworkImageDataSource(SMBJHandler) + private val localImageDataSource: CachedImageDataSource = + CachedImageDataSource(SharedFileCache("cache"), Logger.withTag("CachedImageDataSource")) + val loginViewModel = LoginViewModel(Logger.withTag("LoginViewModel"), UseCaseFactory.credentialsRepository) val directoryViewModel = @@ -16,6 +31,12 @@ object KoinPurse { val slideshowViewModel = SlideshowViewModel(Logger.withTag("SlideshowViewModel")) val playlistViewModel = PlaylistViewModel(UseCaseFactory.playlistRepository, Logger.withTag("PlaylistViewModel")) + val imageRepository = + ImageRepository( + remoteImageDataSource, + localImageDataSource, + Logger.withTag("ImageRepository") + ) } fun main() = application { @@ -23,6 +44,16 @@ fun main() = application { title = "FotoPresenter", onCloseRequest = ::exitApplication ) { + + setSingletonImageLoaderFactory { context -> + ImageLoader.Builder(context) + .components { + add(SMBJFetcher.Factory(imageRepository, Logger.withTag("SMBJFetcher"))) + add(ByteArrayFetcher.Factory(Logger.withTag("ByteArrayFetcher"))) + } + .build() + } + MainView( KoinPurse.loginViewModel, KoinPurse.directoryViewModel, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4380afa6..d4ee9323 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,4 +1,5 @@ [versions] +accompanistPermissions = "0.36.0" activity-compose = "1.9.2" agp = "8.5.2" appcompat = "1.7.0" @@ -7,6 +8,7 @@ cache4k = "0.12.0" coil = "3.0.0-rc01" core-ktx = "1.13.1" eva-icons = "1.1.0" +fileKache = "2.1.0" firebase-crashlytics = "19.2.0" kermit = "2.0.4" kermit-koin = "1.2.2" @@ -33,12 +35,13 @@ sqlite-driver = "2.0.1" turbine = "1.0.0" ## SDK Versions -minSdk = "26" +minSdk = "29" targetSdk = "34" compileSdk = "34" java = "21" [libraries] +accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanistPermissions" } activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity-compose" } android-driver = { module = "app.cash.sqldelight:android-driver", version.ref = "sqlite-driver" } appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" } @@ -46,6 +49,7 @@ atomik = { module = "io.github.kevinschildhorn:atomik", version.ref = "atomik" } cache4k = { module = "io.github.reactivecircus.cache4k:cache4k", version.ref = "cache4k" } core-ktx = { module = "androidx.core:core-ktx", version.ref = "core-ktx" } eva-icons = { module = "br.com.devsrsouza.compose.icons:eva-icons", version.ref = "eva-icons" } +file-kache = { module = "com.mayakapps.kache:file-kache", version.ref = "fileKache" } firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics", version.ref = "firebase-crashlytics" } kermit = { module = "co.touchlab:kermit", version.ref = "kermit" } kermit-koin = { module = "co.touchlab:kermit-koin", version.ref = "kermit-koin" } diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 10ec4f1a..7ba6eca0 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -53,8 +53,8 @@ kotlin { implementation(libs.multiplatform.settings) implementation(libs.kotlinx.datetime) implementation(libs.kim) - implementation(libs.coil) - + api(libs.coil) + implementation(libs.file.kache) } } val commonTest by getting { diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt index b4b5b554..97bc6e85 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt @@ -8,7 +8,9 @@ import app.cash.sqldelight.db.SqlDriver import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler import com.kevinschildhorn.fotopresenter.data.network.SMBJHandler +import com.kevinschildhorn.fotopresenter.ui.shared.CacheInterface import com.kevinschildhorn.fotopresenter.ui.shared.DriverFactory +import com.kevinschildhorn.fotopresenter.ui.shared.SharedFileCache import com.russhwolf.settings.Settings import com.russhwolf.settings.SharedPreferencesSettings import org.koin.core.KoinApplication @@ -45,6 +47,10 @@ internal actual val platformModule: Module = module { SMBJHandler } single { DriverFactory(context = get()).createDriver() } + single { + val context:Context = get() + SharedFileCache(context.cacheDir.path) + } } @OptIn(KoinInternalApi::class) diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt index fd201678..65c4ebce 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt @@ -4,9 +4,23 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import coil3.Image import coil3.asImage +import coil3.decode.DataSource +import coil3.fetch.FetchResult +import coil3.fetch.ImageFetchResult actual open class SharedImage actual constructor(actual val byteArray: ByteArray) { - actual fun getCoilImage(size: Int): Image? = getAndroidBitmap(byteArray, size)?.asImage() + + actual fun getFetchResult(size: Int): FetchResult? { + val image: Image? = getAndroidBitmap(byteArray, size)?.asImage() + return if (image != null) ImageFetchResult( + image = image, + isSampled = true, + dataSource = DataSource.NETWORK, + ) + else null + } + + private fun getCoilImage(size: Int): Image? = getAndroidBitmap(byteArray, size)?.asImage() private fun getAndroidBitmap(byteArray: ByteArray, size: Int): Bitmap? { val options = BitmapFactory.Options() diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt index 5a83b919..c719efc3 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt @@ -3,10 +3,10 @@ package com.kevinschildhorn.fotopresenter import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource -import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource import com.kevinschildhorn.fotopresenter.data.datasources.ImageMetadataDataSource import com.kevinschildhorn.fotopresenter.data.datasources.PlaylistFileDataSource import com.kevinschildhorn.fotopresenter.data.datasources.PlaylistSQLDataSource +import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource import com.kevinschildhorn.fotopresenter.data.datasources.image.NetworkImageDataSource import com.kevinschildhorn.fotopresenter.data.repositories.CredentialsRepository import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository @@ -27,7 +27,7 @@ import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel import com.kevinschildhorn.fotopresenter.ui.shared.CacheInterface -import com.kevinschildhorn.fotopresenter.ui.shared.SharedInMemoryCache +import com.kevinschildhorn.fotopresenter.ui.shared.SharedFileCache import org.koin.core.module.Module import org.koin.dsl.module @@ -39,13 +39,12 @@ val commonModule = module { // Data - single { SharedInMemoryCache } single { NetworkImageDataSource(get()) } single { CredentialsDataSource(get()) } single { CredentialsRepository(get()) } single { DirectoryDataSource(get(), baseLogger.withTag("DirectoryDataSource")) } single { DirectoryRepository(get(), get()) } - single { CachedImageDataSource(get(), get(), baseLogger.withTag("ImageCacheDataSource")) } + single { CachedImageDataSource(get(), baseLogger.withTag("ImageCacheDataSource"), get()) } single { PlaylistFileDataSource(baseLogger.withTag("PlaylistDataSource"), get()) } single { PlaylistSQLDataSource(get(), baseLogger.withTag("PlaylistDataSource")) } single { PlaylistRepository(get(), get()) } @@ -77,7 +76,7 @@ val commonModule = baseLogger.withTag("RetrieveDirectoryContentsUseCase"), ) } - factory { RetrieveImageUseCase(get(), baseLogger.withTag("RetrieveImagesUseCase")) } + factory { RetrieveImageUseCase(get(), baseLogger.withTag("RetrieveImageUseCase")) } factory { SaveMetadataForPathUseCase(get()) } // UI single { LoginViewModel(baseLogger.withTag("LoginViewModel"), get()) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt index 3988dda7..98ed4bd7 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt @@ -1,60 +1,42 @@ package com.kevinschildhorn.fotopresenter.data.datasources.image -import androidx.collection.size import app.cash.sqldelight.db.SqlDriver import co.touchlab.kermit.Logger -import com.kevinschildhorn.fotopresenter.Image as SQLImage import com.kevinschildhorn.fotopresenter.PlaylistDatabase import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.ui.shared.CacheInterface import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage -import java.io.InputStream class CachedImageDataSource( private val cache: CacheInterface, + private val logger: Logger, driver: SqlDriver, - private val logger: Logger ) { private val database = PlaylistDatabase(driver) - fun getImage(directory: NetworkDirectoryDetails): SharedImage? { + suspend fun getImage(directory: NetworkDirectoryDetails): SharedImage? { logger.i { "Getting Image from Cache ${directory.cacheId}" } return try { - val image: SQLImage = database.imageQueries.selectImageByName(directory.cacheId).executeAsOne() - SharedImage(image.image) + cache.getImage(directory.cacheId) + //val image = database.imageQueries.selectImageByName(directory.cacheId).executeAsOne() + //SharedImage(image.image) } catch (e: Exception) { logger.e(e) { "Image NOT found" } + logger.e { e.localizedMessage ?: "" } null } } - fun saveImage(directory: NetworkDirectoryDetails, image: SharedImage) { + suspend fun saveImage(directory: NetworkDirectoryDetails, image: SharedImage) { logger.i { "Saving Image To Cache ${directory.cacheId}" } - database.imageQueries.insertImage( - directory.cacheId, - image.byteArray, - ) + cache.cacheImage(directory.cacheId, image) + //database.imageQueries.insertImage( + // directory.cacheId, + // image.byteArray, + //) logger.i { "Image Saved" } - //cache.cacheImage(directory.cacheId, image) TODO } private val NetworkDirectoryDetails.cacheId: String get() = "$name.$id" - - - fun readBlobInChunks(cursor: Cursor, columnIndex: Int): InputStream { - return object : InputStream() { - private var pos = 0 - private val blob = cursor.getBlob(columnIndex) - - override fun read(): Int { - if (pos >= blob.size) { - return -1 - } - return blob[pos++].toInt() and 0xFF - } - - // Implement other methods of InputStream if needed - } - } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt index afb06f1d..b5ed6bb8 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt @@ -1,10 +1,11 @@ package com.kevinschildhorn.fotopresenter.data.repositories import co.touchlab.kermit.Logger -import coil3.Image +import coil3.fetch.FetchResult import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource import com.kevinschildhorn.fotopresenter.data.datasources.image.NetworkImageDataSource import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage class ImageRepository( private val remoteImageDataSource: NetworkImageDataSource, @@ -12,17 +13,25 @@ class ImageRepository( private val logger: Logger?, ) { - suspend fun getCoilImage(directoryDetails: NetworkDirectoryDetails, size: Int): Image? { - logger?.i { "Getting Image from Cache" } + suspend fun getFetchResult(directoryDetails: NetworkDirectoryDetails, size: Int): FetchResult? { + val image = getImage(directoryDetails, size) + return image?.getFetchResult(size) + } + + private suspend fun getImage(directoryDetails: NetworkDirectoryDetails, size: Int): SharedImage? { + logger?.i { "Getting Image from Cache: ${directoryDetails.name}" } val cachedImage = localImageDataSource.getImage(directoryDetails) - if (cachedImage != null) return cachedImage.getCoilImage(size) + if (cachedImage != null) { + logger?.i { "Cached image found from Cache: ${directoryDetails.name}" } + return cachedImage + } logger?.i { "No cached image found, getting image from directory" } val image = remoteImageDataSource.getImage(directoryDetails) - if(image != null) { - logger?.i { "Storing image in cache" } + if (image != null) { + logger?.i { "Storing image in cache: ${directoryDetails.name}" } localImageDataSource.saveImage(directoryDetails, image) } - return image?.getCoilImage(size) + return image } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt index 070daf5f..e5a93dfe 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt @@ -1,10 +1,10 @@ package com.kevinschildhorn.fotopresenter.ui +import co.touchlab.kermit.Logger import coil3.ImageLoader import coil3.decode.DataSource import coil3.fetch.FetchResult import coil3.fetch.Fetcher -import coil3.fetch.ImageFetchResult import coil3.request.Options import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler import kotlinx.coroutines.Dispatchers @@ -13,30 +13,28 @@ import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage class ByteArrayFetcher( private val byteArray: ByteArray, - private val networkHandler: NetworkHandler, + private val logger: Logger, ) : Fetcher { override suspend fun fetch(): FetchResult? { return withContext(Dispatchers.IO) { val image = SharedImage(byteArray) - val coilImage = image.getCoilImage(64) - if (coilImage != null) { - ImageFetchResult( - image = coilImage, - isSampled = true, - dataSource = DataSource.NETWORK, - ) + val result = image.getFetchResult(64) + if (result != null) { + logger.i { "Image Got!" } + result } else { - throw Exception("Failed to fetch image from FTP") + logger.i { "No Image Fetched" } + null } } } - class Factory(private val networkHandler: NetworkHandler) : Fetcher.Factory { + class Factory(private val logger: Logger) : Fetcher.Factory { override fun create( data: ByteArray, options: Options, imageLoader: ImageLoader - ): Fetcher = ByteArrayFetcher(data, networkHandler) + ): Fetcher = ByteArrayFetcher(data, logger) } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt index 52c02f14..330b60a5 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt @@ -1,11 +1,14 @@ package com.kevinschildhorn.fotopresenter.ui.shared +import com.mayakapps.kache.FileKache +import com.mayakapps.kache.KacheStrategy import io.github.reactivecircus.cache4k.Cache +import java.io.File interface CacheInterface { - fun getImage(id: String): SharedImage? + suspend fun getImage(id: String): SharedImage? - fun cacheImage( + suspend fun cacheImage( id: String, image: SharedImage, ) @@ -14,11 +17,11 @@ interface CacheInterface { object SharedInMemoryCache : CacheInterface { private val imageCache = Cache.Builder().build() - override fun getImage(id: String): SharedImage? = imageCache.get(id)?.let { + override suspend fun getImage(id: String): SharedImage? = imageCache.get(id)?.let { SharedImage(it) } - override fun cacheImage( + override suspend fun cacheImage( id: String, image: SharedImage, ) { @@ -26,17 +29,68 @@ object SharedInMemoryCache : CacheInterface { } } +class SharedFileCache(private val cacheLocation: String) : CacheInterface { + + override suspend fun getImage(id: String): SharedImage? { + val cache = createCache() + + val test = cache?.get(id) + println(test) + val byteArray = cache?.get(id)?.toByteArray() + return if (byteArray != null) SharedImage(byteArray) else null + } + + override suspend fun cacheImage( + id: String, + image: SharedImage, + ) { + val cache = createCache() + try { + val imageData = cache?.put(id) { path -> + val file = File(path) + try { + val stream = file.outputStream() + stream.write(image.byteArray) + stream.close() + true + } catch (e: Exception) { + println(e.localizedMessage) + false + } + } + println(imageData) + } finally { + cache?.close() + } + } + + + private suspend fun createCache(): FileKache? { + try { + println("Creating Cache") + return FileKache(directory = cacheLocation, maxSize = 10 * 1024 * 1024) { + strategy = KacheStrategy.LRU + + } + } catch (e: Exception) { + println("Error Creating Cache") + println(e.localizedMessage) + return null + } + } +} + class MockSharedCache : CacheInterface { private val contents = mutableMapOf() - override fun cacheImage( + override suspend fun cacheImage( id: String, image: SharedImage, ) { contents[id] = image.byteArray } - override fun getImage(id: String): SharedImage? = contents[id]?.let { + override suspend fun getImage(id: String): SharedImage? = contents[id]?.let { SharedImage(it) } -} +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index 2ed8c1b6..30ec1611 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -1,11 +1,11 @@ package com.kevinschildhorn.fotopresenter.ui.shared -import coil3.Image +import coil3.fetch.FetchResult expect class SharedImage(byteArray: ByteArray) { val byteArray: ByteArray - fun getCoilImage(size: Int): Image? + fun getFetchResult(size: Int): FetchResult? } fun getScaledDimensions( diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt index f0aca7c0..0bc46fca 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt @@ -1,10 +1,28 @@ package com.kevinschildhorn.fotopresenter.ui.shared import coil3.Image +import coil3.decode.DataSource +import coil3.decode.ImageSource +import coil3.fetch.FetchResult +import coil3.fetch.SourceFetchResult +import okio.FileSystem +import okio.buffer +import okio.source +import java.io.ByteArrayInputStream actual open class SharedImage actual constructor(actual val byteArray: ByteArray) { - // TODO - actual fun getCoilImage(size: Int): Image? = null + actual fun getFetchResult(size: Int): FetchResult? { + val source = ByteArrayInputStream(byteArray).source().buffer() + + return SourceFetchResult( + source = ImageSource( + source = source, + fileSystem = FileSystem.SYSTEM, + ), + mimeType = null, + dataSource = DataSource.NETWORK, + ) + } } diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt index ba19b311..10403a10 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt @@ -1,5 +1,6 @@ package com.kevinschildhorn.fotopresenter.ui +import co.touchlab.kermit.Logger import coil3.ImageLoader import coil3.decode.DataSource import coil3.fetch.FetchResult @@ -15,29 +16,28 @@ import kotlinx.coroutines.withContext class SMBJFetcher( private val directoryDetails: NetworkDirectoryDetails, private val imageRepository: ImageRepository, + private val logger: Logger, ) : Fetcher { - override suspend fun fetch(): FetchResult? { - return withContext(Dispatchers.IO) { - val image = imageRepository.getCoilImage(directoryDetails, 64) - if(image != null) { - ImageFetchResult( - image = image, - isSampled = true, - dataSource = DataSource.NETWORK, - ) - } else { - null - } + override suspend fun fetch(): FetchResult? = withContext(Dispatchers.IO) { + logger.i { "Fetching image: ${directoryDetails.name}" } + + val image = imageRepository.getFetchResult(directoryDetails, 64) + if (image != null) { + logger.i { "Image Got! ${directoryDetails.name}" } + image + } else { + logger.i { "No Image Fetched: ${directoryDetails.name}" } + null } } - class Factory(private val imageRepository: ImageRepository) : + class Factory(private val imageRepository: ImageRepository, private val logger: Logger) : Fetcher.Factory { override fun create( data: NetworkDirectoryDetails, options: Options, imageLoader: ImageLoader - ): Fetcher = SMBJFetcher(data, imageRepository) + ): Fetcher = SMBJFetcher(data, imageRepository, logger) } } \ No newline at end of file From b7a8227c7481d8c4aa8051c63a04d1a8193b8868 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Wed, 16 Oct 2024 15:47:27 -0400 Subject: [PATCH 16/19] formatting --- .editorConfig | 4 + shared/build.gradle.kts | 3 +- shared/src/androidMain/kotlin/Main.android.kt | 2 +- .../fotopresenter/KoinAndroid.kt | 40 +++--- .../fotopresenter/UseCaseFactoryAndroid.kt | 5 +- .../ui/compose/CommonPreviews.kt | 18 +-- .../ui/compose/DirectoryPreviews.kt | 38 ++--- .../fotopresenter/ui/compose/LoginPreviews.kt | 6 +- .../ui/compose/PlaylistPreviews.kt | 13 +- .../fotopresenter/ui/shared/DriverFactory.kt | 2 +- .../ui/shared/SharedImageAndroid.kt | 9 +- .../fotopresenter/ui/shared/ViewModel.kt | 3 +- shared/src/commonMain/kotlin/App.kt | 6 +- .../com/kevinschildhorn/fotopresenter/Koin.kt | 8 +- .../fotopresenter/UseCaseFactory.kt | 2 +- .../fotopresenter/data/Directory.kt | 3 +- .../fotopresenter/data/ImageUtils.kt | 13 +- .../fotopresenter/data/LoginCredentials.kt | 16 +-- .../fotopresenter/data/MetadataDetails.kt | 4 +- .../fotopresenter/data/PlaylistDetails.kt | 4 +- .../fotopresenter/data/State.kt | 5 +- .../data/datasources/DirectoryDataSource.kt | 4 +- .../datasources/ImageMetadataDataSource.kt | 5 +- .../datasources/PlaylistFileDataSource.kt | 3 +- .../data/datasources/PlaylistSQLDataSource.kt | 18 ++- .../image/CachedImageDataSource.kt | 30 +--- .../image/NetworkImageDataSource.kt | 6 +- .../data/network/NetworkDirectoryDetails.kt | 6 +- .../data/network/NetworkHandler.kt | 9 +- .../data/repositories/DirectoryRepository.kt | 18 +-- .../data/repositories/ImageRepository.kt | 10 +- .../data/repositories/PlaylistRepository.kt | 14 +- .../image/RetrieveImageDirectoriesUseCase.kt | 9 +- .../domain/image/RetrieveImageUseCase.kt | 1 - .../RetrieveSlideshowFromPlaylistUseCase.kt | 45 +++--- .../image/SaveMetadataForPathUseCase.kt | 13 +- .../extension/StringExtensions.kt | 1 - .../fotopresenter/ui/ByteArrayFetcher.kt | 7 +- .../fotopresenter/ui/SortingType.kt | 2 +- .../fotopresenter/ui/UiState.kt | 5 - .../fotopresenter/ui/atoms/FotoColors.kt | 43 +++--- .../fotopresenter/ui/atoms/FotoTypography.kt | 48 ++++--- .../ui/screens/common/ImageViewModel.kt | 2 + .../screens/common/composables/ActionSheet.kt | 41 +++--- .../common/composables/DialogButtonText.kt | 30 ++-- .../screens/common/composables/ErrorView.kt | 1 - .../common/composables/FilterDialog.kt | 18 +-- .../screens/common/composables/FotoDIalog.kt | 25 ++-- .../common/composables/ImagePreviewOverlay.kt | 20 ++- .../ui/screens/common/composables/Overlay.kt | 35 +++-- .../common/composables/PrimaryButton.kt | 11 +- .../common/composables/PrimaryIconButton.kt | 3 +- .../common/composables/PrimaryTextButton.kt | 2 - .../common/composables/ToastOverlay.kt | 25 ++-- .../ui/screens/directory/DirectoryScreen.kt | 21 +-- .../screens/directory/DirectoryScreenState.kt | 20 +-- .../screens/directory/DirectoryViewModel.kt | 66 +++++---- .../composables/grid/DirectoryGrid.kt | 18 +-- .../navbar/DirectoryNavigationBar.kt | 11 +- .../navbar/DirectoryNavigationHome.kt | 12 +- .../navbar/DirectoryNavigationItem.kt | 15 +- .../navrail/DirectoryTitleBarButton.kt | 12 +- .../navrail/NavigationRailOverlay.kt | 12 +- .../ui/screens/login/LoginScreen.kt | 13 +- .../login/composables/LoginScreenForm.kt | 1 - .../login/composables/LoginTextField.kt | 10 +- .../ui/screens/playlist/PlaylistScreen.kt | 31 ++-- .../screens/playlist/PlaylistScreenState.kt | 4 +- .../ui/screens/playlist/PlaylistViewModel.kt | 16 +-- .../playlist/composables/PlaylistColumn.kt | 8 +- .../playlist/composables/PlaylistOverlay.kt | 4 +- .../composables/PlaylistScreenCreateRow.kt | 4 +- .../composables/PlaylistScreenPlaylistRow.kt | 12 +- .../playlist/composables/TextEntryDialog.kt | 10 +- .../playlist/composables/TextListDialog.kt | 4 +- .../ui/screens/slideshow/SlideshowScreen.kt | 64 ++++----- .../screens/slideshow/SlideshowScreenState.kt | 1 - .../screens/slideshow/SlideshowViewModel.kt | 12 +- .../fotopresenter/ui/shared/DriverFactory.kt | 2 +- .../fotopresenter/ui/shared/SharedCache.kt | 14 +- .../fotopresenter/ui/shared/SharedImage.kt | 4 +- .../kevinschildhorn/fotopresenter/KoinTest.kt | 3 - .../fotopresenter/StringTest.kt | 2 - .../datasources/ImageCacheDataSourceTest.kt | 26 ---- .../ImageMetadataDataSourceTest.kt | 66 ++++----- .../datasources/PlaylistFileDataSourceTest.kt | 101 ++++++------- .../datasources/PlaylistSQLDataSourceTest.kt | 52 +++---- .../data/network/MockNetworkHandler.kt | 124 ++++++++-------- .../domain/SaveCredentialsUseCaseTest.kt | 1 - .../ui/viewmodel/DirectoryViewModelTest.kt | 11 +- .../ui/viewmodel/LoginViewModelTest.kt | 3 - .../fotopresenter/KoinDesktop.kt | 17 +-- .../fotopresenter/UseCaseFactoryDesktop.kt | 133 ++++++++++-------- .../fotopresenter/ui/shared/DriverFactory.kt | 2 +- .../ui/shared/SharedImageDesktop.kt | 4 +- .../fotopresenter/ui/shared/ViewModel.kt | 2 +- .../fotopresenter/data/network/SMBJHandler.kt | 76 +++++----- .../network/SMBJNetworkDirectoryDetails.kt | 1 - .../fotopresenter/ui/SMBJFetcher.kt | 8 +- 99 files changed, 880 insertions(+), 867 deletions(-) create mode 100644 .editorConfig delete mode 100644 shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageCacheDataSourceTest.kt diff --git a/.editorConfig b/.editorConfig new file mode 100644 index 00000000..03e6d151 --- /dev/null +++ b/.editorConfig @@ -0,0 +1,4 @@ +root = true + +[*.{kt,kts}] +ktlint_function_naming_ignore_when_annotated_with=Composable \ No newline at end of file diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 10ec4f1a..b6280bc4 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -10,7 +10,7 @@ plugins { alias(libs.plugins.jetbrains.compose) alias(libs.plugins.ktlint) alias(libs.plugins.sqldelight) - //alias(libs.plugins.crashlytics) + // alias(libs.plugins.crashlytics) alias(libs.plugins.serialization) } @@ -54,7 +54,6 @@ kotlin { implementation(libs.kotlinx.datetime) implementation(libs.kim) implementation(libs.coil) - } } val commonTest by getting { diff --git a/shared/src/androidMain/kotlin/Main.android.kt b/shared/src/androidMain/kotlin/Main.android.kt index fd25cda6..193c4f9a 100644 --- a/shared/src/androidMain/kotlin/Main.android.kt +++ b/shared/src/androidMain/kotlin/Main.android.kt @@ -12,4 +12,4 @@ fun MainView( directoryViewModel: DirectoryViewModel, slideshowViewModel: SlideshowViewModel, playlistViewModel: PlaylistViewModel, - ) = App(loginViewModel, directoryViewModel, slideshowViewModel, playlistViewModel) +) = App(loginViewModel, directoryViewModel, slideshowViewModel, playlistViewModel) diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt index b4b5b554..f79c4035 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt @@ -26,26 +26,28 @@ fun startKoin(context: Context) { } } -internal actual val platformModule: Module = module { - single { - SharedPreferencesSettings( - delegate = EncryptedSharedPreferences.create( - get(), - CredentialsDataSource.DATABASE_NAME, - MasterKey.Builder(get()) - .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) - .build(), - EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, - EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM, - ), - commit = false, - ) +internal actual val platformModule: Module = + module { + single { + SharedPreferencesSettings( + delegate = + EncryptedSharedPreferences.create( + get(), + CredentialsDataSource.DATABASE_NAME, + MasterKey.Builder(get()) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build(), + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM, + ), + commit = false, + ) + } + single { + SMBJHandler + } + single { DriverFactory(context = get()).createDriver() } } - single { - SMBJHandler - } - single { DriverFactory(context = get()).createDriver() } -} @OptIn(KoinInternalApi::class) fun KoinApplication.androidContext(androidContext: Context): KoinApplication { diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryAndroid.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryAndroid.kt index e59af8d6..54367661 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryAndroid.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryAndroid.kt @@ -1,3 +1,5 @@ +@file:Suppress("ktlint:standard:filename") + package com.kevinschildhorn.fotopresenter import com.kevinschildhorn.fotopresenter.domain.RetrieveDirectoryContentsUseCase @@ -14,7 +16,6 @@ import org.koin.core.component.KoinComponent import org.koin.core.component.inject actual object UseCaseFactory : KoinComponent { - actual val connectToServerUseCase: ConnectToServerUseCase get() { val useCase: ConnectToServerUseCase by inject() @@ -65,4 +66,4 @@ actual object UseCaseFactory : KoinComponent { val useCase: SaveMetadataForPathUseCase by inject() return useCase } -} \ No newline at end of file +} diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/CommonPreviews.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/CommonPreviews.kt index 9f7c3569..f639a4fd 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/CommonPreviews.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/CommonPreviews.kt @@ -1,3 +1,5 @@ +@file:Suppress("ktlint:standard:class-naming") + package com.kevinschildhorn.fotopresenter.ui.compose import androidx.compose.foundation.layout.Column @@ -28,10 +30,11 @@ fun ActionSheetPreview() { ActionSheet( visible = true, offset = 200, - values = listOf( - ActionSheetContext(ActionSheetAction.START_SLIDESHOW, 1), - ActionSheetContext(ActionSheetAction.NONE, 2), - ), + values = + listOf( + ActionSheetContext(ActionSheetAction.START_SLIDESHOW, 1), + ActionSheetContext(ActionSheetAction.NONE, 2), + ), onClick = {}, onDismiss = {}, ) @@ -44,10 +47,8 @@ fun ConfirmationDialogPreview() { "Hello", "World", { - }, { - }, ) } @@ -59,10 +60,8 @@ fun TextConfirmationDialogPreview() { title = "", initialValue = "", { - }, { - }, ) } @@ -73,11 +72,8 @@ fun FilterDialogPreview() { FilterDialog( "Hello", { - }, { - }, ) } - diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt index d6fddee5..19c0cc04 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt @@ -3,14 +3,12 @@ package com.kevinschildhorn.fotopresenter.ui.compose import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview -import com.kevinschildhorn.fotopresenter.data.network.DefaultNetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.network.MockNetworkDirectoryDetails -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryGridCellState -import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.grid.DirectoryGridCell +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryGridState import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.grid.DirectoryGrid +import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.grid.DirectoryGridCell import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.grid.FolderDirectoryGridCell -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryGridState import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.navbar.DirectoryNavigationBar import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.navbar.DirectoryNavigationItem @@ -18,7 +16,7 @@ import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.navbar @Composable fun BaseDirectoryPreview() { Column { - DirectoryGridCell() {} + DirectoryGridCell {} } } @@ -26,7 +24,7 @@ fun BaseDirectoryPreview() { @Composable fun FolderDirectoryEmptyPreview() { Column { - FolderDirectoryGridCell(DirectoryGridCellState.Folder("Hello",0)) + FolderDirectoryGridCell(DirectoryGridCellState.Folder("Hello", 0)) } } @@ -34,14 +32,17 @@ fun FolderDirectoryEmptyPreview() { @Composable fun DirectoryGridPreview() { DirectoryGrid( - directoryContent = DirectoryGridState( - folderStates = listOf( - DirectoryGridCellState.Folder("Hello",0), + directoryContent = + DirectoryGridState( + folderStates = + listOf( + DirectoryGridCellState.Folder("Hello", 0), + ), + imageStates = + mutableListOf( + DirectoryGridCellState.Image(MockNetworkDirectoryDetails(), "Hello", 1), + ), ), - imageStates = mutableListOf( - DirectoryGridCellState.Image(MockNetworkDirectoryDetails(),"Hello", 1) - ) - ), onFolderPressed = {}, onImageDirectoryPressed = {}, onActionSheet = {}, @@ -50,18 +51,17 @@ fun DirectoryGridPreview() { @Preview @Composable -fun DirectoryNavigationItemPreview(){ - DirectoryNavigationItem("Photos"){ - +fun DirectoryNavigationItemPreview() { + DirectoryNavigationItem("Photos") { } } @Preview @Composable -fun DirectoryNavigationBarPreview(){ +fun DirectoryNavigationBarPreview() { DirectoryNavigationBar( - listOf("Photos1", "Subfolder1","Photos2", "Subfolder2","Photos3", "Subfolder3"), + listOf("Photos1", "Subfolder1", "Photos2", "Subfolder2", "Photos3", "Subfolder3"), + {}, {}, - {} ) } diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/LoginPreviews.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/LoginPreviews.kt index 18aad095..1bb20524 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/LoginPreviews.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/LoginPreviews.kt @@ -3,13 +3,13 @@ package com.kevinschildhorn.fotopresenter.ui.compose import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview +import com.kevinschildhorn.fotopresenter.ui.UiState import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ErrorView import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.TitleView +import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreenState import com.kevinschildhorn.fotopresenter.ui.screens.login.composables.LoginPasswordTextField -import com.kevinschildhorn.fotopresenter.ui.screens.login.composables.LoginTextField import com.kevinschildhorn.fotopresenter.ui.screens.login.composables.LoginScreenForm -import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreenState -import com.kevinschildhorn.fotopresenter.ui.UiState +import com.kevinschildhorn.fotopresenter.ui.screens.login.composables.LoginTextField @Preview @Composable diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/PlaylistPreviews.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/PlaylistPreviews.kt index 6908f64f..44ccf330 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/PlaylistPreviews.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/PlaylistPreviews.kt @@ -1,8 +1,6 @@ package com.kevinschildhorn.fotopresenter.ui.compose -import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.Button @@ -15,19 +13,17 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview -import com.kevinschildhorn.fotopresenter.Playlist import com.kevinschildhorn.fotopresenter.data.PlaylistDetails import com.kevinschildhorn.fotopresenter.ui.screens.playlist.composables.PlaylistColumn import com.kevinschildhorn.fotopresenter.ui.screens.playlist.composables.PlaylistOverlay import com.kevinschildhorn.fotopresenter.ui.screens.playlist.composables.PlaylistScreenCreateRow import com.kevinschildhorn.fotopresenter.ui.screens.playlist.composables.PlaylistScreenPlaylistRow - @Composable @Preview fun PlaylistRowsPreview() { Column(modifier = Modifier.fillMaxSize()) { - PlaylistScreenPlaylistRow("Playlist 1", {},{}, {}, {}) + PlaylistScreenPlaylistRow("Playlist 1", {}, {}, {}, {}) PlaylistScreenPlaylistRow("Playlist 2", {}, {}, {}, {}) PlaylistScreenCreateRow(onClick = {}) } @@ -37,12 +33,12 @@ fun PlaylistRowsPreview() { @Preview fun PlaylistColumnPreview() { PlaylistColumn( - listOf(PlaylistDetails(1,"Playlist 1"), PlaylistDetails(2, "Playlist 2")), + listOf(PlaylistDetails(1, "Playlist 1"), PlaylistDetails(2, "Playlist 2")), + {}, {}, {}, {}, {}, - {} ) } @@ -59,7 +55,7 @@ fun PlaylistOverlayPreview() { Text("Toggle") } PlaylistOverlay( - listOf(PlaylistDetails(1,"Playlist 1"), PlaylistDetails(2, "Playlist 2")), + listOf(PlaylistDetails(1, "Playlist 1"), PlaylistDetails(2, "Playlist 2")), overlaid = false, {}, {}, @@ -68,6 +64,5 @@ fun PlaylistOverlayPreview() { {}, {}, ) - } } diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/DriverFactory.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/DriverFactory.kt index 4392a3c1..aef1010e 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/DriverFactory.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/DriverFactory.kt @@ -9,4 +9,4 @@ actual class DriverFactory(private val context: Context) { actual fun createDriver(): SqlDriver { return AndroidSqliteDriver(PlaylistDatabase.Schema, context, "playlist.db") } -} \ No newline at end of file +} diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt index fd201678..17add46a 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt @@ -1,3 +1,5 @@ +@file:Suppress("ktlint:standard:filename") + package com.kevinschildhorn.fotopresenter.ui.shared import android.graphics.Bitmap @@ -8,7 +10,10 @@ import coil3.asImage actual open class SharedImage actual constructor(actual val byteArray: ByteArray) { actual fun getCoilImage(size: Int): Image? = getAndroidBitmap(byteArray, size)?.asImage() - private fun getAndroidBitmap(byteArray: ByteArray, size: Int): Bitmap? { + private fun getAndroidBitmap( + byteArray: ByteArray, + size: Int, + ): Bitmap? { val options = BitmapFactory.Options() options.inJustDecodeBounds = true BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options) @@ -23,4 +28,4 @@ actual open class SharedImage actual constructor(actual val byteArray: ByteArray options.inJustDecodeBounds = false return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options) } -} \ No newline at end of file +} diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/ViewModel.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/ViewModel.kt index 810ca1b3..45a70229 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/ViewModel.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/ViewModel.kt @@ -6,7 +6,8 @@ import androidx.lifecycle.viewModelScope as androidXViewModelScope actual abstract class ViewModel actual constructor() : ViewModel() { actual val viewModelScope: CoroutineScope = androidXViewModelScope + actual override fun onCleared() { super.onCleared() } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/App.kt b/shared/src/commonMain/kotlin/App.kt index aed9a377..c6114c6d 100644 --- a/shared/src/commonMain/kotlin/App.kt +++ b/shared/src/commonMain/kotlin/App.kt @@ -28,7 +28,7 @@ fun App( directoryViewModel: DirectoryViewModel, slideshowViewModel: SlideshowViewModel, playlistViewModel: PlaylistViewModel, - navController: NavHostController = rememberNavController() + navController: NavHostController = rememberNavController(), ) { MaterialTheme( colors = fotoColors, @@ -39,7 +39,7 @@ fun App( NavHost( navController = navController, startDestination = Screen.LOGIN.name, - modifier = Modifier.fillMaxSize().padding(innerPadding) + modifier = Modifier.fillMaxSize().padding(innerPadding), ) { composable(route = Screen.LOGIN.name) { LoginScreen(loginViewModel) { @@ -60,7 +60,7 @@ fun App( }, onShowPlaylists = { navController.navigate(Screen.PLAYLIST.name) - } + }, ) } composable(route = Screen.SLIDESHOW.name) { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt index 5a83b919..bbc09e74 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt @@ -3,10 +3,10 @@ package com.kevinschildhorn.fotopresenter import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource -import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource import com.kevinschildhorn.fotopresenter.data.datasources.ImageMetadataDataSource import com.kevinschildhorn.fotopresenter.data.datasources.PlaylistFileDataSource import com.kevinschildhorn.fotopresenter.data.datasources.PlaylistSQLDataSource +import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource import com.kevinschildhorn.fotopresenter.data.datasources.image.NetworkImageDataSource import com.kevinschildhorn.fotopresenter.data.repositories.CredentialsRepository import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository @@ -31,10 +31,8 @@ import com.kevinschildhorn.fotopresenter.ui.shared.SharedInMemoryCache import org.koin.core.module.Module import org.koin.dsl.module - val baseLogger = Logger.withTag("") - val commonModule = module { @@ -61,14 +59,14 @@ val commonModule = DisconnectFromServerUseCase( get(), get(), - baseLogger.withTag("DisconnectFromServerUseCase") + baseLogger.withTag("DisconnectFromServerUseCase"), ) } factory { RetrieveImageDirectoriesUseCase(baseLogger.withTag("RetrieveImageDirectoriesUseCase")) } factory { RetrieveSlideshowFromPlaylistUseCase( baseLogger.withTag("RetrieveSlideshowFromPlaylistUseCase"), - get() + get(), ) } factory { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactory.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactory.kt index d43e875b..82ac56fe 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactory.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactory.kt @@ -22,4 +22,4 @@ expect object UseCaseFactory { val retrieveDirectoryContentsUseCase: RetrieveDirectoryContentsUseCase val retrieveImageUseCase: RetrieveImageUseCase val saveMetadataForPathUseCase: SaveMetadataForPathUseCase -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt index f663b314..967a71e2 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt @@ -20,7 +20,8 @@ data class FolderDirectory( override fun toString(): String = "(F:${details.fullPath}:${details.id})" val isValid: Boolean - get() = name != ".." && + get() = + name != ".." && name.isNotEmpty() && name.isNotBlank() } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/ImageUtils.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/ImageUtils.kt index 08b825a8..a2d2e46d 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/ImageUtils.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/ImageUtils.kt @@ -1,8 +1,9 @@ package com.kevinschildhorn.fotopresenter.data -val supportedImageTypes = listOf( - "png", - "jpg", - "jpeg", - "bmp" -) \ No newline at end of file +val supportedImageTypes = + listOf( + "png", + "jpg", + "jpeg", + "bmp", + ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/LoginCredentials.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/LoginCredentials.kt index 3a450a43..efcd9960 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/LoginCredentials.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/LoginCredentials.kt @@ -19,13 +19,13 @@ data class LoginCredentials( override fun toString(): String { return """ - LoginCredentials( - hostname: $hostname - username: $username - password: $password - sharedFolder: $sharedFolder - shouldAutoConnect: $shouldAutoConnect - ) - """.trimIndent() + LoginCredentials( + hostname: $hostname + username: $username + password: $password + sharedFolder: $sharedFolder + shouldAutoConnect: $shouldAutoConnect + ) + """.trimIndent() } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/MetadataDetails.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/MetadataDetails.kt index e3faf36a..d33d6e8f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/MetadataDetails.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/MetadataDetails.kt @@ -4,7 +4,7 @@ import kotlinx.serialization.Serializable @Serializable data class MetadataDetails( - val files: MutableList + val files: MutableList, ) @Serializable @@ -14,4 +14,4 @@ data class MetadataFileDetails( ) { val tagsString: String get() = tags.joinToString(", ") -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/PlaylistDetails.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/PlaylistDetails.kt index 98972ffe..af0d37ed 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/PlaylistDetails.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/PlaylistDetails.kt @@ -30,6 +30,6 @@ data class PlaylistItem( id = item.id, playlistId = item.playlist_id, directoryPath = item.directory_path, - directoryId = item.directory_id + directoryId = item.directory_id, ) -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/State.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/State.kt index 5f43142b..0a3a7b6d 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/State.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/State.kt @@ -51,10 +51,9 @@ sealed class State { when (this) { is IDLE -> "Idle" is LOADING -> "Loading" - is ERROR -> "Error: ${message}" - is SUCCESS -> "Success:${data}" + is ERROR -> "Error: $message" + is SUCCESS -> "Success:$data" } } """.trimIndent() - } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/DirectoryDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/DirectoryDataSource.kt index 18bd4800..3a356cca 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/DirectoryDataSource.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/DirectoryDataSource.kt @@ -21,8 +21,8 @@ class DirectoryDataSource( if (!networkHandler.isConnected) throw NetworkHandlerException(NetworkHandlerError.NOT_CONNECTED) logger?.i { "Does the directory exist?" } - //val exists = networkHandler.folderExists(directoryName) - //logger?.i { "Does the directory exist? $exists" } + // val exists = networkHandler.folderExists(directoryName) + // logger?.i { "Does the directory exist? $exists" } logger?.i { "Opening the directory..." } networkHandler.openDirectory(directoryName)?.let { return it } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageMetadataDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageMetadataDataSource.kt index 739deb85..5813bb32 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageMetadataDataSource.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageMetadataDataSource.kt @@ -14,7 +14,6 @@ class ImageMetadataDataSource( private val logger: Logger?, private val networkHandler: NetworkHandler, ) { - suspend fun importMetaData(): MetadataDetails { logger?.i { "Importing Metadata" } networkHandler.getMetadata()?.let { @@ -56,9 +55,9 @@ class ImageMetadataDataSource( return MetadataFileDetails( filePath = filePath, - tags = keywords.toSet() + tags = keywords.toSet(), ) } return null } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistFileDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistFileDataSource.kt index 38074427..0dc16c80 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistFileDataSource.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistFileDataSource.kt @@ -11,7 +11,6 @@ class PlaylistFileDataSource( private val logger: Logger?, private val networkHandler: NetworkHandler, ) : KoinComponent { - suspend fun importPlaylists(): List = networkHandler.getPlaylists().mapNotNull { try { @@ -41,4 +40,4 @@ class PlaylistFileDataSource( } return true } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistSQLDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistSQLDataSource.kt index 270739f8..82d28485 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistSQLDataSource.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistSQLDataSource.kt @@ -15,10 +15,12 @@ class PlaylistSQLDataSource( driver: SqlDriver, private val logger: Logger? = null, ) : KoinComponent { - private val database = PlaylistDatabase(driver) - fun createPlaylist(name: String, directories: List = emptyList()): Playlist? { + fun createPlaylist( + name: String, + directories: List = emptyList(), + ): Playlist? { return try { logger?.i { "Creating Playlist $name with images: ${directories.count()}" } database.playlistQueries.insertPlaylist(name) @@ -74,7 +76,10 @@ class PlaylistSQLDataSource( } } - fun insertPlaylistImage(playlistId: Long, directory: Directory): PlaylistItem? { + fun insertPlaylistImage( + playlistId: Long, + directory: Directory, + ): PlaylistItem? { logger?.i { "Inserting Playlist Image ${directory.name}" } database.playlistItemsQueries.insertPlaylistImage( playlist_id = playlistId, @@ -84,7 +89,10 @@ class PlaylistSQLDataSource( return getPlaylistImage(playlistId, directory.details.fullPath) } - fun getPlaylistImage(playlistId: Long, directoryPath: String): PlaylistItem? { + fun getPlaylistImage( + playlistId: Long, + directoryPath: String, + ): PlaylistItem? { return try { logger?.i { "Selecting Playlist Image $playlistId" } val image: PlaylistItems = @@ -107,4 +115,4 @@ class PlaylistSQLDataSource( false } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt index 3988dda7..ad51c562 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt @@ -1,19 +1,17 @@ package com.kevinschildhorn.fotopresenter.data.datasources.image -import androidx.collection.size import app.cash.sqldelight.db.SqlDriver import co.touchlab.kermit.Logger -import com.kevinschildhorn.fotopresenter.Image as SQLImage import com.kevinschildhorn.fotopresenter.PlaylistDatabase import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.ui.shared.CacheInterface import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage -import java.io.InputStream +import com.kevinschildhorn.fotopresenter.Image as SQLImage class CachedImageDataSource( private val cache: CacheInterface, driver: SqlDriver, - private val logger: Logger + private val logger: Logger, ) { private val database = PlaylistDatabase(driver) @@ -28,33 +26,19 @@ class CachedImageDataSource( } } - fun saveImage(directory: NetworkDirectoryDetails, image: SharedImage) { + fun saveImage( + directory: NetworkDirectoryDetails, + image: SharedImage, + ) { logger.i { "Saving Image To Cache ${directory.cacheId}" } database.imageQueries.insertImage( directory.cacheId, image.byteArray, ) logger.i { "Image Saved" } - //cache.cacheImage(directory.cacheId, image) TODO + // cache.cacheImage(directory.cacheId, image) TODO } private val NetworkDirectoryDetails.cacheId: String get() = "$name.$id" - - - fun readBlobInChunks(cursor: Cursor, columnIndex: Int): InputStream { - return object : InputStream() { - private var pos = 0 - private val blob = cursor.getBlob(columnIndex) - - override fun read(): Int { - if (pos >= blob.size) { - return -1 - } - return blob[pos++].toInt() and 0xFF - } - - // Implement other methods of InputStream if needed - } - } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/NetworkImageDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/NetworkImageDataSource.kt index 0809b27e..4fa81afa 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/NetworkImageDataSource.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/NetworkImageDataSource.kt @@ -8,5 +8,7 @@ class NetworkImageDataSource(private val networkHandler: NetworkHandler) { suspend fun getImage(directory: NetworkDirectoryDetails): SharedImage? = if (networkHandler.isConnected) { networkHandler.openImage(path = directory.fullPath) - } else null -} \ No newline at end of file + } else { + null + } +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectoryDetails.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectoryDetails.kt index 5a9fd98f..53410a92 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectoryDetails.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectoryDetails.kt @@ -5,7 +5,7 @@ import kotlinx.datetime.Clock interface NetworkDirectoryDetails { val fullPath: String - val dateMillis:Long + val dateMillis: Long val id: Int val fileName: String @@ -26,11 +26,11 @@ interface NetworkDirectoryDetails { class DefaultNetworkDirectoryDetails( override val fullPath: String, override val id: Int, - override val dateMillis: Long = Clock.System.now().toEpochMilliseconds() + override val dateMillis: Long = Clock.System.now().toEpochMilliseconds(), ) : NetworkDirectoryDetails class MockNetworkDirectoryDetails( override val fullPath: String = "", override val id: Int = 0, - override val dateMillis: Long = Clock.System.now().toEpochMilliseconds() + override val dateMillis: Long = Clock.System.now().toEpochMilliseconds(), ) : NetworkDirectoryDetails diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkHandler.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkHandler.kt index 84d31ba4..46c87dec 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkHandler.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkHandler.kt @@ -20,10 +20,15 @@ interface NetworkHandler { suspend fun folderExists(path: String): Boolean? - suspend fun savePlaylist(playlistName:String, json:String): Boolean + suspend fun savePlaylist( + playlistName: String, + json: String, + ): Boolean + suspend fun getPlaylists(): List - suspend fun setMetadata(json:String): Boolean + suspend fun setMetadata(json: String): Boolean + suspend fun getMetadata(): String? suspend fun deletePlaylist(playlistName: String) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt index e4aea211..a7799d2c 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt @@ -3,7 +3,6 @@ package com.kevinschildhorn.fotopresenter.data.repositories import com.kevinschildhorn.fotopresenter.data.DirectoryContents import com.kevinschildhorn.fotopresenter.data.FolderDirectory import com.kevinschildhorn.fotopresenter.data.ImageDirectory -import com.kevinschildhorn.fotopresenter.data.MetadataFileDetails import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource import com.kevinschildhorn.fotopresenter.data.datasources.ImageMetadataDataSource import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails @@ -18,17 +17,18 @@ class DirectoryRepository( val imageDirectories: List = directoryDataSource.getImageDirectories(path) - //val metaData = metadataDataSource.importMetaData() - + // val metaData = metadataDataSource.importMetaData() return DirectoryContents( folders = folderDirectories.map { FolderDirectory(it) }, - images = imageDirectories.map { networkDetails -> - ImageDirectory( - networkDetails, - metaData = null,// metaData.files.find { networkDetails.fullPath == it.filePath } - ) - }, + images = + imageDirectories.map { networkDetails -> + ImageDirectory( + networkDetails, + // metaData.files.find { networkDetails.fullPath == it.filePath } + metaData = null, + ) + }, ) } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt index afb06f1d..d8bb4141 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt @@ -11,18 +11,20 @@ class ImageRepository( private val localImageDataSource: CachedImageDataSource, private val logger: Logger?, ) { - - suspend fun getCoilImage(directoryDetails: NetworkDirectoryDetails, size: Int): Image? { + suspend fun getCoilImage( + directoryDetails: NetworkDirectoryDetails, + size: Int, + ): Image? { logger?.i { "Getting Image from Cache" } val cachedImage = localImageDataSource.getImage(directoryDetails) if (cachedImage != null) return cachedImage.getCoilImage(size) logger?.i { "No cached image found, getting image from directory" } val image = remoteImageDataSource.getImage(directoryDetails) - if(image != null) { + if (image != null) { logger?.i { "Storing image in cache" } localImageDataSource.saveImage(directoryDetails, image) } return image?.getCoilImage(size) } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/PlaylistRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/PlaylistRepository.kt index 60dcb40d..5e65b86e 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/PlaylistRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/PlaylistRepository.kt @@ -12,8 +12,10 @@ class PlaylistRepository( private val playlistSQLDataSource: PlaylistSQLDataSource, private val playlistFileDataSource: PlaylistFileDataSource, ) { - - suspend fun createPlaylist(name: String, directories: List = emptyList()): Playlist? { + suspend fun createPlaylist( + name: String, + directories: List = emptyList(), + ): Playlist? { val playlist = playlistSQLDataSource.createPlaylist(name, directories) playlistSQLDataSource.getPlaylistByName(name)?.let { playlistFileDataSource.exportPlaylist(it) @@ -26,7 +28,10 @@ class PlaylistRepository( return playlistSQLDataSource.getAllPlaylists() } - suspend fun insertPlaylistImage(playlistId: Long, directory: Directory): PlaylistItem? { + suspend fun insertPlaylistImage( + playlistId: Long, + directory: Directory, + ): PlaylistItem? { val item = playlistSQLDataSource.insertPlaylistImage(playlistId, directory) playlistSQLDataSource.getPlaylistById(playlistId)?.let { playlistFileDataSource.exportPlaylist(it) @@ -40,5 +45,4 @@ class PlaylistRepository( } return playlistSQLDataSource.deletePlaylist(id) } - -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageDirectoriesUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageDirectoriesUseCase.kt index c8de06a8..98c2872f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageDirectoriesUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageDirectoriesUseCase.kt @@ -21,10 +21,11 @@ class RetrieveImageDirectoriesUseCase( val contents = retrieveContentsUseCase(directoryDetails.fullPath) logger.i { "Retrieved Contents: $contents" } - val folders = contents.folders.filter { - logger.i { "Filtering (${it.name})" } - it.isValid - } + val folders = + contents.folders.filter { + logger.i { "Filtering (${it.name})" } + it.isValid + } val images = contents.images.toMutableList() if (recursively) { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt index 6638bccc..d55057ca 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt @@ -12,7 +12,6 @@ class RetrieveImageUseCase( private val cachedImageDataSource: CachedImageDataSource, private val logger: Logger, ) { - suspend operator fun invoke( directory: ImageDirectory, imageSize: Int, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveSlideshowFromPlaylistUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveSlideshowFromPlaylistUseCase.kt index b91c57c4..162788e5 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveSlideshowFromPlaylistUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveSlideshowFromPlaylistUseCase.kt @@ -7,7 +7,6 @@ import com.kevinschildhorn.fotopresenter.data.PlaylistDetails import com.kevinschildhorn.fotopresenter.data.network.DefaultNetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.extension.isImagePath import org.koin.core.component.KoinComponent -import org.koin.core.component.inject /** Retrieving Slideshow Details From Playlist Details @@ -16,30 +15,30 @@ class RetrieveSlideshowFromPlaylistUseCase( private val logger: Logger, private val retrieveDirectoryUseCase: RetrieveImageDirectoriesUseCase, ) : KoinComponent { - suspend operator fun invoke( - playlistDetails: PlaylistDetails, - ): ImageSlideshowDetails { + suspend operator fun invoke(playlistDetails: PlaylistDetails): ImageSlideshowDetails { logger.i { "Starting to get details from playlist ${playlistDetails.name}" } - val directories: List = playlistDetails.items.map { item -> - val directoryDetails = DefaultNetworkDirectoryDetails( - id = item.directoryId.toInt(), - fullPath = item.directoryPath - ) - if (item.directoryPath.isImagePath) { - listOf( - ImageDirectory( - directoryDetails, - null + val directories: List = + playlistDetails.items.map { item -> + val directoryDetails = + DefaultNetworkDirectoryDetails( + id = item.directoryId.toInt(), + fullPath = item.directoryPath, ) - ) - } else { - retrieveDirectoryUseCase( - directoryDetails = directoryDetails, - recursively = true, - ) - } - }.flatten() + if (item.directoryPath.isImagePath) { + listOf( + ImageDirectory( + directoryDetails, + null, + ), + ) + } else { + retrieveDirectoryUseCase( + directoryDetails = directoryDetails, + recursively = true, + ) + } + }.flatten() return ImageSlideshowDetails(directories) } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/SaveMetadataForPathUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/SaveMetadataForPathUseCase.kt index d078f2c1..f4682537 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/SaveMetadataForPathUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/SaveMetadataForPathUseCase.kt @@ -1,6 +1,5 @@ package com.kevinschildhorn.fotopresenter.domain.image -import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails import com.kevinschildhorn.fotopresenter.data.MetadataFileDetails import com.kevinschildhorn.fotopresenter.data.datasources.ImageMetadataDataSource import org.koin.core.component.KoinComponent @@ -8,7 +7,6 @@ import org.koin.core.component.KoinComponent class SaveMetadataForPathUseCase( private val dataSource: ImageMetadataDataSource, ) : KoinComponent { - suspend operator fun invoke( path: String, tags: String, @@ -16,14 +14,15 @@ class SaveMetadataForPathUseCase( val tagList: List = tags.split(",").map { it.trim() } val metaData = dataSource.importMetaData() - val fileMetadata = MetadataFileDetails( - filePath = path, - tags = tagList.toSet(), - ) + val fileMetadata = + MetadataFileDetails( + filePath = path, + tags = tagList.toSet(), + ) metaData.files.removeIf { it.filePath == path } if (fileMetadata.tags.isNotEmpty()) metaData.files.add(fileMetadata) return dataSource.exportMetadata(metaData) } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/extension/StringExtensions.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/extension/StringExtensions.kt index 4ca6a561..66143255 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/extension/StringExtensions.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/extension/StringExtensions.kt @@ -33,4 +33,3 @@ val String.isImagePath: Boolean val extension = this.split(".").last() return supportedImageTypes.contains(extension) } - diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt index 070daf5f..3f88d766 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt @@ -7,15 +7,14 @@ import coil3.fetch.Fetcher import coil3.fetch.ImageFetchResult import coil3.request.Options import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage class ByteArrayFetcher( private val byteArray: ByteArray, private val networkHandler: NetworkHandler, ) : Fetcher { - override suspend fun fetch(): FetchResult? { return withContext(Dispatchers.IO) { val image = SharedImage(byteArray) @@ -36,7 +35,7 @@ class ByteArrayFetcher( override fun create( data: ByteArray, options: Options, - imageLoader: ImageLoader + imageLoader: ImageLoader, ): Fetcher = ByteArrayFetcher(data, networkHandler) } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SortingType.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SortingType.kt index ea0fe2dc..86cc01c3 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SortingType.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SortingType.kt @@ -5,4 +5,4 @@ enum class SortingType { NAME_DESC, TIME_ASC, TIME_DESC, -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/UiState.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/UiState.kt index b93771fc..02bc23f4 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/UiState.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/UiState.kt @@ -1,10 +1,5 @@ package com.kevinschildhorn.fotopresenter.ui -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ErrorView -import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.LoadingOverlay - sealed class UiState { data object IDLE : UiState() diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoColors.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoColors.kt index 14f3c527..bdd66ece 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoColors.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoColors.kt @@ -1,33 +1,34 @@ package com.kevinschildhorn.fotopresenter.ui.atoms -import androidx.compose.foundation.shape.CornerBasedShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Colors import androidx.compose.material.Shapes import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -val fotoColors = Colors( - primary = Color(0xFFFFA500), - primaryVariant = Color(0xFFFFA500), - secondary = Color(0xFFFFD383), - secondaryVariant = Color(0xFFFFD383), - background = Color(0xFFFFFFFF), - surface = Color(0xFFFFFFFF), - error = Color(0xFFFF0000), - onPrimary = Color(0xFF402900), - onSecondary = Color(0xFFC1872E), - onBackground = Color(0xFF25231F), - onSurface = Color(0xFFC2882E), - onError = Color(0xFF9E1F1F), - isLight = true -) +val fotoColors = + Colors( + primary = Color(0xFFFFA500), + primaryVariant = Color(0xFFFFA500), + secondary = Color(0xFFFFD383), + secondaryVariant = Color(0xFFFFD383), + background = Color(0xFFFFFFFF), + surface = Color(0xFFFFFFFF), + error = Color(0xFFFF0000), + onPrimary = Color(0xFF402900), + onSecondary = Color(0xFFC1872E), + onBackground = Color(0xFF25231F), + onSurface = Color(0xFFC2882E), + onError = Color(0xFF9E1F1F), + isLight = true, + ) val disabled = Color(0xE0E0E0) val shadow = Color(red = 0f, green = 0f, blue = 0f, alpha = 0.25f) -val fotoShapes = Shapes( - small = RoundedCornerShape(5.dp), - medium = RoundedCornerShape(10.dp), - large = RoundedCornerShape(20.dp), -) \ No newline at end of file +val fotoShapes = + Shapes( + small = RoundedCornerShape(5.dp), + medium = RoundedCornerShape(10.dp), + large = RoundedCornerShape(20.dp), + ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoTypography.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoTypography.kt index 05aeca68..4ee641b8 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoTypography.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/FotoTypography.kt @@ -1,3 +1,5 @@ +@file:Suppress("ktlint:standard:class-naming") + package com.kevinschildhorn.fotopresenter.ui.atoms import androidx.compose.material.Typography @@ -17,27 +19,29 @@ import org.jetbrains.compose.resources.Font @OptIn(ExperimentalResourceApi::class) @Composable -fun QuicksandFontFamily() = FontFamily( - Font(Res.font.quicksand_light, weight = FontWeight.Light), - Font(Res.font.quicksand_regular, weight = FontWeight.Normal), - Font(Res.font.quicksand_medium, weight = FontWeight.Medium), - Font(Res.font.quicksand_semibold, weight = FontWeight.SemiBold), - Font(Res.font.quicksand_bold, weight = FontWeight.Bold) -) +fun QuicksandFontFamily() = + FontFamily( + Font(Res.font.quicksand_light, weight = FontWeight.Light), + Font(Res.font.quicksand_regular, weight = FontWeight.Normal), + Font(Res.font.quicksand_medium, weight = FontWeight.Medium), + Font(Res.font.quicksand_semibold, weight = FontWeight.SemiBold), + Font(Res.font.quicksand_bold, weight = FontWeight.Bold), + ) @Composable -fun FotoTypography() = Typography().run { - val fontFamily = QuicksandFontFamily() - this.copy( - h1 = TextStyle(fontSize = 96.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), - h2 = TextStyle(fontSize = 48.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), - h3 = TextStyle(fontSize = 36.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), - h4 = TextStyle(fontSize = 24.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), - subtitle1 = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), - subtitle2 = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), - button = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Bold, fontFamily = fontFamily), - body1 = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), - body2 = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), - caption = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Bold, fontFamily = fontFamily), - ) -} \ No newline at end of file +fun FotoTypography() = + Typography().run { + val fontFamily = QuicksandFontFamily() + this.copy( + h1 = TextStyle(fontSize = 96.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + h2 = TextStyle(fontSize = 48.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + h3 = TextStyle(fontSize = 36.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + h4 = TextStyle(fontSize = 24.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + subtitle1 = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + subtitle2 = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + button = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Bold, fontFamily = fontFamily), + body1 = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + body2 = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, fontFamily = fontFamily), + caption = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Bold, fontFamily = fontFamily), + ) + } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/ImageViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/ImageViewModel.kt index 5dee6c8a..993ff079 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/ImageViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/ImageViewModel.kt @@ -32,10 +32,12 @@ interface ImageViewModel { } fun clearPresentedImage() + fun cancelImageJobs() } class DefaultImageViewModel(private val logger: Logger? = null) : ImageViewModel, KoinComponent { + @Suppress("ktlint:standard:property-naming") private val _uiState = MutableStateFlow(ImageScreenState()) override var scope: CoroutineScope? = null override val imageUiState: StateFlow = _uiState.asStateFlow() diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ActionSheet.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ActionSheet.kt index d741e9eb..f7806eec 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ActionSheet.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ActionSheet.kt @@ -1,13 +1,8 @@ package com.kevinschildhorn.fotopresenter.ui.screens.common.composables -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -42,39 +37,39 @@ fun ActionSheet( visible = visible, onDismiss = onDismiss, enter = - slideInVertically( - initialOffsetY = { offset }, - ), + slideInVertically( + initialOffsetY = { offset }, + ), exit = - slideOutVertically( - targetOffsetY = { offset }, - ), + slideOutVertically( + targetOffsetY = { offset }, + ), ) { Column( modifier = - Modifier - .fillMaxSize(), + Modifier + .fillMaxSize(), verticalArrangement = Arrangement.SpaceBetween, ) { Spacer(modifier = Modifier.fillMaxWidth()) Column( modifier = - Modifier - .clip(shape = RoundedCornerShape(15.dp)) - .fillMaxWidth() - .padding(10.dp) - .weight(1f, false) - .background(fotoColors.secondary), + Modifier + .clip(shape = RoundedCornerShape(15.dp)) + .fillMaxWidth() + .padding(10.dp) + .weight(1f, false) + .background(fotoColors.secondary), horizontalAlignment = Alignment.CenterHorizontally, ) { LazyColumn { items(values) { TextButton( modifier = - Modifier - .fillMaxWidth() - .wrapContentHeight() - .padding(start = 10.dp), + Modifier + .fillMaxWidth() + .wrapContentHeight() + .padding(start = 10.dp), onClick = { onClick(it) }, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/DialogButtonText.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/DialogButtonText.kt index 1131ba1e..96d335c2 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/DialogButtonText.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/DialogButtonText.kt @@ -7,41 +7,53 @@ import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors @Composable -fun DialogButtonText(text: String, modifier: Modifier = Modifier) { +fun DialogButtonText( + text: String, + modifier: Modifier = Modifier, +) { Text( text, style = FotoTypography().button, color = fotoColors.onSurface, - modifier = modifier + modifier = modifier, ) } @Composable -fun DialogTitle(text: String, modifier: Modifier = Modifier) { +fun DialogTitle( + text: String, + modifier: Modifier = Modifier, +) { Text( text, style = FotoTypography().h4, color = fotoColors.onSecondary, - modifier = modifier + modifier = modifier, ) } @Composable -fun DialogMessage(text: String, modifier: Modifier = Modifier) { +fun DialogMessage( + text: String, + modifier: Modifier = Modifier, +) { Text( text, style = FotoTypography().body1, color = fotoColors.onSurface, - modifier = modifier + modifier = modifier, ) } @Composable -fun ToastMessage(text: String, modifier: Modifier = Modifier) { +fun ToastMessage( + text: String, + modifier: Modifier = Modifier, +) { Text( text, style = FotoTypography().body1, color = fotoColors.onPrimary, - modifier = modifier + modifier = modifier, ) -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ErrorView.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ErrorView.kt index 634cff5e..892cec2e 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ErrorView.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ErrorView.kt @@ -1,6 +1,5 @@ package com.kevinschildhorn.fotopresenter.ui.screens.common.composables -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/FilterDialog.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/FilterDialog.kt index 81bdb3db..ae057b87 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/FilterDialog.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/FilterDialog.kt @@ -29,46 +29,46 @@ fun FilterDialog( Row(verticalAlignment = Alignment.CenterVertically) { RadioButton( selected = selectedOption.value == SortingType.NAME_ASC, - onClick = { selectedOption.value = SortingType.NAME_ASC } + onClick = { selectedOption.value = SortingType.NAME_ASC }, ) Text( text = "File Name A-Z", style = FotoTypography().button, - color = fotoColors.onSurface + color = fotoColors.onSurface, ) } Row(verticalAlignment = Alignment.CenterVertically) { RadioButton( selected = selectedOption.value == SortingType.NAME_DESC, - onClick = { selectedOption.value = SortingType.NAME_DESC } + onClick = { selectedOption.value = SortingType.NAME_DESC }, ) Text( text = "File Name Z-A", style = FotoTypography().button, - color = fotoColors.onSurface + color = fotoColors.onSurface, ) } Row(verticalAlignment = Alignment.CenterVertically) { RadioButton( selected = selectedOption.value == SortingType.TIME_ASC, - onClick = { selectedOption.value = SortingType.TIME_ASC } + onClick = { selectedOption.value = SortingType.TIME_ASC }, ) Text( text = "Time Created Ascending", style = FotoTypography().button, - color = fotoColors.onSurface + color = fotoColors.onSurface, ) } Row(verticalAlignment = Alignment.CenterVertically) { RadioButton( selected = selectedOption.value == SortingType.TIME_DESC, - onClick = { selectedOption.value = SortingType.TIME_DESC } + onClick = { selectedOption.value = SortingType.TIME_DESC }, ) Text( text = "Time Created Descending", style = FotoTypography().button, - color = fotoColors.onSurface + color = fotoColors.onSurface, ) } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/FotoDIalog.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/FotoDIalog.kt index 0abad4f8..ca094d51 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/FotoDIalog.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/FotoDIalog.kt @@ -28,14 +28,16 @@ fun FotoDialog( Dialog(onDismissRequest = { onDismissRequest() }) { // Draw a rectangle shape with rounded corners inside the dialog Card( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), + modifier = + Modifier + .fillMaxWidth() + .padding(16.dp), shape = RoundedCornerShape(16.dp), ) { Column( - modifier = Modifier - .fillMaxWidth().padding(Padding.STANDARD.dp), + modifier = + Modifier + .fillMaxWidth().padding(Padding.STANDARD.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.Start, ) { @@ -43,17 +45,18 @@ fun FotoDialog( Spacer(Modifier.size(Padding.MEDIUM.dp)) content() Row( - modifier = Modifier - .fillMaxWidth() - .padding(top = Padding.SMALL.dp), + modifier = + Modifier + .fillMaxWidth() + .padding(top = Padding.SMALL.dp), horizontalArrangement = Arrangement.End, - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { TextButton( onClick = { onDismissRequest() }, - modifier = Modifier.padding(Padding.SMALL.dp) + modifier = Modifier.padding(Padding.SMALL.dp), ) { DialogButtonText("Dismiss") } @@ -66,4 +69,4 @@ fun FotoDialog( } } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ImagePreviewOverlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ImagePreviewOverlay.kt index 0fe2e779..38a98125 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ImagePreviewOverlay.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ImagePreviewOverlay.kt @@ -10,15 +10,14 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage import com.kevinschildhorn.fotopresenter.ui.atoms.Padding +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage import compose.icons.EvaIcons import compose.icons.evaicons.Fill import compose.icons.evaicons.fill.ArrowLeft import compose.icons.evaicons.fill.ArrowRight -import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage @Composable fun ImagePreviewOverlay( @@ -28,7 +27,6 @@ fun ImagePreviewOverlay( onBack: () -> Unit, onForward: () -> Unit, ) { - Overlay( 5f, visible = visible, @@ -43,17 +41,17 @@ fun ImagePreviewOverlay( model = image, contentDescription = null, modifier = - Modifier - .fillMaxWidth() - .fillMaxHeight(.9f) - .padding(Padding.IMAGE.dp), + Modifier + .fillMaxWidth() + .fillMaxHeight(.9f) + .padding(Padding.IMAGE.dp), ) Row( modifier = - Modifier - .fillMaxWidth() - .padding(Padding.STANDARD.dp) - .height(44.dp), + Modifier + .fillMaxWidth() + .padding(Padding.STANDARD.dp) + .height(44.dp), horizontalArrangement = Arrangement.SpaceBetween, ) { PrimaryIconButton( diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/Overlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/Overlay.kt index 49d42895..6700ba51 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/Overlay.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/Overlay.kt @@ -3,10 +3,8 @@ package com.kevinschildhorn.fotopresenter.ui.screens.common.composables import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition -import androidx.compose.animation.expandIn import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut -import androidx.compose.animation.shrinkOut import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource @@ -17,14 +15,13 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.zIndex -import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors import com.kevinschildhorn.fotopresenter.ui.atoms.shadow @Composable fun Overlay( z: Float, visible: Boolean, - shadow:Boolean = true, + shadow: Boolean = true, modifier: Modifier = Modifier, onDismiss: () -> Unit, enter: EnterTransition = fadeIn(), @@ -34,7 +31,7 @@ fun Overlay( OverlayShadow( z - 1, visible && shadow, - onDismiss = onDismiss + onDismiss = onDismiss, ) AnimatedVisibility( visible = visible, @@ -42,9 +39,10 @@ fun Overlay( exit = exit, ) { Box( - modifier = modifier - .fillMaxSize() - .zIndex(z), + modifier = + modifier + .fillMaxSize() + .zIndex(z), content = content, ) } @@ -64,15 +62,16 @@ fun OverlayShadow( ) { val interactionSource = remember { MutableInteractionSource() } Box( - modifier = modifier - .zIndex(z) - .fillMaxSize() - .background(shadow) - .clickable( - interactionSource = interactionSource, - indication = null, - onClick = onDismiss, - ), + modifier = + modifier + .zIndex(z) + .fillMaxSize() + .background(shadow) + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = onDismiss, + ), ) } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryButton.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryButton.kt index e815efb4..7ddcc91e 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryButton.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryButton.kt @@ -12,7 +12,6 @@ import androidx.compose.ui.unit.dp import com.kevinschildhorn.fotopresenter.ui.atoms.disabled import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors - @Composable fun PrimaryButton( modifier: Modifier = Modifier, @@ -25,10 +24,10 @@ fun PrimaryButton( modifier = modifier.height(44.dp), enabled = buttonState.enabled, colors = - ButtonDefaults.buttonColors( - backgroundColor = fotoColors.primary, - disabledBackgroundColor = disabled, - ), + ButtonDefaults.buttonColors( + backgroundColor = fotoColors.primary, + disabledBackgroundColor = disabled, + ), ) { if (buttonState.loading) { CircularProgressIndicator( @@ -52,4 +51,4 @@ enum class ButtonState { val loading: Boolean get() = this == LOADING -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryIconButton.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryIconButton.kt index d0df19e6..9c0471bd 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryIconButton.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryIconButton.kt @@ -5,7 +5,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector - @Composable fun PrimaryIconButton( imageVector: ImageVector, @@ -16,4 +15,4 @@ fun PrimaryIconButton( PrimaryButton(modifier = modifier, buttonState = buttonState, onClick = onClick) { Icon(imageVector, contentDescription = null) } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryTextButton.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryTextButton.kt index 7c236463..2d22c753 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryTextButton.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/PrimaryTextButton.kt @@ -1,6 +1,5 @@ package com.kevinschildhorn.fotopresenter.ui.screens.common.composables - import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -14,7 +13,6 @@ fun PrimaryTextButton( buttonState: ButtonState = ButtonState.ENABLED, onClick: () -> Unit, ) { - PrimaryButton(modifier = modifier, buttonState = buttonState, onClick = onClick) { Text( title, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ToastOverlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ToastOverlay.kt index b47fe337..fff9cad4 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ToastOverlay.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/common/composables/ToastOverlay.kt @@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment @@ -39,7 +38,7 @@ fun ToastOverlay( AnimatedVisibility( visible = visible, enter = slideInVertically { -25 } + fadeIn(initialAlpha = 0.3f), - exit = slideOutVertically { -25 } + fadeOut() + exit = slideOutVertically { -25 } + fadeOut(), ) { Overlay( z = 8f, @@ -50,22 +49,24 @@ fun ToastOverlay( Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.SpaceBetween, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Spacer(Modifier) Column(modifier = Modifier.padding(horizontal = Padding.STANDARD.dp)) { Box( - modifier = Modifier - .clip(RoundedCornerShape(25.dp)) - .background(fotoColors.secondary), + modifier = + Modifier + .clip(RoundedCornerShape(25.dp)) + .background(fotoColors.secondary), ) { ToastMessage( text, - modifier = Modifier - .padding( - horizontal = Padding.STANDARD.dp, - vertical = Padding.MEDIUM.dp - ), + modifier = + Modifier + .padding( + horizontal = Padding.STANDARD.dp, + vertical = Padding.MEDIUM.dp, + ), ) } Spacer(Modifier.height(25.dp)) @@ -73,4 +74,4 @@ fun ToastOverlay( } } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt index 9202b58f..7427b01f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt @@ -72,10 +72,11 @@ fun DirectoryScreen( (uiState.state as? UiState.ERROR)?.let { ErrorView( it.message, - modifier = Modifier.padding( - horizontal = Padding.STANDARD.dp, - vertical = Padding.SMALL.dp, - ) + modifier = + Modifier.padding( + horizontal = Padding.STANDARD.dp, + vertical = Padding.SMALL.dp, + ), ) } DirectoryNavigationBar( @@ -86,7 +87,7 @@ fun DirectoryScreen( onItem = { viewModel.navigateToFolder(it) }, - modifier = Modifier.padding(Padding.SMALL.dp) + modifier = Modifier.padding(Padding.SMALL.dp), ) DirectoryGrid( uiState.directoryGridState, @@ -206,7 +207,7 @@ fun DirectoryScreen( }, onConfirmation = { viewModel.setFilterType(it) - } + }, ) } @@ -217,7 +218,7 @@ fun DirectoryScreen( overlaid = true, onDismiss = { overlayVisible = DirectoryOverlay.NONE - } + }, ) { playlist -> viewModel.addSelectedDirectoryToPlaylist(playlist) overlayVisible = DirectoryOverlay.NONE @@ -232,10 +233,12 @@ fun DirectoryScreen( initialValue = viewModel.selectedMetadata?.tagsString ?: "", { overlayVisible = DirectoryOverlay.NONE - }, { + }, + { viewModel.saveMetadata(it) viewModel.setSelectedDirectory(null) overlayVisible = DirectoryOverlay.NONE - }) + }, + ) } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt index 9d717074..9d84c0b4 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreenState.kt @@ -16,9 +16,7 @@ data class DirectoryScreenState( val sortingType: SortingType = SortingType.NAME_ASC, override val state: UiState = UiState.IDLE, ) : ScreenState { - - fun getImageIndexFromId(id: Int): Int = - directoryGridState.imageStates.indexOfFirst { it.id == id } + fun getImageIndexFromId(id: Int): Int = directoryGridState.imageStates.indexOfFirst { it.id == id } val currentPathList: List get() = currentPath.split("\\").filter { it.isNotEmpty() } @@ -44,21 +42,25 @@ data class DirectoryGridState( sealed class DirectoryGridCellState( val name: String, val id: Int, - val actionSheetContexts: List - + val actionSheetContexts: List, ) { class Folder(name: String, id: Int) : DirectoryGridCellState( - name, id, listOf( + name, + id, + listOf( ActionSheetContext(ActionSheetAction.START_SLIDESHOW, 1), ActionSheetContext(ActionSheetAction.ADD_DYNAMIC_LOCATION, 2), - ) + ), ) class Image(val directoryDetails: NetworkDirectoryDetails, name: String, id: Int) : DirectoryGridCellState( - name, id, listOf( + name, + id, + listOf( ActionSheetContext(ActionSheetAction.ADD_STATIC_LOCATION, 1), ActionSheetContext(ActionSheetAction.ADD_METADATA, 2), - ) + ), ) + override fun toString(): String = "(I:$name:$id)" } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt index 62a6cd77..cadf2b58 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt @@ -35,11 +35,13 @@ class DirectoryViewModel( ) : PlaylistViewModel(playlistRepository, logger), ImageViewModel by DefaultImageViewModel(logger), KoinComponent { - private val slideshowScope: CoroutineScope = viewModelScope + Dispatchers.IO private val imageScope: CoroutineScope = viewModelScope + Dispatchers.IO + @Suppress("ktlint:standard:property-naming") private val _directoryContentsState = MutableStateFlow(DirectoryContents()) + + @Suppress("ktlint:standard:property-naming") private val _uiState = MutableStateFlow(DirectoryScreenState()) val uiState: StateFlow = _uiState.asStateFlow() @@ -87,7 +89,7 @@ class DirectoryViewModel( val retrieveImagesUseCase = UseCaseFactory.retrieveImageDirectoriesUseCase val images = retrieveImagesUseCase(it.details) logger.v { "Retrieved images, copying them to state" } - //_uiState.update { it.copy(slideshowDetails = ImageSlideshowDetails(images)) } + // _uiState.update { it.copy(slideshowDetails = ImageSlideshowDetails(images)) } } } } ?: run { @@ -174,36 +176,39 @@ class DirectoryViewModel( } } - private fun updateGrid() = with(_directoryContentsState.value) { - logger.i { "Updating State to Success" } - logger.i { "Setting Directories: $this" } - setImageDirectories(this.images) - val gridState = this.asDirectoryGridState - logger.i { "New Grid State $gridState" } - _uiState.update { - it.copy( - directoryGridState = gridState, - state = UiState.SUCCESS, - ) + private fun updateGrid() = + with(_directoryContentsState.value) { + logger.i { "Updating State to Success" } + logger.i { "Setting Directories: $this" } + setImageDirectories(this.images) + val gridState = this.asDirectoryGridState + logger.i { "New Grid State $gridState" } + _uiState.update { + it.copy( + directoryGridState = gridState, + state = UiState.SUCCESS, + ) + } } - } private val DirectoryContents.asDirectoryGridState: DirectoryGridState get() = DirectoryGridState( - folderStates = folders.map { - DirectoryGridCellState.Folder( - it.name, - it.id - ) - }, - imageStates = images.map { - DirectoryGridCellState.Image( - it.details, - it.name, - it.id, - ) - }.toMutableList(), + folderStates = + folders.map { + DirectoryGridCellState.Folder( + it.name, + it.id, + ) + }, + imageStates = + images.map { + DirectoryGridCellState.Image( + it.details, + it.name, + it.id, + ) + }.toMutableList(), ) //endregion @@ -216,8 +221,11 @@ class DirectoryViewModel( logger.i { "Inserting Playlist Image ${playlist.id} as ${uiState.value.selectedDirectory}" } val states: List = - if (selectedDirectory is DirectoryGridCellState.Image) this.images - else this.folders + if (selectedDirectory is DirectoryGridCellState.Image) { + this.images + } else { + this.folders + } states.find { it.id == selectedDirectory.id } ?.let { directory -> diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGrid.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGrid.kt index 1cf3745e..a08dbe40 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGrid.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/grid/DirectoryGrid.kt @@ -63,14 +63,16 @@ fun DirectoryGrid( onLongClickLabel = "Action Sheet", ) when (state) { - is DirectoryGridCellState.Folder -> FolderDirectoryGridCell( - state, - modifier = directoryItemModifier, - ) - is DirectoryGridCellState.Image -> ImageDirectoryGridCell( - state, - modifier = directoryItemModifier, - ) + is DirectoryGridCellState.Folder -> + FolderDirectoryGridCell( + state, + modifier = directoryItemModifier, + ) + is DirectoryGridCellState.Image -> + ImageDirectoryGridCell( + state, + modifier = directoryItemModifier, + ) } } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationBar.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationBar.kt index c76e4190..fa10de10 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationBar.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationBar.kt @@ -24,26 +24,25 @@ fun DirectoryNavigationBar( ) { Row( modifier = modifier, - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { DirectoryNavigationHome { onHome() } - LazyRow() { - itemsIndexed(directories){ index, item -> + LazyRow { + itemsIndexed(directories) { index, item -> Icon( EvaIcons.Fill.ChevronRight, tint = fotoColors.onSecondary, contentDescription = null, - modifier = Modifier.height(44.dp) + modifier = Modifier.height(44.dp), ) DirectoryNavigationItem(item) { onItem(index) } } items(directories) { - } } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationHome.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationHome.kt index ce1f514e..a2d808e2 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationHome.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationHome.kt @@ -23,16 +23,16 @@ fun DirectoryNavigationHome(onClick: () -> Unit) { onClick = onClick, modifier = Modifier.height(44.dp).width(44.dp).clip(RoundedCornerShape(10.dp)), colors = - ButtonDefaults.buttonColors( - backgroundColor = fotoColors.secondary, - disabledBackgroundColor = disabled, - ), + ButtonDefaults.buttonColors( + backgroundColor = fotoColors.secondary, + disabledBackgroundColor = disabled, + ), ) { Icon( imageVector = EvaIcons.Fill.Home, tint = fotoColors.onSecondary, contentDescription = "Home", - modifier = Modifier.size(44.dp) + modifier = Modifier.size(44.dp), ) } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationItem.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationItem.kt index f60bb366..9c491b82 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationItem.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navbar/DirectoryNavigationItem.kt @@ -12,16 +12,19 @@ import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.DialogButtonText @Composable -fun DirectoryNavigationItem(title: String, onClick: () -> Unit) { +fun DirectoryNavigationItem( + title: String, + onClick: () -> Unit, +) { Button( onClick = onClick, modifier = Modifier.height(44.dp).clip(RoundedCornerShape(10.dp)), colors = - ButtonDefaults.buttonColors( - backgroundColor = fotoColors.secondary, - disabledBackgroundColor = fotoColors.onSecondary, - ), + ButtonDefaults.buttonColors( + backgroundColor = fotoColors.secondary, + disabledBackgroundColor = fotoColors.onSecondary, + ), ) { DialogButtonText(title) } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/DirectoryTitleBarButton.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/DirectoryTitleBarButton.kt index 42400840..79cd1e86 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/DirectoryTitleBarButton.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/DirectoryTitleBarButton.kt @@ -1,27 +1,27 @@ package com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.navrail +import androidx.compose.foundation.layout.size import androidx.compose.material.Icon import androidx.compose.material.TextButton import androidx.compose.runtime.Composable -import androidx.compose.ui.unit.dp import androidx.compose.ui.Modifier -import androidx.compose.foundation.layout.size import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp import com.kevinschildhorn.fotopresenter.ui.atoms.fotoColors @Composable fun DirectoryTitleBarButton( imageVector: ImageVector, - onClick: () -> Unit + onClick: () -> Unit, ) { TextButton( modifier = Modifier.size(55.dp), - onClick = onClick + onClick = onClick, ) { Icon( imageVector, contentDescription = "Menu", - tint = fotoColors.onBackground + tint = fotoColors.onBackground, ) } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/NavigationRailOverlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/NavigationRailOverlay.kt index 698d2fd0..be3e9eb8 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/NavigationRailOverlay.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/composables/navrail/NavigationRailOverlay.kt @@ -32,7 +32,7 @@ fun NavigationRailOverlay( ) { Row { NavigationRail( - backgroundColor = fotoColors.surface + backgroundColor = fotoColors.surface, ) { NavigationRailItem( label = { @@ -42,11 +42,11 @@ fun NavigationRailOverlay( Icon( EvaIcons.Outline.Monitor, contentDescription = "Playlists", - tint = fotoColors.onSurface + tint = fotoColors.onSurface, ) }, selected = true, - onClick = onPlaylists + onClick = onPlaylists, ) NavigationRailItem( label = { @@ -56,13 +56,13 @@ fun NavigationRailOverlay( Icon( EvaIcons.Fill.LogOut, contentDescription = "Logout", - tint = fotoColors.onSurface + tint = fotoColors.onSurface, ) }, selected = true, - onClick = onLogout + onClick = onLogout, ) } } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/LoginScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/LoginScreen.kt index ebb7f0b9..a8255cde 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/LoginScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/LoginScreen.kt @@ -7,8 +7,6 @@ import androidx.compose.foundation.text.ClickableText import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalUriHandler @@ -18,7 +16,6 @@ import androidx.compose.ui.text.style.TextAlign import com.kevinschildhorn.fotopresenter.ui.UiState import com.kevinschildhorn.fotopresenter.ui.atoms.Padding import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.TitleView -import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ToastOverlay import com.kevinschildhorn.fotopresenter.ui.screens.login.composables.LoginScreenForm @Composable @@ -36,11 +33,11 @@ fun LoginScreen( TitleView( "Foto", modifier = - Modifier.padding( - top = Padding.SMALL.dp, - start = Padding.STANDARD.dp, - bottom = Padding.LARGE.dp, - ), + Modifier.padding( + top = Padding.SMALL.dp, + start = Padding.STANDARD.dp, + bottom = Padding.LARGE.dp, + ), ) LoginScreenForm( uiState = uiState, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginScreenForm.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginScreenForm.kt index a964d852..74e37e9f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginScreenForm.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginScreenForm.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.extension.required import com.kevinschildhorn.fotopresenter.ui.UiState import com.kevinschildhorn.fotopresenter.ui.atoms.Padding diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginTextField.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginTextField.kt index ef4e703f..9f409bef 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginTextField.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/login/composables/LoginTextField.kt @@ -1,7 +1,6 @@ package com.kevinschildhorn.fotopresenter.ui.screens.login.composables import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.foundation.text.KeyboardOptions.Companion import androidx.compose.material.OutlinedTextField import androidx.compose.material.Text import androidx.compose.material.TextFieldDefaults @@ -34,10 +33,11 @@ fun LoginTextField( style = FotoTypography().subtitle1, ) }, - colors = TextFieldDefaults.outlinedTextFieldColors( - textColor = fotoColors.onPrimary, - disabledTextColor = disabled, - ), + colors = + TextFieldDefaults.outlinedTextFieldColors( + textColor = fotoColors.onPrimary, + disabledTextColor = disabled, + ), shape = fotoShapes.small, textStyle = FotoTypography().subtitle1, keyboardOptions = keyboardOptions, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistScreen.kt index a8df055b..21b8b67e 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistScreen.kt @@ -1,6 +1,5 @@ package com.kevinschildhorn.fotopresenter.ui.screens.playlist - import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState @@ -8,10 +7,8 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import com.kevinschildhorn.fotopresenter.Playlist import com.kevinschildhorn.fotopresenter.data.PlaylistDetails import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ConfirmationDialog -import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryOverlay import com.kevinschildhorn.fotopresenter.ui.screens.playlist.composables.PlaylistOverlay import com.kevinschildhorn.fotopresenter.ui.screens.playlist.composables.TextEntryDialog import com.kevinschildhorn.fotopresenter.ui.screens.playlist.composables.TextListDialog @@ -21,7 +18,7 @@ enum class PlaylistDialog { CREATE, DELETE, DETAILS, - EDIT + EDIT, } @Composable @@ -45,22 +42,27 @@ fun PlaylistScreen( viewModel.getPlaylist(id)?.let { onPlaylistSelected(it) } - }, onDetails = { + }, + onDetails = { dialogOpen = PlaylistDialog.DETAILS viewModel.setSelectedPlaylist(it) - }, onDelete = { + }, + onDelete = { dialogOpen = PlaylistDialog.DELETE viewModel.setSelectedPlaylist(it) - }, onEdit = { + }, + onEdit = { dialogOpen = PlaylistDialog.EDIT viewModel.setSelectedPlaylist(it) - }, onCreate = { + }, + onCreate = { dialogOpen = PlaylistDialog.CREATE - }, onDismiss = { + }, + onDismiss = { if (onDismiss != null) { onDismiss() } - } + }, ) when (dialogOpen) { @@ -70,10 +72,12 @@ fun PlaylistScreen( initialValue = "", { dialogOpen = PlaylistDialog.NONE - }, { + }, + { viewModel.createPlaylist(it) dialogOpen = PlaylistDialog.NONE - }) + }, + ) } PlaylistDialog.DELETE -> { @@ -101,7 +105,6 @@ fun PlaylistScreen( } else -> { - } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistScreenState.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistScreenState.kt index 4359864c..4a4157d7 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistScreenState.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistScreenState.kt @@ -1,6 +1,5 @@ package com.kevinschildhorn.fotopresenter.ui.screens.playlist -import com.kevinschildhorn.fotopresenter.Playlist import com.kevinschildhorn.fotopresenter.data.PlaylistDetails import com.kevinschildhorn.fotopresenter.ui.UiState import com.kevinschildhorn.fotopresenter.ui.screens.common.ScreenState @@ -10,10 +9,9 @@ data class PlaylistScreenState( val selectedId: Long? = null, override val state: UiState = UiState.IDLE, ) : ScreenState { - val selectedPlaylist: PlaylistDetails? get() = selectedId?.let { id -> playlists.find { it.id == id } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistViewModel.kt index bfaf1f2e..6cc6ef88 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/PlaylistViewModel.kt @@ -1,9 +1,7 @@ package com.kevinschildhorn.fotopresenter.ui.screens.playlist import co.touchlab.kermit.Logger -import com.kevinschildhorn.fotopresenter.Playlist import com.kevinschildhorn.fotopresenter.data.Directory -import com.kevinschildhorn.fotopresenter.data.ImageDirectory import com.kevinschildhorn.fotopresenter.data.PlaylistDetails import com.kevinschildhorn.fotopresenter.data.repositories.PlaylistRepository import com.kevinschildhorn.fotopresenter.ui.shared.ViewModel @@ -19,7 +17,7 @@ open class PlaylistViewModel( private val playlistRepository: PlaylistRepository, private val logger: Logger, ) : ViewModel(), KoinComponent { - + @Suppress("ktlint:standard:property-naming") private val _uiState = MutableStateFlow(PlaylistScreenState()) val playlistState: StateFlow = _uiState.asStateFlow() @@ -38,8 +36,7 @@ open class PlaylistViewModel( _uiState.update { it.copy(selectedId = id) } } - fun getPlaylist(id: Long): PlaylistDetails? = - _uiState.value.playlists.find { it.id == id } + fun getPlaylist(id: Long): PlaylistDetails? = _uiState.value.playlists.find { it.id == id } fun clearSelectedPlaylist() { _uiState.update { it.copy(selectedId = null) } @@ -52,12 +49,15 @@ open class PlaylistViewModel( } } - fun addToPlaylist(directory: Directory, playlist: PlaylistDetails) { + fun addToPlaylist( + directory: Directory, + playlist: PlaylistDetails, + ) { logger.i { "Inserting Playlist Image ${playlist.id} as ${directory.name}" } viewModelScope.launch(Dispatchers.Default) { playlistRepository.insertPlaylistImage( playlistId = playlist.id, - directory = directory + directory = directory, )?.let { logger.i { "Successfully inserted playlist image" } } ?: run { @@ -75,4 +75,4 @@ open class PlaylistViewModel( clearSelectedPlaylist() } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistColumn.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistColumn.kt index caf49a1c..45989141 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistColumn.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistColumn.kt @@ -32,7 +32,7 @@ fun PlaylistColumn( .fillMaxWidth() .padding(Padding.STANDARD.dp) .clip(RoundedCornerShape(10.dp)) - .background(fotoColors.secondary) + .background(fotoColors.secondary), ) { Column(Modifier.fillMaxWidth().padding(Padding.MEDIUM.dp)) { DialogButtonText("Playlists") @@ -51,16 +51,16 @@ fun PlaylistColumn( }, onDelete = { onDelete(it.id) - } + }, ) Divider( startIndent = 0.dp, thickness = 1.dp, - color = fotoColors.onSecondary + color = fotoColors.onSecondary, ) } } PlaylistScreenCreateRow(onClick = onCreate) } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistOverlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistOverlay.kt index 7faa22b9..c496fd24 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistOverlay.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistOverlay.kt @@ -26,7 +26,7 @@ fun PlaylistOverlay( onDismiss = onDismiss, ) { Box( - modifier = Modifier.align(Alignment.Center) + modifier = Modifier.align(Alignment.Center), ) { PlaylistColumn( options, @@ -49,4 +49,4 @@ fun PlaylistOverlay( onDelete = onDelete, ) } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenCreateRow.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenCreateRow.kt index 70cbeee7..c22ac764 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenCreateRow.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenCreateRow.kt @@ -29,7 +29,7 @@ fun PlaylistScreenCreateRow( ) { TextButton( modifier = Modifier.fillMaxWidth(), - onClick = onClick + onClick = onClick, ) { Icon( EvaIcons.Outline.PlusCircle, @@ -41,4 +41,4 @@ fun PlaylistScreenCreateRow( Spacer(Modifier.fillMaxWidth()) } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenPlaylistRow.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenPlaylistRow.kt index cd4d7fd4..0fed2e89 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenPlaylistRow.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/PlaylistScreenPlaylistRow.kt @@ -33,11 +33,11 @@ fun PlaylistScreenPlaylistRow( Row( modifier = Modifier.fillMaxWidth().height(55.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween + horizontalArrangement = Arrangement.SpaceBetween, ) { TextButton( onClick = onClick, - modifier = Modifier.fillMaxSize(0.7f) + modifier = Modifier.fillMaxSize(0.7f), ) { DialogButtonText(title) Spacer(Modifier.fillMaxWidth()) @@ -45,7 +45,7 @@ fun PlaylistScreenPlaylistRow( Row(modifier = Modifier.fillMaxHeight()) { TextButton( modifier = Modifier.width(44.dp), - onClick = onDetails + onClick = onDetails, ) { Icon( EvaIcons.Outline.Info, @@ -55,7 +55,7 @@ fun PlaylistScreenPlaylistRow( } TextButton( modifier = Modifier.width(44.dp), - onClick = onEdit + onClick = onEdit, ) { Icon( EvaIcons.Outline.Edit, @@ -70,9 +70,9 @@ fun PlaylistScreenPlaylistRow( Icon( EvaIcons.Outline.Trash, tint = fotoColors.onSecondary, - contentDescription = "Trash" + contentDescription = "Trash", ) } } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/TextEntryDialog.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/TextEntryDialog.kt index 4266b0b3..5030e266 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/TextEntryDialog.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/TextEntryDialog.kt @@ -13,15 +13,15 @@ import com.kevinschildhorn.fotopresenter.ui.screens.login.composables.LoginTextF @Composable fun TextEntryDialog( - title:String, + title: String, initialValue: String, onDismissRequest: () -> Unit, onConfirmation: (String) -> Unit, ) { - var enteredValue:String by remember { mutableStateOf(initialValue) } + var enteredValue: String by remember { mutableStateOf(initialValue) } FotoDialog( - dialogTitle = title,//"Playlist Name", + dialogTitle = title, onDismissRequest = onDismissRequest, onConfirmation = { onConfirmation(enteredValue) @@ -33,7 +33,7 @@ fun TextEntryDialog( enteredValue = it }, placeholder = "Name", - modifier = Modifier.padding(top = Padding.STANDARD.dp) + modifier = Modifier.padding(top = Padding.STANDARD.dp), ) } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/TextListDialog.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/TextListDialog.kt index 104a9eab..ac58dea8 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/TextListDialog.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/playlist/composables/TextListDialog.kt @@ -16,9 +16,9 @@ fun TextListDialog( onDismissRequest = onDismissRequest, ) { LazyColumn { - items(list){ + items(list) { Text(it) } } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowScreen.kt index a7878dee..ab0dd61d 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowScreen.kt @@ -6,7 +6,6 @@ import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement @@ -61,7 +60,7 @@ fun SlideshowScreen( Box(modifier = Modifier.fillMaxSize().background(Color.Black)) { imageState.selectedImage?.let { sharedImage -> - Crossfade(imageState.selectedImageIndex, animationSpec = tween(500)){ + Crossfade(imageState.selectedImageIndex, animationSpec = tween(500)) { AsyncImage( model = sharedImage, contentDescription = null, @@ -77,8 +76,7 @@ fun SlideshowScreen( 5f, visible = true, onDismiss = { - - } + }, ) { Column( modifier = Modifier.fillMaxSize(), @@ -90,7 +88,7 @@ fun SlideshowScreen( AnimatedVisibility( visible = show, enter = fadeIn(animationSpec = tween(500)), - exit = fadeOut(animationSpec = tween(500)) + exit = fadeOut(animationSpec = tween(500)), ) { TextButton(onClick = { viewModel.stopSlideshow() @@ -100,7 +98,7 @@ fun SlideshowScreen( EvaIcons.Fill.Close, tint = Color.White, contentDescription = "Close", - modifier = Modifier.size(55.dp) + modifier = Modifier.size(55.dp), ) } } @@ -111,57 +109,59 @@ fun SlideshowScreen( horizontalArrangement = Arrangement.SpaceBetween, ) { Box( - modifier = Modifier - .fillMaxHeight() - .fillMaxWidth(0.5f) - .combinedClickable( - onClick = { - show = true - }, - onDoubleClick = { - viewModel.skipBackwards() - }, - ) + modifier = + Modifier + .fillMaxHeight() + .fillMaxWidth(0.5f) + .combinedClickable( + onClick = { + show = true + }, + onDoubleClick = { + viewModel.skipBackwards() + }, + ), ) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Start, - modifier = Modifier.fillMaxSize() + modifier = Modifier.fillMaxSize(), ) { if (show) { Icon( EvaIcons.Fill.ArrowLeft, tint = Color.White, contentDescription = "Left", - modifier = Modifier.size(55.dp) + modifier = Modifier.size(55.dp), ) } } } Box( - modifier = Modifier - .fillMaxHeight() - .fillMaxWidth() - .combinedClickable( - onClick = { - show = true - }, - onDoubleClick = { - viewModel.skipForward() - }, - ) + modifier = + Modifier + .fillMaxHeight() + .fillMaxWidth() + .combinedClickable( + onClick = { + show = true + }, + onDoubleClick = { + viewModel.skipForward() + }, + ), ) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.End, - modifier = Modifier.fillMaxSize() + modifier = Modifier.fillMaxSize(), ) { if (show) { Icon( EvaIcons.Fill.ArrowRight, tint = Color.White, contentDescription = "Right", - modifier = Modifier.size(55.dp) + modifier = Modifier.size(55.dp), ) } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowScreenState.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowScreenState.kt index 7d6bd309..c1883d43 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowScreenState.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowScreenState.kt @@ -1,7 +1,6 @@ package com.kevinschildhorn.fotopresenter.ui.screens.slideshow import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails -import com.kevinschildhorn.fotopresenter.ui.screens.common.ImageScreenState data class SlideshowScreenState( val slideshowDetails: ImageSlideshowDetails = ImageSlideshowDetails(), diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowViewModel.kt index db690920..13de2d93 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/slideshow/SlideshowViewModel.kt @@ -1,6 +1,7 @@ package com.kevinschildhorn.fotopresenter.ui.screens.slideshow import co.touchlab.kermit.Logger +import com.kevinschildhorn.fotopresenter.UseCaseFactory import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails import com.kevinschildhorn.fotopresenter.data.PlaylistDetails import com.kevinschildhorn.fotopresenter.ui.screens.common.DefaultImageViewModel @@ -14,16 +15,14 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent -import java.util.* +import java.util.Timer import kotlin.concurrent.fixedRateTimer -import com.kevinschildhorn.fotopresenter.UseCaseFactory class SlideshowViewModel( private val logger: Logger, ) : ViewModel(), ImageViewModel by DefaultImageViewModel(logger), KoinComponent { - private val _uiState = MutableStateFlow(SlideshowScreenState()) val uiState: StateFlow = _uiState.asStateFlow() private var timer: Timer? = null @@ -74,9 +73,10 @@ class SlideshowViewModel( private fun startImageTimer(seconds: Long = 5L) { val time = seconds * 1000 - timer = fixedRateTimer(period = time, initialDelay = time) { - showNextImage() - } + timer = + fixedRateTimer(period = time, initialDelay = time) { + showNextImage() + } } private fun stopImageTimer() { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/DriverFactory.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/DriverFactory.kt index 7bb208a0..67f384c4 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/DriverFactory.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/DriverFactory.kt @@ -4,4 +4,4 @@ import app.cash.sqldelight.db.SqlDriver expect class DriverFactory { fun createDriver(): SqlDriver -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt index 52c02f14..0e535d9f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt @@ -14,9 +14,10 @@ interface CacheInterface { object SharedInMemoryCache : CacheInterface { private val imageCache = Cache.Builder().build() - override fun getImage(id: String): SharedImage? = imageCache.get(id)?.let { - SharedImage(it) - } + override fun getImage(id: String): SharedImage? = + imageCache.get(id)?.let { + SharedImage(it) + } override fun cacheImage( id: String, @@ -36,7 +37,8 @@ class MockSharedCache : CacheInterface { contents[id] = image.byteArray } - override fun getImage(id: String): SharedImage? = contents[id]?.let { - SharedImage(it) - } + override fun getImage(id: String): SharedImage? = + contents[id]?.let { + SharedImage(it) + } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index 2ed8c1b6..831d34d6 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -3,8 +3,8 @@ package com.kevinschildhorn.fotopresenter.ui.shared import coil3.Image expect class SharedImage(byteArray: ByteArray) { - val byteArray: ByteArray + fun getCoilImage(size: Int): Image? } @@ -25,4 +25,4 @@ fun getScaledDimensions( newHeight = height * ratio } return Pair(newWidth.toInt(), newHeight.toInt()) -} \ No newline at end of file +} diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/KoinTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/KoinTest.kt index 6f12fc5f..b6d586e3 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/KoinTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/KoinTest.kt @@ -3,7 +3,6 @@ package com.kevinschildhorn.fotopresenter import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver import co.touchlab.kermit.Logger -import co.touchlab.kermit.LoggerConfig import com.kevinschildhorn.fotopresenter.data.network.MockNetworkHandler import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler import com.russhwolf.settings.MapSettings @@ -22,6 +21,4 @@ fun testingModule(settings: MapSettings = MapSettings()) = PlaylistDatabase.Schema.create(driver) driver } - - } + commonModule diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/StringTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/StringTest.kt index dea7a504..47fafdd1 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/StringTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/StringTest.kt @@ -47,7 +47,5 @@ class StringTest { path = path.navigateBackToPathAtIndex(-1) assertEquals("", path) - - } } diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageCacheDataSourceTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageCacheDataSourceTest.kt deleted file mode 100644 index 57ef6dc3..00000000 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageCacheDataSourceTest.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.kevinschildhorn.fotopresenter.data.datasources - -/* TODO: Requires mocking -/** -Testing [ImageCacheDataSource] - **/ -class ImageCacheDataSourceTest { - private val cache = MockSharedCache() - private val dataSource = ImageCacheDataSource(cache) - - @Test - fun `save Image`() = - runBlocking { - val directoryDetails = MockNetworkDirectoryDetails( - fullPath = "Photos/sample.png", - id = 1, - ) - val bitmap = mockk() - assertTrue(cache.contents.isEmpty()) - dataSource.saveImage(directoryDetails, bitmap) - assertFalse(cache.contents.isEmpty()) - - val result = dataSource.getImage(directoryDetails) - assertEquals(bitmap, result) - } -}*/ diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageMetadataDataSourceTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageMetadataDataSourceTest.kt index 15589d1a..430b373d 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageMetadataDataSourceTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageMetadataDataSourceTest.kt @@ -4,11 +4,11 @@ import com.kevinschildhorn.fotopresenter.data.MetadataFileDetails import com.kevinschildhorn.fotopresenter.data.network.MockNetworkHandler import kotlinx.coroutines.runBlocking import org.junit.Test +import kotlin.test.AfterTest +import kotlin.test.BeforeTest import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertTrue -import kotlin.test.AfterTest -import kotlin.test.BeforeTest /** Testing [ImageMetadataDataSource] @@ -16,7 +16,6 @@ Testing [ImageMetadataDataSource] class ImageMetadataDataSourceTest { private val networkHandler: MockNetworkHandler = MockNetworkHandler - @BeforeTest fun startTest() = runBlocking { @@ -30,34 +29,37 @@ class ImageMetadataDataSourceTest { } @Test - fun `Import Metadata`() = runBlocking { - val dataSource = ImageMetadataDataSource(null, networkHandler) - val metadata = dataSource.importMetaData() - assertNotNull(metadata) - assertEquals(1, metadata.files.count()) - } + fun `Import Metadata`() = + runBlocking { + val dataSource = ImageMetadataDataSource(null, networkHandler) + val metadata = dataSource.importMetaData() + assertNotNull(metadata) + assertEquals(1, metadata.files.count()) + } @Test - fun `Export Playlist`() = runBlocking { - val dataSource = ImageMetadataDataSource(null, networkHandler) - var metadata = dataSource.importMetaData() - assertNotNull(metadata) - assertEquals(0, metadata.files.count()) - - val newMetadataFileDetails = MetadataFileDetails( - "MyPath.png", - setOf("Tag1", "Wallpaper"), - ) - val mutableFiles = metadata.files.toMutableList() - mutableFiles.add(newMetadataFileDetails) - metadata = metadata.copy(files = mutableFiles) - - val result = dataSource.exportMetadata(metadata) - assertTrue(result) - - metadata = dataSource.importMetaData() - - assertNotNull(metadata) - assertTrue(metadata.files.contains(newMetadataFileDetails)) - } -} \ No newline at end of file + fun `Export Playlist`() = + runBlocking { + val dataSource = ImageMetadataDataSource(null, networkHandler) + var metadata = dataSource.importMetaData() + assertNotNull(metadata) + assertEquals(0, metadata.files.count()) + + val newMetadataFileDetails = + MetadataFileDetails( + "MyPath.png", + setOf("Tag1", "Wallpaper"), + ) + val mutableFiles = metadata.files.toMutableList() + mutableFiles.add(newMetadataFileDetails) + metadata = metadata.copy(files = mutableFiles) + + val result = dataSource.exportMetadata(metadata) + assertTrue(result) + + metadata = dataSource.importMetaData() + + assertNotNull(metadata) + assertTrue(metadata.files.contains(newMetadataFileDetails)) + } +} diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistFileDataSourceTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistFileDataSourceTest.kt index ae1edf9e..49985a74 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistFileDataSourceTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistFileDataSourceTest.kt @@ -17,24 +17,26 @@ Testing [PlaylistFileDataSource] class PlaylistFileDataSourceTest { private val networkHandler: MockNetworkHandler = MockNetworkHandler - private val newPlaylist = PlaylistDetails( - id = 2, - name = "NewPlaylist", - items = listOf( - PlaylistItem( - id = 1, - playlistId = 2, - directoryPath = "Photos/SubPhotos/Peeng3.png", - directoryId = 2, - ), - PlaylistItem( - id = 2, - playlistId = 2, - directoryPath = "Photos/SubPhotos/Jaypeg3.jpg", - directoryId = 3, - ) - ), - ) + private val newPlaylist = + PlaylistDetails( + id = 2, + name = "NewPlaylist", + items = + listOf( + PlaylistItem( + id = 1, + playlistId = 2, + directoryPath = "Photos/SubPhotos/Peeng3.png", + directoryId = 2, + ), + PlaylistItem( + id = 2, + playlistId = 2, + directoryPath = "Photos/SubPhotos/Jaypeg3.jpg", + directoryId = 3, + ), + ), + ) @BeforeTest fun startTest() = @@ -49,42 +51,45 @@ class PlaylistFileDataSourceTest { } @Test - fun `Import Playlist`() = runBlocking { - val dataSource = PlaylistFileDataSource(null, networkHandler) - val playlists = dataSource.importPlaylists() + fun `Import Playlist`() = + runBlocking { + val dataSource = PlaylistFileDataSource(null, networkHandler) + val playlists = dataSource.importPlaylists() - val existingPlaylist = playlists.firstOrNull() - assertNotNull(existingPlaylist) - assertEquals("Existing", existingPlaylist.name) - assertEquals(2, existingPlaylist.items.count()) - } + val existingPlaylist = playlists.firstOrNull() + assertNotNull(existingPlaylist) + assertEquals("Existing", existingPlaylist.name) + assertEquals(2, existingPlaylist.items.count()) + } @Test - fun `Export Playlist`() = runBlocking { - val dataSource = PlaylistFileDataSource(null, networkHandler) - var playlists = dataSource.importPlaylists().toMutableList() - assertEquals(1, playlists.count()) + fun `Export Playlist`() = + runBlocking { + val dataSource = PlaylistFileDataSource(null, networkHandler) + var playlists = dataSource.importPlaylists().toMutableList() + assertEquals(1, playlists.count()) - val result = dataSource.exportPlaylist(newPlaylist) - assertTrue(result) + val result = dataSource.exportPlaylist(newPlaylist) + assertTrue(result) - playlists = dataSource.importPlaylists().toMutableList() + playlists = dataSource.importPlaylists().toMutableList() - val searchedPlaylist = playlists.find { it.name == "NewPlaylist" } - assertNotNull(searchedPlaylist) - print("finished") - } + val searchedPlaylist = playlists.find { it.name == "NewPlaylist" } + assertNotNull(searchedPlaylist) + print("finished") + } @Test - fun `Delete Playlist`() = runBlocking { - val dataSource = PlaylistFileDataSource(null, networkHandler) - dataSource.exportPlaylist(newPlaylist) - var playlists = dataSource.importPlaylists() - val searchedPlaylist = playlists.find { it.name == "NewPlaylist" } - assertNotNull(searchedPlaylist) - dataSource.deletePlaylist(searchedPlaylist) + fun `Delete Playlist`() = + runBlocking { + val dataSource = PlaylistFileDataSource(null, networkHandler) + dataSource.exportPlaylist(newPlaylist) + var playlists = dataSource.importPlaylists() + val searchedPlaylist = playlists.find { it.name == "NewPlaylist" } + assertNotNull(searchedPlaylist) + dataSource.deletePlaylist(searchedPlaylist) - playlists = dataSource.importPlaylists() - assertEquals(1, playlists.count()) - } -} \ No newline at end of file + playlists = dataSource.importPlaylists() + assertEquals(1, playlists.count()) + } +} diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistSQLDataSourceTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistSQLDataSourceTest.kt index 43fbb520..3c121e3b 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistSQLDataSourceTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/PlaylistSQLDataSourceTest.kt @@ -16,32 +16,35 @@ import kotlin.test.fail Testing [PlaylistSQLDataSource] **/ class PlaylistSQLDataSourceTest { - - private val imageDirectory = ImageDirectory( - details = DefaultNetworkDirectoryDetails( - fullPath = "Image1.png", - id = 1, - ), - metaData = null, - - ) - private val imageDirectoryList: List = listOf( - imageDirectory, + private val imageDirectory = ImageDirectory( - details = DefaultNetworkDirectoryDetails( - fullPath = "Photos/Image2.png", - id = 2, - ), + details = + DefaultNetworkDirectoryDetails( + fullPath = "Image1.png", + id = 1, + ), metaData = null, - ), - ImageDirectory( - details = DefaultNetworkDirectoryDetails( - fullPath = "Image3.png", - id = 3, + ) + private val imageDirectoryList: List = + listOf( + imageDirectory, + ImageDirectory( + details = + DefaultNetworkDirectoryDetails( + fullPath = "Photos/Image2.png", + id = 2, + ), + metaData = null, ), - metaData = null, - ), - ) + ImageDirectory( + details = + DefaultNetworkDirectoryDetails( + fullPath = "Image3.png", + id = 3, + ), + metaData = null, + ), + ) @Test fun `Create Playlist Success`() { @@ -196,7 +199,6 @@ class PlaylistSQLDataSourceTest { val dataSource = PlaylistSQLDataSource(createInMemorySqlDriver()) val playlists = dataSource.getAllPlaylists() assertEquals(0, playlists.count()) - } private fun createInMemorySqlDriver(): SqlDriver { @@ -204,4 +206,4 @@ class PlaylistSQLDataSourceTest { PlaylistDatabase.Schema.create(driver) return driver } -} \ No newline at end of file +} diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/network/MockNetworkHandler.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/network/MockNetworkHandler.kt index 591d2699..f1167154 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/network/MockNetworkHandler.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/network/MockNetworkHandler.kt @@ -15,72 +15,74 @@ object MockNetworkHandler : NetworkHandler { val photoDirectoryId = 5 - private val playlists = mutableMapOf( - "Existing" to """ - { - "id" : 1, - "name" : "Existing", - "items": [ + private val playlists = + mutableMapOf( + "Existing" to + """ { "id" : 1, - "playlistId" : 1, - "directoryPath" : "Photos/SubPhotos/Peeng3.png", - "directoryId" : 2 - }, - { - "id" : 2, - "playlistId" : 1, - "directoryPath" : "Photos/Jaypeg2.jpg", - "directoryId" : 3 + "name" : "Existing", + "items": [ + { + "id" : 1, + "playlistId" : 1, + "directoryPath" : "Photos/SubPhotos/Peeng3.png", + "directoryId" : 2 + }, + { + "id" : 2, + "playlistId" : 1, + "directoryPath" : "Photos/Jaypeg2.jpg", + "directoryId" : 3 + } + ] } - ] - } - """.trimIndent() - ) + """.trimIndent(), + ) private var metadata: String? = null private val networkContents = mapOf( "" to - listOf( - DefaultNetworkDirectoryDetails(fullPath = "Photos", id = photoDirectoryId), - DefaultNetworkDirectoryDetails(fullPath = "NewDirectory", id = 1), - DefaultNetworkDirectoryDetails(fullPath = "Peeng.png", id = 75), - DefaultNetworkDirectoryDetails(fullPath = "Jaypeg.jpg", id = 3), - DefaultNetworkDirectoryDetails(fullPath = "textFile.txt", id = 4), - ), + listOf( + DefaultNetworkDirectoryDetails(fullPath = "Photos", id = photoDirectoryId), + DefaultNetworkDirectoryDetails(fullPath = "NewDirectory", id = 1), + DefaultNetworkDirectoryDetails(fullPath = "Peeng.png", id = 75), + DefaultNetworkDirectoryDetails(fullPath = "Jaypeg.jpg", id = 3), + DefaultNetworkDirectoryDetails(fullPath = "textFile.txt", id = 4), + ), "Directories" to - listOf( - DefaultNetworkDirectoryDetails( - fullPath = "Directories/NewDirectory", - id = 1 - ), - DefaultNetworkDirectoryDetails( - fullPath = "Directories/NewDirectory2", - id = 2 - ), + listOf( + DefaultNetworkDirectoryDetails( + fullPath = "Directories/NewDirectory", + id = 1, ), - "Photos" to - listOf( - DefaultNetworkDirectoryDetails(fullPath = "Photos/Peeng2.png", id = 2), - DefaultNetworkDirectoryDetails(fullPath = "Photos/Jaypeg2.jpg", id = 3), - DefaultNetworkDirectoryDetails(fullPath = "Photos/textFile2.txt", id = 4), - DefaultNetworkDirectoryDetails(fullPath = "Photos/SubPhotos", id = 5), + DefaultNetworkDirectoryDetails( + fullPath = "Directories/NewDirectory2", + id = 2, ), + ), + "Photos" to + listOf( + DefaultNetworkDirectoryDetails(fullPath = "Photos/Peeng2.png", id = 2), + DefaultNetworkDirectoryDetails(fullPath = "Photos/Jaypeg2.jpg", id = 3), + DefaultNetworkDirectoryDetails(fullPath = "Photos/textFile2.txt", id = 4), + DefaultNetworkDirectoryDetails(fullPath = "Photos/SubPhotos", id = 5), + ), "Photos/SubPhotos" to - listOf( - DefaultNetworkDirectoryDetails( - fullPath = "Photos/SubPhotos/Peeng3.png", - id = 2, - ), - DefaultNetworkDirectoryDetails( - fullPath = "Photos/SubPhotos/Jaypeg3.jpg", - id = 3, - ), - DefaultNetworkDirectoryDetails( - fullPath = "Photos/SubPhotos/textFile3.txt", - id = 4, - ), + listOf( + DefaultNetworkDirectoryDetails( + fullPath = "Photos/SubPhotos/Peeng3.png", + id = 2, + ), + DefaultNetworkDirectoryDetails( + fullPath = "Photos/SubPhotos/Jaypeg3.jpg", + id = 3, ), + DefaultNetworkDirectoryDetails( + fullPath = "Photos/SubPhotos/textFile3.txt", + id = 4, + ), + ), ) private val successImageName: String = "Photos/Success.png" @@ -101,7 +103,7 @@ object MockNetworkHandler : NetworkHandler { } connected = credentials == successLoginCredentials print("Is Connected $connected\n") - if(!connected) { + if (!connected) { print("Success Credentials: $successLoginCredentials\n") print("Actual Credentials $credentials\n") } @@ -148,10 +150,16 @@ object MockNetworkHandler : NetworkHandler { } override suspend fun folderExists(path: String): Boolean? = - if (path == "") null - else networkContents.keys.contains(path) + if (path == "") { + null + } else { + networkContents.keys.contains(path) + } - override suspend fun savePlaylist(playlistName: String, json: String): Boolean { + override suspend fun savePlaylist( + playlistName: String, + json: String, + ): Boolean { playlists[playlistName] = json return true } diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/domain/SaveCredentialsUseCaseTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/domain/SaveCredentialsUseCaseTest.kt index 3c7e0411..50c6574f 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/domain/SaveCredentialsUseCaseTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/domain/SaveCredentialsUseCaseTest.kt @@ -1,7 +1,6 @@ package com.kevinschildhorn.fotopresenter.domain import co.touchlab.kermit.Logger -import co.touchlab.kermit.LoggerConfig import com.kevinschildhorn.fotopresenter.data.LoginCredentials import com.kevinschildhorn.fotopresenter.domain.connection.SaveCredentialsUseCase import com.kevinschildhorn.fotopresenter.testingModule diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt index 4c08a34b..50d79ede 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt @@ -21,9 +21,7 @@ import org.koin.test.inject import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.assertEquals -import kotlin.test.assertFalse import kotlin.test.assertNotNull -import kotlin.test.assertTrue /** Testing [DirectoryViewModel] @@ -130,10 +128,11 @@ class DirectoryViewModelTest : KoinTest { state = awaitItem() assertEquals(UiState.SUCCESS, state.state) - val directory = FolderDirectoryGridCellState( - name = "", - id = MockNetworkHandler.photoDirectoryId, - ) + val directory = + FolderDirectoryGridCellState( + name = "", + id = MockNetworkHandler.photoDirectoryId, + ) viewModel.setSelectedDirectory(directory) viewModel.startSlideshow() while (state.slideshowDetails == null) { diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/LoginViewModelTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/LoginViewModelTest.kt index a02dd170..49641140 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/LoginViewModelTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/LoginViewModelTest.kt @@ -6,8 +6,6 @@ import com.kevinschildhorn.fotopresenter.ui.UiState import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.russhwolf.settings.MapSettings import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.delay -import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.koin.core.context.startKoin import org.koin.core.context.stopKoin @@ -159,7 +157,6 @@ class LoginViewModelTest : KoinTest { } } - @Test fun `Login Success`() = runTest { diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/KoinDesktop.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/KoinDesktop.kt index 4157ea77..5674f68b 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/KoinDesktop.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/KoinDesktop.kt @@ -16,12 +16,13 @@ fun startKoin() { } } -internal actual val platformModule: Module = module { - single { - PreferencesSettings(get()) +internal actual val platformModule: Module = + module { + single { + PreferencesSettings(get()) + } + single { + SMBJHandler + } + single { DriverFactory().createDriver() } } - single { - SMBJHandler - } - single { DriverFactory().createDriver() } -} diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt index d621ec4b..81e9e649 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt @@ -1,11 +1,13 @@ +@file:Suppress("ktlint:standard:filename") + package com.kevinschildhorn.fotopresenter import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource -import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource import com.kevinschildhorn.fotopresenter.data.datasources.ImageMetadataDataSource import com.kevinschildhorn.fotopresenter.data.datasources.PlaylistFileDataSource import com.kevinschildhorn.fotopresenter.data.datasources.PlaylistSQLDataSource +import com.kevinschildhorn.fotopresenter.data.datasources.image.CachedImageDataSource import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler import com.kevinschildhorn.fotopresenter.data.network.SMBJHandler import com.kevinschildhorn.fotopresenter.data.repositories.CredentialsRepository @@ -27,26 +29,28 @@ import com.russhwolf.settings.PreferencesSettings import java.util.prefs.Preferences actual object UseCaseFactory { - private val preferences: Preferences = Preferences.userRoot() private val settings = PreferencesSettings(preferences) private val networkHandler: NetworkHandler = SMBJHandler - private val directoryDataSource = DirectoryDataSource( - networkHandler, - baseLogger.withTag("DirectoryDataSource") - ) + private val directoryDataSource = + DirectoryDataSource( + networkHandler, + baseLogger.withTag("DirectoryDataSource"), + ) private val sqlDriver = DriverFactory().createDriver() private val credentialDataSource = CredentialsDataSource(settings) val credentialsRepository = CredentialsRepository(credentialDataSource) - private val imageMetadataDataSource = ImageMetadataDataSource( - networkHandler = networkHandler, - logger = baseLogger.withTag("imageMetadataDataSource") - ) + private val imageMetadataDataSource = + ImageMetadataDataSource( + networkHandler = networkHandler, + logger = baseLogger.withTag("imageMetadataDataSource"), + ) private val directoryRepository = DirectoryRepository(directoryDataSource, imageMetadataDataSource) - private val playlistSQLDataSource = PlaylistSQLDataSource( - sqlDriver, - com.kevinschildhorn.fotopresenter.baseLogger - ) + private val playlistSQLDataSource = + PlaylistSQLDataSource( + sqlDriver, + com.kevinschildhorn.fotopresenter.baseLogger, + ) private val playlistFileDataSource = PlaylistFileDataSource( baseLogger.withTag("playlistFileDataSource"), @@ -55,58 +59,69 @@ actual object UseCaseFactory { val playlistRepository = PlaylistRepository(playlistSQLDataSource, playlistFileDataSource) actual val connectToServerUseCase: ConnectToServerUseCase - get() = ConnectToServerUseCase( - client = networkHandler, - logger = baseLogger.withTag("ConnectToServerUseCase") - ) + get() = + ConnectToServerUseCase( + client = networkHandler, + logger = baseLogger.withTag("ConnectToServerUseCase"), + ) actual val changeDirectoryUseCase: ChangeDirectoryUseCase - get() = ChangeDirectoryUseCase( - dataSource = DirectoryDataSource( - networkHandler, - baseLogger.withTag("DirectoryDataSource") - ), - logger = baseLogger.withTag("ChangeDirectoryUseCase") - ) + get() = + ChangeDirectoryUseCase( + dataSource = + DirectoryDataSource( + networkHandler, + baseLogger.withTag("DirectoryDataSource"), + ), + logger = baseLogger.withTag("ChangeDirectoryUseCase"), + ) actual val autoConnectUseCase: AutoConnectUseCase - get() = AutoConnectUseCase( - client = networkHandler, - repository = credentialsRepository, - logger = baseLogger.withTag("AutoConnectUseCase") - ) + get() = + AutoConnectUseCase( + client = networkHandler, + repository = credentialsRepository, + logger = baseLogger.withTag("AutoConnectUseCase"), + ) actual val saveCredentialsUseCase: SaveCredentialsUseCase - get() = SaveCredentialsUseCase( - repository = credentialsRepository, - logger = baseLogger.withTag("SaveCredentialsUseCase") - ) + get() = + SaveCredentialsUseCase( + repository = credentialsRepository, + logger = baseLogger.withTag("SaveCredentialsUseCase"), + ) actual val disconnectFromServerUseCase: DisconnectFromServerUseCase - get() = DisconnectFromServerUseCase( - credentialsRepository, - networkHandler, - baseLogger.withTag("DisconnectFromServerUseCase") - ) + get() = + DisconnectFromServerUseCase( + credentialsRepository, + networkHandler, + baseLogger.withTag("DisconnectFromServerUseCase"), + ) actual val retrieveImageDirectoriesUseCase: RetrieveImageDirectoriesUseCase - get() = RetrieveImageDirectoriesUseCase( - logger = baseLogger.withTag("RetrieveImageDirectoriesUseCase") - ) + get() = + RetrieveImageDirectoriesUseCase( + logger = baseLogger.withTag("RetrieveImageDirectoriesUseCase"), + ) actual val retrieveSlideshowFromPlaylistUseCase: RetrieveSlideshowFromPlaylistUseCase - get() = RetrieveSlideshowFromPlaylistUseCase( - logger = baseLogger.withTag("RetrieveSlideshowFromPlaylistUseCase"), - retrieveDirectoryUseCase = this.retrieveImageDirectoriesUseCase, - ) + get() = + RetrieveSlideshowFromPlaylistUseCase( + logger = baseLogger.withTag("RetrieveSlideshowFromPlaylistUseCase"), + retrieveDirectoryUseCase = this.retrieveImageDirectoriesUseCase, + ) actual val retrieveDirectoryContentsUseCase: RetrieveDirectoryContentsUseCase - get() = RetrieveDirectoryContentsUseCase( - directoryRepository = directoryRepository, - logger = baseLogger.withTag("RetrieveDirectoryContentsUseCase") - ) + get() = + RetrieveDirectoryContentsUseCase( + directoryRepository = directoryRepository, + logger = baseLogger.withTag("RetrieveDirectoryContentsUseCase"), + ) actual val retrieveImageUseCase: RetrieveImageUseCase - get() = RetrieveImageUseCase( - cachedImageDataSource = CachedImageDataSource( - cache = SharedInMemoryCache, - driver = sqlDriver, - logger = baseLogger.withTag("ImageCacheDataSource") - ), - logger = baseLogger.withTag("RetrieveImageUseCase") - ) + get() = + RetrieveImageUseCase( + cachedImageDataSource = + CachedImageDataSource( + cache = SharedInMemoryCache, + driver = sqlDriver, + logger = baseLogger.withTag("ImageCacheDataSource"), + ), + logger = baseLogger.withTag("RetrieveImageUseCase"), + ) actual val saveMetadataForPathUseCase: SaveMetadataForPathUseCase get() = SaveMetadataForPathUseCase(dataSource = imageMetadataDataSource) -} \ No newline at end of file +} diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/DriverFactory.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/DriverFactory.kt index 93fb9c9c..dc0e3ca7 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/DriverFactory.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/DriverFactory.kt @@ -10,4 +10,4 @@ actual class DriverFactory { PlaylistDatabase.Schema.create(driver) return driver } -} \ No newline at end of file +} diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt index f0aca7c0..29e52185 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt @@ -1,10 +1,10 @@ +@file:Suppress("ktlint:standard:filename") + package com.kevinschildhorn.fotopresenter.ui.shared import coil3.Image - actual open class SharedImage actual constructor(actual val byteArray: ByteArray) { // TODO actual fun getCoilImage(size: Int): Image? = null } - diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/ViewModel.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/ViewModel.kt index dc6d93d0..60eb688b 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/ViewModel.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/ViewModel.kt @@ -25,4 +25,4 @@ actual abstract class ViewModel { onCleared() // viewModelScope.cancel() TODO } -} \ No newline at end of file +} diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt index 422f7a4e..69b4ed81 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt @@ -15,19 +15,14 @@ import com.hierynomus.smbj.share.File import com.kevinschildhorn.fotopresenter.data.LoginCredentials import com.kevinschildhorn.fotopresenter.extension.addPath import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.json.Json import java.io.OutputStream -import java.util.* -import kotlin.math.log - object SMBJHandler : NetworkHandler { private val client = SMBClient() private var connection: Connection? = null private var session: Session? = null private var share: DiskShare? = null - private const val metaDataName: String = "FotoMetaData.json" + private const val META_DATA_NAME: String = "FotoMetaData.json" private val logger = Logger.withTag("SMBJHandler") private val accessMask: Set = @@ -93,14 +88,15 @@ object SMBJHandler : NetworkHandler { override suspend fun openDirectory(path: String): String? { logger.i { "Opening Directory $path" } - val result = share?.openDirectory( - path, - accessMask, - attributes, - shareAccesses, - createDisposition, - createOptions, - ) + val result = + share?.openDirectory( + path, + accessMask, + attributes, + shareAccesses, + createDisposition, + createOptions, + ) return result?.path } @@ -125,13 +121,15 @@ object SMBJHandler : NetworkHandler { connection = null } - override suspend fun savePlaylist(playlistName: String, json: String): Boolean = - writeFile(fileName = "$playlistName.json", contents = json) + override suspend fun savePlaylist( + playlistName: String, + json: String, + ): Boolean = writeFile(fileName = "$playlistName.json", contents = json) override suspend fun getPlaylists(): List = getDirectoryContents("") .filter { it.fileExtension == "json" } - .filter { !it.fileName.contains(metaDataName) } + .filter { !it.fileName.contains(META_DATA_NAME) } .mapNotNull { getFile(it.fullPath) } .map { val str = it.inputStream.readAllBytes().decodeToString() @@ -141,24 +139,22 @@ object SMBJHandler : NetworkHandler { override suspend fun setMetadata(json: String): Boolean { logger.i { "Setting Metadata" } - return writeFile(fileName = metaDataName, contents = json) + return writeFile(fileName = META_DATA_NAME, contents = json) } - override suspend fun getMetadata(): String? = getFile(metaDataName)?.let { - logger.i { "Importing Metadata" } - val str = it.inputStream.readAllBytes().decodeToString() - it.close() - str - } + override suspend fun getMetadata(): String? = + getFile(META_DATA_NAME)?.let { + logger.i { "Importing Metadata" } + val str = it.inputStream.readAllBytes().decodeToString() + it.close() + str + } override suspend fun deletePlaylist(playlistName: String) { share?.rm("$playlistName.json") } - - private fun getFile( - path: String, - ): File? = + private fun getFile(path: String): File? = try { logger.v { "Getting File at path $path" } share?.openFile( @@ -174,8 +170,10 @@ object SMBJHandler : NetworkHandler { null } - - private suspend fun writeFile(fileName: String, contents: String): Boolean { + private suspend fun writeFile( + fileName: String, + contents: String, + ): Boolean { logger.i { "Writing File" } val fileAttributes: MutableSet = HashSet() fileAttributes.add(FileAttributes.FILE_ATTRIBUTE_NORMAL) @@ -183,16 +181,16 @@ object SMBJHandler : NetworkHandler { createOptions.add(SMB2CreateOptions.FILE_RANDOM_ACCESS) try { - logger.i { "Trying to open a file $fileName" } - val file = share?.openFile( - fileName, - setOf(AccessMask.GENERIC_ALL), - fileAttributes, - SMB2ShareAccess.ALL, - SMB2CreateDisposition.FILE_OVERWRITE_IF, - createOptions - ) + val file = + share?.openFile( + fileName, + setOf(AccessMask.GENERIC_ALL), + fileAttributes, + SMB2ShareAccess.ALL, + SMB2CreateDisposition.FILE_OVERWRITE_IF, + createOptions, + ) file?.let { logger.i { "Got the file, writing contents" } val oStream: OutputStream = it.outputStream diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJNetworkDirectoryDetails.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJNetworkDirectoryDetails.kt index b93a74be..32642672 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJNetworkDirectoryDetails.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJNetworkDirectoryDetails.kt @@ -9,5 +9,4 @@ class SMBJNetworkDirectoryDetails( override val id: Int = information.fileId.toInt() override val dateMillis: Long = information.changeTime.toEpochMillis() - } diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt index ba19b311..651ef073 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt @@ -11,16 +11,14 @@ import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -// ImageRepository class SMBJFetcher( private val directoryDetails: NetworkDirectoryDetails, private val imageRepository: ImageRepository, ) : Fetcher { - override suspend fun fetch(): FetchResult? { return withContext(Dispatchers.IO) { val image = imageRepository.getCoilImage(directoryDetails, 64) - if(image != null) { + if (image != null) { ImageFetchResult( image = image, isSampled = true, @@ -37,7 +35,7 @@ class SMBJFetcher( override fun create( data: NetworkDirectoryDetails, options: Options, - imageLoader: ImageLoader + imageLoader: ImageLoader, ): Fetcher = SMBJFetcher(data, imageRepository) } -} \ No newline at end of file +} From a48db179a685c7974bcf80608c20305a857c539e Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Wed, 16 Oct 2024 15:51:42 -0400 Subject: [PATCH 17/19] updating test --- .../ImageFileRemoteDataSourceTest.kt | 72 ------------------- .../ui/viewmodel/DirectoryViewModelTest.kt | 4 +- 2 files changed, 2 insertions(+), 74 deletions(-) delete mode 100644 shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageFileRemoteDataSourceTest.kt diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageFileRemoteDataSourceTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageFileRemoteDataSourceTest.kt deleted file mode 100644 index 09f9e084..00000000 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageFileRemoteDataSourceTest.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.kevinschildhorn.fotopresenter.data.datasources - -import com.kevinschildhorn.fotopresenter.data.network.DefaultNetworkDirectoryDetails -import com.kevinschildhorn.fotopresenter.data.network.MockNetworkHandler -import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerError -import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException -import junit.framework.TestCase.assertEquals -import kotlinx.coroutines.runBlocking -import kotlin.test.AfterTest -import kotlin.test.BeforeTest -import kotlin.test.Test -import kotlin.test.assertNull -import kotlin.test.fail - -/** -Testing [ImageFileRemoteDataSource] - **/ -class ImageFileRemoteDataSourceTest { - private val networkHandler: MockNetworkHandler = MockNetworkHandler - private val dataSource = ImageFileRemoteDataSource(networkHandler) - - @BeforeTest - fun startTest() = - runBlocking { - networkHandler.connectSuccessfully() - } - - @AfterTest - fun tearDown() = - runBlocking { - networkHandler.disconnect() - } - - @Test - fun `get Image Success`() = - runBlocking { - val networkDirectory = - DefaultNetworkDirectoryDetails( - fullPath = "Photos/Success.png", - id = 1, - ) - try { - val image = dataSource.getImage(networkDirectory) - } catch (e: Exception) { - assertEquals("Success", e.message) - } - } - - @Test - fun `get Image Failure`() = - runBlocking { - val networkDirectory = - DefaultNetworkDirectoryDetails( - fullPath = "Photos/nonExistant.png", - id = 1, - ) - val image = dataSource.getImage(networkDirectory) - assertNull(image) - } - - @Test - fun `get Image Disconnected`() = - runBlocking { - networkHandler.disconnect() - try { - val image = dataSource.getImage(DefaultNetworkDirectoryDetails("", 1)) - fail("Should have thrown exception") - } catch (e: NetworkHandlerException) { - assertEquals(e.message, NetworkHandlerError.NOT_CONNECTED.message) - } - } -} diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt index 50d79ede..9d462b34 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModelTest.kt @@ -4,8 +4,8 @@ import app.cash.turbine.test import com.kevinschildhorn.fotopresenter.data.network.MockNetworkHandler import com.kevinschildhorn.fotopresenter.testingModule import com.kevinschildhorn.fotopresenter.ui.UiState +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryGridCellState import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel -import com.kevinschildhorn.fotopresenter.ui.screens.directory.FolderDirectoryGridCellState import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking @@ -129,7 +129,7 @@ class DirectoryViewModelTest : KoinTest { assertEquals(UiState.SUCCESS, state.state) val directory = - FolderDirectoryGridCellState( + DirectoryGridCellState.Folder( name = "", id = MockNetworkHandler.photoDirectoryId, ) From 25134be92b610ba0a9c7682fa7865ea3d720a211 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Wed, 16 Oct 2024 15:59:38 -0400 Subject: [PATCH 18/19] formatting --- .../com/kevinschildhorn/fotopresenter/Koin.kt | 2 - .../image/CachedImageDataSource.kt | 9 ++-- .../data/repositories/ImageRepository.kt | 11 +++-- .../fotopresenter/ui/ByteArrayFetcher.kt | 4 +- .../fotopresenter/ui/shared/SharedCache.kt | 42 +++++++++---------- .../fotopresenter/ui/shared/SharedImage.kt | 1 + .../ui/shared/SharedImageDesktop.kt | 10 ++--- .../fotopresenter/ui/SMBJFetcher.kt | 26 ++++++------ 8 files changed, 52 insertions(+), 53 deletions(-) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt index 0e213061..826192ec 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt @@ -26,8 +26,6 @@ import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel -import com.kevinschildhorn.fotopresenter.ui.shared.CacheInterface -import com.kevinschildhorn.fotopresenter.ui.shared.SharedFileCache import org.koin.core.module.Module import org.koin.dsl.module diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt index 14f3f9f1..739a112f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt @@ -6,7 +6,6 @@ import com.kevinschildhorn.fotopresenter.PlaylistDatabase import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.ui.shared.CacheInterface import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage -import com.kevinschildhorn.fotopresenter.Image as SQLImage class CachedImageDataSource( private val cache: CacheInterface, @@ -20,8 +19,8 @@ class CachedImageDataSource( logger.i { "Getting Image from Cache ${directory.cacheId}" } return try { cache.getImage(directory.cacheId) - //val image = database.imageQueries.selectImageByName(directory.cacheId).executeAsOne() - //SharedImage(image.image) + // val image = database.imageQueries.selectImageByName(directory.cacheId).executeAsOne() + // SharedImage(image.image) } catch (e: Exception) { logger.e(e) { "Image NOT found" } logger.e { e.localizedMessage ?: "" } @@ -35,10 +34,10 @@ class CachedImageDataSource( ) { logger.i { "Saving Image To Cache ${directory.cacheId}" } cache.cacheImage(directory.cacheId, image) - //database.imageQueries.insertImage( + // database.imageQueries.insertImage( // directory.cacheId, // image.byteArray, - //) + // ) logger.i { "Image Saved" } // cache.cacheImage(directory.cacheId, image) TODO } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt index e31d4db1..af52436e 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt @@ -12,13 +12,18 @@ class ImageRepository( private val localImageDataSource: CachedImageDataSource, private val logger: Logger?, ) { - - suspend fun getFetchResult(directoryDetails: NetworkDirectoryDetails, size: Int): FetchResult? { + suspend fun getFetchResult( + directoryDetails: NetworkDirectoryDetails, + size: Int, + ): FetchResult? { val image = getImage(directoryDetails, size) return image?.getFetchResult(size) } - private suspend fun getImage(directoryDetails: NetworkDirectoryDetails, size: Int): SharedImage? { + private suspend fun getImage( + directoryDetails: NetworkDirectoryDetails, + size: Int, + ): SharedImage? { logger?.i { "Getting Image from Cache: ${directoryDetails.name}" } val cachedImage = localImageDataSource.getImage(directoryDetails) if (cachedImage != null) { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt index 1c05013b..6ce5ce2d 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/ByteArrayFetcher.kt @@ -2,11 +2,9 @@ package com.kevinschildhorn.fotopresenter.ui import co.touchlab.kermit.Logger import coil3.ImageLoader -import coil3.decode.DataSource import coil3.fetch.FetchResult import coil3.fetch.Fetcher import coil3.request.Options -import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -33,7 +31,7 @@ class ByteArrayFetcher( override fun create( data: ByteArray, options: Options, - imageLoader: ImageLoader + imageLoader: ImageLoader, ): Fetcher = ByteArrayFetcher(data, logger) } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt index a8b7df28..891ef2e9 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedCache.kt @@ -17,9 +17,10 @@ interface CacheInterface { object SharedInMemoryCache : CacheInterface { private val imageCache = Cache.Builder().build() - override suspend fun getImage(id: String): SharedImage? = imageCache.get(id)?.let { - SharedImage(it) - } + override suspend fun getImage(id: String): SharedImage? = + imageCache.get(id)?.let { + SharedImage(it) + } override suspend fun cacheImage( id: String, @@ -30,7 +31,6 @@ object SharedInMemoryCache : CacheInterface { } class SharedFileCache(private val cacheLocation: String) : CacheInterface { - override suspend fun getImage(id: String): SharedImage? { val cache = createCache() @@ -46,31 +46,30 @@ class SharedFileCache(private val cacheLocation: String) : CacheInterface { ) { val cache = createCache() try { - val imageData = cache?.put(id) { path -> - val file = File(path) - try { - val stream = file.outputStream() - stream.write(image.byteArray) - stream.close() - true - } catch (e: Exception) { - println(e.localizedMessage) - false + val imageData = + cache?.put(id) { path -> + val file = File(path) + try { + val stream = file.outputStream() + stream.write(image.byteArray) + stream.close() + true + } catch (e: Exception) { + println(e.localizedMessage) + false + } } - } println(imageData) } finally { cache?.close() } } - private suspend fun createCache(): FileKache? { try { println("Creating Cache") - return FileKache(directory = cacheLocation, maxSize = 10 * 1024 * 1024) { + return FileKache(directory = cacheLocation, maxSize = 10 * 1024 * 1024) { strategy = KacheStrategy.LRU - } } catch (e: Exception) { println("Error Creating Cache") @@ -90,7 +89,8 @@ class MockSharedCache : CacheInterface { contents[id] = image.byteArray } - override suspend fun getImage(id: String): SharedImage? = contents[id]?.let { - SharedImage(it) - } + override suspend fun getImage(id: String): SharedImage? = + contents[id]?.let { + SharedImage(it) + } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index bea3c18f..c229a9b6 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -4,6 +4,7 @@ import coil3.fetch.FetchResult expect class SharedImage(byteArray: ByteArray) { val byteArray: ByteArray + fun getFetchResult(size: Int): FetchResult? } diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt index 4c22a3e0..e492b0a1 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageDesktop.kt @@ -2,7 +2,6 @@ package com.kevinschildhorn.fotopresenter.ui.shared -import coil3.Image import coil3.decode.DataSource import coil3.decode.ImageSource import coil3.fetch.FetchResult @@ -17,10 +16,11 @@ actual open class SharedImage actual constructor(actual val byteArray: ByteArray val source = ByteArrayInputStream(byteArray).source().buffer() return SourceFetchResult( - source = ImageSource( - source = source, - fileSystem = FileSystem.SYSTEM, - ), + source = + ImageSource( + source = source, + fileSystem = FileSystem.SYSTEM, + ), mimeType = null, dataSource = DataSource.NETWORK, ) diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt index 4add029c..e1caacba 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SMBJFetcher.kt @@ -2,10 +2,8 @@ package com.kevinschildhorn.fotopresenter.ui import co.touchlab.kermit.Logger import coil3.ImageLoader -import coil3.decode.DataSource import coil3.fetch.FetchResult import coil3.fetch.Fetcher -import coil3.fetch.ImageFetchResult import coil3.request.Options import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository @@ -17,26 +15,26 @@ class SMBJFetcher( private val imageRepository: ImageRepository, private val logger: Logger, ) : Fetcher { + override suspend fun fetch(): FetchResult? = + withContext(Dispatchers.IO) { + logger.i { "Fetching image: ${directoryDetails.name}" } - override suspend fun fetch(): FetchResult? = withContext(Dispatchers.IO) { - logger.i { "Fetching image: ${directoryDetails.name}" } - - val image = imageRepository.getFetchResult(directoryDetails, 64) - if (image != null) { - logger.i { "Image Got! ${directoryDetails.name}" } - image - } else { - logger.i { "No Image Fetched: ${directoryDetails.name}" } - null + val image = imageRepository.getFetchResult(directoryDetails, 64) + if (image != null) { + logger.i { "Image Got! ${directoryDetails.name}" } + image + } else { + logger.i { "No Image Fetched: ${directoryDetails.name}" } + null + } } - } class Factory(private val imageRepository: ImageRepository, private val logger: Logger) : Fetcher.Factory { override fun create( data: NetworkDirectoryDetails, options: Options, - imageLoader: ImageLoader + imageLoader: ImageLoader, ): Fetcher = SMBJFetcher(data, imageRepository, logger) } } From 2f67ae93e6ba61f1631479239e58a71589707807 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Wed, 16 Oct 2024 16:03:21 -0400 Subject: [PATCH 19/19] formatting --- .../fotopresenter/KoinAndroid.kt | 17 ++++++++--------- .../ui/shared/SharedImageAndroid.kt | 16 +++++++++------- .../datasources/image/CachedImageDataSource.kt | 3 +-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt index d4749225..181713fe 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/KoinAndroid.kt @@ -49,16 +49,15 @@ internal actual val platformModule: Module = SMBJHandler } single { DriverFactory(context = get()).createDriver() } + single { + SMBJHandler + } + single { DriverFactory(context = get()).createDriver() } + single { + val context: Context = get() + SharedFileCache(context.cacheDir.path) + } } - single { - SMBJHandler - } - single { DriverFactory(context = get()).createDriver() } - single { - val context:Context = get() - SharedFileCache(context.cacheDir.path) - } -} @OptIn(KoinInternalApi::class) fun KoinApplication.androidContext(androidContext: Context): KoinApplication { diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt index 7ac17a64..c3fa9a61 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt @@ -11,15 +11,17 @@ import coil3.fetch.FetchResult import coil3.fetch.ImageFetchResult actual open class SharedImage actual constructor(actual val byteArray: ByteArray) { - actual fun getFetchResult(size: Int): FetchResult? { val image: Image? = getAndroidBitmap(byteArray, size)?.asImage() - return if (image != null) ImageFetchResult( - image = image, - isSampled = true, - dataSource = DataSource.NETWORK, - ) - else null + return if (image != null) { + ImageFetchResult( + image = image, + isSampled = true, + dataSource = DataSource.NETWORK, + ) + } else { + null + } } private fun getCoilImage(size: Int): Image? = getAndroidBitmap(byteArray, size)?.asImage() diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt index 739a112f..ddb6791f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/image/CachedImageDataSource.kt @@ -11,7 +11,6 @@ class CachedImageDataSource( private val cache: CacheInterface, private val logger: Logger, driver: SqlDriver, - private val logger: Logger, ) { private val database = PlaylistDatabase(driver) @@ -28,7 +27,7 @@ class CachedImageDataSource( } } - fun saveImage( + suspend fun saveImage( directory: NetworkDirectoryDetails, image: SharedImage, ) {