From 3187fc32001302606f4c24be7ca56eef97ff9464 Mon Sep 17 00:00:00 2001 From: Gerard Paligot Date: Fri, 24 Nov 2023 00:03:18 +0100 Subject: [PATCH] refactor(openfeedback): migrate to KMP. --- build-logic/build.gradle.kts | 8 +++ .../kotlin/io/openfeedback/OpenFeedback.kt | 4 -- .../extensions/LibraryExtensionExt.kt | 10 ---- .../plugins/ComposeLibraryPlugin.kt | 4 -- .../io/openfeedback/plugins/LibraryPlugin.kt | 4 -- .../plugins/MultiplatformPlugin.kt | 22 ++++++++ .../openfeedback/plugins/PublishingPlugin.kt | 15 ++++++ build.gradle.kts | 3 +- libs.versions.toml | 17 +++++- openfeedback-m2/build.gradle.kts | 1 + .../io/openfeedback/android/m2/PoweredBy.kt | 2 +- openfeedback-m3/build.gradle.kts | 2 + .../io/openfeedback/android/m3/Comment.kt | 2 +- .../openfeedback/android/m3/CommentInput.kt | 2 +- .../openfeedback/android/m3/CommentItems.kt | 2 +- .../io/openfeedback/android/m3/PoweredBy.kt | 2 +- openfeedback-viewmodel/build.gradle.kts | 1 + .../viewmodels/OpenFeedbackViewModel.kt | 14 ++--- .../android/viewmodels/mappers/UiMappers.kt | 21 ++++++-- openfeedback/build.gradle.kts | 50 +++++++++++++----- .../mappers/FirestoreToModelMappers.kt | 21 ++++++++ .../src/commonMain/kotlin/io/.DS_Store | Bin 0 -> 6148 bytes .../openfeedback}/OpenFeedbackRepository.kt | 16 +++--- .../caches/OptimisticVoteCaching.kt | 6 +-- .../mappers/FirestoreToModelMappers.kt | 5 ++ .../kotlin/io/openfeedback}/model/Model.kt | 8 +-- .../openfeedback}/sources/OpenFeedbackAuth.kt | 2 +- .../sources/OpenFeedbackFirestore.kt | 12 ++--- .../resources/MR/base}/strings.xml | 0 .../resources/MR/fr}/strings.xml | 0 .../MR/images/openfeedback_dark@1x.png} | Bin .../MR/images/openfeedback_light@1x.png} | Bin .../android/FirebaseExtensions.kt | 45 ---------------- .../mappers/FirestoreToModelMappers.kt | 16 ------ settings.gradle.kts | 1 + 35 files changed, 180 insertions(+), 138 deletions(-) create mode 100644 build-logic/src/main/kotlin/io/openfeedback/plugins/MultiplatformPlugin.kt create mode 100644 build-logic/src/main/kotlin/io/openfeedback/plugins/PublishingPlugin.kt create mode 100644 openfeedback/src/androidMain/kotlin/io/openfeedback/mappers/FirestoreToModelMappers.kt create mode 100644 openfeedback/src/commonMain/kotlin/io/.DS_Store rename openfeedback/src/{main/java/io/openfeedback/android => commonMain/kotlin/io/openfeedback}/OpenFeedbackRepository.kt (84%) rename openfeedback/src/{main/java/io/openfeedback/android => commonMain/kotlin/io/openfeedback}/caches/OptimisticVoteCaching.kt (90%) create mode 100644 openfeedback/src/commonMain/kotlin/io/openfeedback/mappers/FirestoreToModelMappers.kt rename openfeedback/src/{main/java/io/openfeedback/android => commonMain/kotlin/io/openfeedback}/model/Model.kt (86%) rename openfeedback/src/{main/java/io/openfeedback/android => commonMain/kotlin/io/openfeedback}/sources/OpenFeedbackAuth.kt (96%) rename openfeedback/src/{main/java/io/openfeedback/android => commonMain/kotlin/io/openfeedback}/sources/OpenFeedbackFirestore.kt (96%) rename openfeedback/src/{main/res/values => commonMain/resources/MR/base}/strings.xml (100%) rename openfeedback/src/{main/res/values-fr => commonMain/resources/MR/fr}/strings.xml (100%) rename openfeedback/src/{main/res/drawable/openfeedback_dark.png => commonMain/resources/MR/images/openfeedback_dark@1x.png} (100%) rename openfeedback/src/{main/res/drawable/openfeedback_light.png => commonMain/resources/MR/images/openfeedback_light@1x.png} (100%) delete mode 100644 openfeedback/src/main/java/io/openfeedback/android/FirebaseExtensions.kt delete mode 100644 openfeedback/src/main/java/io/openfeedback/android/mappers/FirestoreToModelMappers.kt diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 47c5692..0fd62ab 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -22,10 +22,18 @@ gradlePlugin { id = "io.openfeedback.plugins.lib" implementationClass = "io.openfeedback.plugins.LibraryPlugin" } + register("io.openfeedback.plugins.lib.multiplatform") { + id = "io.openfeedback.plugins.lib.multiplatform" + implementationClass = "io.openfeedback.plugins.MultiplatformPlugin" + } register("io.openfeedback.plugins.compose.lib") { id = "io.openfeedback.plugins.compose.lib" implementationClass = "io.openfeedback.plugins.ComposeLibraryPlugin" } + register("io.openfeedback.plugins.publishing") { + id = "io.openfeedback.plugins.publishing" + implementationClass = "io.openfeedback.plugins.PublishingPlugin" + } register("io.openfeedback.plugins.app") { id = "io.openfeedback.plugins.app" implementationClass = "io.openfeedback.plugins.AppPlugin" diff --git a/build-logic/src/main/kotlin/io/openfeedback/OpenFeedback.kt b/build-logic/src/main/kotlin/io/openfeedback/OpenFeedback.kt index 13a064c..565c943 100644 --- a/build-logic/src/main/kotlin/io/openfeedback/OpenFeedback.kt +++ b/build-logic/src/main/kotlin/io/openfeedback/OpenFeedback.kt @@ -1,11 +1,7 @@ package io.openfeedback -import com.android.build.gradle.internal.tasks.factory.dependsOn -import io.openfeedback.extensions.* import io.openfeedback.extensions.configurePublishingInternal import org.gradle.api.Project -import org.gradle.api.logging.LogLevel -import org.gradle.api.tasks.PathSensitivity open class OpenFeedback(val project: Project) { fun Project.configurePublishing(artifactName: String) { diff --git a/build-logic/src/main/kotlin/io/openfeedback/extensions/LibraryExtensionExt.kt b/build-logic/src/main/kotlin/io/openfeedback/extensions/LibraryExtensionExt.kt index bedda6a..40604f1 100644 --- a/build-logic/src/main/kotlin/io/openfeedback/extensions/LibraryExtensionExt.kt +++ b/build-logic/src/main/kotlin/io/openfeedback/extensions/LibraryExtensionExt.kt @@ -6,10 +6,8 @@ import com.android.build.api.dsl.CommonExtension import org.gradle.api.JavaVersion import org.gradle.api.Project import org.gradle.api.artifacts.VersionCatalogsExtension -import org.gradle.api.plugins.ExtensionAware import org.gradle.kotlin.dsl.dependencies import org.gradle.kotlin.dsl.getByType -import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions internal fun CommonExtension<*, *, *, *, *>.configureKotlinAndroid() { compileSdk = 34 @@ -22,10 +20,6 @@ internal fun CommonExtension<*, *, *, *, *>.configureKotlinAndroid() { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } } internal fun CommonExtension<*, *, *, *, *>.configureAndroidCompose(project: Project) { @@ -44,7 +38,3 @@ internal fun CommonExtension<*, *, *, *, *>.configureAndroidCompose(project: Pro add("debugImplementation", "androidx.savedstate:savedstate-ktx:1.2.0") } } - -private fun CommonExtension<*, *, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { - (this as ExtensionAware).extensions.configure("kotlinOptions", block) -} diff --git a/build-logic/src/main/kotlin/io/openfeedback/plugins/ComposeLibraryPlugin.kt b/build-logic/src/main/kotlin/io/openfeedback/plugins/ComposeLibraryPlugin.kt index fd673c3..3be1749 100644 --- a/build-logic/src/main/kotlin/io/openfeedback/plugins/ComposeLibraryPlugin.kt +++ b/build-logic/src/main/kotlin/io/openfeedback/plugins/ComposeLibraryPlugin.kt @@ -1,7 +1,6 @@ package io.openfeedback.plugins import com.android.build.gradle.LibraryExtension -import io.openfeedback.OpenFeedback import io.openfeedback.extensions.configureAndroidCompose import io.openfeedback.extensions.configureKotlinAndroid import io.openfeedback.extensions.configureKotlinCompiler @@ -14,11 +13,8 @@ class ComposeLibraryPlugin : Plugin { with(target.pluginManager) { apply("com.android.library") apply("org.jetbrains.kotlin.android") - apply("maven-publish") - apply("signing") } - target.extensions.create("openfeedback", OpenFeedback::class.java, target) target.extensions.configure { configureKotlinAndroid() configureAndroidCompose(target) diff --git a/build-logic/src/main/kotlin/io/openfeedback/plugins/LibraryPlugin.kt b/build-logic/src/main/kotlin/io/openfeedback/plugins/LibraryPlugin.kt index 823ba93..cb56230 100644 --- a/build-logic/src/main/kotlin/io/openfeedback/plugins/LibraryPlugin.kt +++ b/build-logic/src/main/kotlin/io/openfeedback/plugins/LibraryPlugin.kt @@ -1,7 +1,6 @@ package io.openfeedback.plugins import com.android.build.gradle.LibraryExtension -import io.openfeedback.OpenFeedback import io.openfeedback.extensions.configureKotlinAndroid import io.openfeedback.extensions.configureKotlinCompiler import org.gradle.api.Plugin @@ -14,11 +13,8 @@ class LibraryPlugin : Plugin { apply("com.android.library") apply("org.jetbrains.kotlin.android") apply("org.jetbrains.kotlin.plugin.serialization") - apply("maven-publish") - apply("signing") } - target.extensions.create("openfeedback", OpenFeedback::class.java, target) target.extensions.configure { configureKotlinAndroid() defaultConfig.targetSdk = 34 diff --git a/build-logic/src/main/kotlin/io/openfeedback/plugins/MultiplatformPlugin.kt b/build-logic/src/main/kotlin/io/openfeedback/plugins/MultiplatformPlugin.kt new file mode 100644 index 0000000..f09562f --- /dev/null +++ b/build-logic/src/main/kotlin/io/openfeedback/plugins/MultiplatformPlugin.kt @@ -0,0 +1,22 @@ +package io.openfeedback.plugins + +import com.android.build.gradle.LibraryExtension +import io.openfeedback.extensions.configureKotlinAndroid +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure + +class MultiplatformPlugin : Plugin { + override fun apply(target: Project) { + with(target.pluginManager) { + apply("com.android.library") + apply("org.jetbrains.kotlin.multiplatform") + apply("org.jetbrains.kotlin.plugin.serialization") + } + + target.extensions.configure { + configureKotlinAndroid() + defaultConfig.targetSdk = 34 + } + } +} diff --git a/build-logic/src/main/kotlin/io/openfeedback/plugins/PublishingPlugin.kt b/build-logic/src/main/kotlin/io/openfeedback/plugins/PublishingPlugin.kt new file mode 100644 index 0000000..9df42be --- /dev/null +++ b/build-logic/src/main/kotlin/io/openfeedback/plugins/PublishingPlugin.kt @@ -0,0 +1,15 @@ +package io.openfeedback.plugins + +import io.openfeedback.OpenFeedback +import org.gradle.api.Plugin +import org.gradle.api.Project + +class PublishingPlugin : Plugin { + override fun apply(target: Project) { + with(target.pluginManager) { + apply("maven-publish") + apply("signing") + } + target.extensions.create("openfeedback", OpenFeedback::class.java, target) + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 5032350..cdaa3b3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,10 +2,11 @@ import io.openfeedback.extensions.configureRoot plugins { id("io.openfeedback.plugins.compose.lib") apply false + alias(libs.plugins.moko.resources.generator) apply false } version = "0.1.2" -subprojects { +allprojects { repositories { google() mavenCentral() diff --git a/libs.versions.toml b/libs.versions.toml index 5c4cb3b..838193d 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -1,12 +1,17 @@ [versions] kotlin_lang = "1.9.10" kotlin_coroutines = "1.7.3" +kotlinx_datetime = "0.4.1" kotlinx_serialization = "1.6.0" androidx_core = "1.12.0" androidx_compose_bom = "2023.10.01" androidx_compose_compiler = "1.5.3" androidx_lifecycle = "2.6.2" +firebase_common = "20.4.2" +firebase_firestore = "24.9.1" +firebase_auth = "22.3.0" gitlive_firebase = "1.10.4" +moko_resources = "0.23.0" [libraries] android-gradle-plugin = "com.android.tools.build:gradle:8.1.2" @@ -15,11 +20,14 @@ vespene = "net.mbonnin.vespene:vespene-lib:0.5" kotlin_gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin_lang" } kotlin_serialization-plugin = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin_lang" } kotlin-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin_coroutines" } -kotlin-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlin_coroutines" } -kotlin-coroutines-play-services = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services", version.ref = "kotlin_coroutines" } +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" } +firebase_common = { module = "com.google.firebase:firebase-common", version.ref = "firebase_common" } +firebase_firestore = { module = "com.google.firebase:firebase-firestore-ktx", version.ref = "firebase_firestore" } +firebase_auth = { module = "com.google.firebase:firebase-auth", version.ref = "firebase_auth" } +gitlive_app = { module = "dev.gitlive:firebase-app", version.ref = "gitlive_firebase" } gitlive_firestore = { module = "dev.gitlive:firebase-firestore", version.ref = "gitlive_firebase" } gitlive_auth = { module = "dev.gitlive:firebase-auth", version.ref = "gitlive_firebase" } gitlive_common = { module = "dev.gitlive:firebase-common", version.ref = "gitlive_firebase" } @@ -32,3 +40,8 @@ androidx_compose_ui = { module = "androidx.compose.ui:ui" } androidx_compose_runtime = { module = "androidx.compose.runtime:runtime" } androidx_compose_uitooling = { module = "androidx.compose.ui:ui-tooling" } androidx_lifecycle_viewmodel_compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx_lifecycle" } + +moko_resources = { module = "dev.icerock.moko:resources", version.ref = "moko_resources"} + +[plugins] +moko_resources_generator = { id = "dev.icerock.mobile.multiplatform-resources", version.ref = "moko_resources" } diff --git a/openfeedback-m2/build.gradle.kts b/openfeedback-m2/build.gradle.kts index cffe39d..821ed7d 100644 --- a/openfeedback-m2/build.gradle.kts +++ b/openfeedback-m2/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("io.openfeedback.plugins.compose.lib") + id("io.openfeedback.plugins.publishing") } android { diff --git a/openfeedback-m2/src/main/java/io/openfeedback/android/m2/PoweredBy.kt b/openfeedback-m2/src/main/java/io/openfeedback/android/m2/PoweredBy.kt index a8a4496..d44f7f3 100644 --- a/openfeedback-m2/src/main/java/io/openfeedback/android/m2/PoweredBy.kt +++ b/openfeedback-m2/src/main/java/io/openfeedback/android/m2/PoweredBy.kt @@ -19,7 +19,7 @@ import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import io.openfeedback.android.R as ROF +import io.openfeedback.R as ROF @Composable fun PoweredBy( diff --git a/openfeedback-m3/build.gradle.kts b/openfeedback-m3/build.gradle.kts index cfadbc2..833eb9d 100644 --- a/openfeedback-m3/build.gradle.kts +++ b/openfeedback-m3/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("io.openfeedback.plugins.compose.lib") + id("io.openfeedback.plugins.publishing") } android { @@ -14,6 +15,7 @@ openfeedback { dependencies { api(projects.openfeedback) api(projects.openfeedbackViewmodel) + implementation(libs.androidx.lifecycle.viewmodel.compose) implementation(platform(libs.androidx.compose.bom)) implementation(libs.androidx.compose.material3) diff --git a/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/Comment.kt b/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/Comment.kt index 1bb23a4..4d9939d 100644 --- a/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/Comment.kt +++ b/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/Comment.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import io.openfeedback.android.R +import io.openfeedback.R import io.openfeedback.android.viewmodels.models.UIComment import io.openfeedback.android.viewmodels.models.UIDot diff --git a/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/CommentInput.kt b/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/CommentInput.kt index 4bf6d47..788e10d 100644 --- a/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/CommentInput.kt +++ b/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/CommentInput.kt @@ -14,7 +14,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.tooling.preview.Preview -import io.openfeedback.android.R +import io.openfeedback.R @Composable fun CommentInput( diff --git a/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/CommentItems.kt b/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/CommentItems.kt index b7ce32e..9c464c9 100644 --- a/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/CommentItems.kt +++ b/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/CommentItems.kt @@ -10,9 +10,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import io.openfeedback.android.R import io.openfeedback.android.viewmodels.models.UIComment import io.openfeedback.android.viewmodels.models.UIDot +import io.openfeedback.R @Composable internal fun CommentItems( diff --git a/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/PoweredBy.kt b/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/PoweredBy.kt index c65f415..3b39b75 100644 --- a/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/PoweredBy.kt +++ b/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/PoweredBy.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp -import io.openfeedback.android.R as ROF +import io.openfeedback.R as ROF @Composable internal fun PoweredBy( diff --git a/openfeedback-viewmodel/build.gradle.kts b/openfeedback-viewmodel/build.gradle.kts index 9eacfde..07bd4c0 100644 --- a/openfeedback-viewmodel/build.gradle.kts +++ b/openfeedback-viewmodel/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("io.openfeedback.plugins.compose.lib") + id("io.openfeedback.plugins.publishing") } android { diff --git a/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/OpenFeedbackViewModel.kt b/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/OpenFeedbackViewModel.kt index 8d2a524..ae2ada6 100644 --- a/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/OpenFeedbackViewModel.kt +++ b/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/OpenFeedbackViewModel.kt @@ -4,11 +4,11 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import dev.gitlive.firebase.FirebaseApp -import io.openfeedback.android.OpenFeedbackRepository -import io.openfeedback.android.caches.OptimisticVoteCaching -import io.openfeedback.android.model.VoteStatus -import io.openfeedback.android.sources.OpenFeedbackAuth -import io.openfeedback.android.sources.OpenFeedbackFirestore +import io.openfeedback.OpenFeedbackRepository +import io.openfeedback.caches.OptimisticVoteCaching +import io.openfeedback.model.VoteStatus +import io.openfeedback.sources.OpenFeedbackAuth +import io.openfeedback.sources.OpenFeedbackFirestore import io.openfeedback.android.viewmodels.mappers.convertToUiSessionFeedback import io.openfeedback.android.viewmodels.models.UIComment import io.openfeedback.android.viewmodels.models.UISessionFeedback @@ -32,8 +32,8 @@ class OpenFeedbackViewModel( private val locale: Locale ) : ViewModel() { private val repository = OpenFeedbackRepository( - auth = OpenFeedbackAuth.Factory.create(firebaseApp), - firestore = OpenFeedbackFirestore.Factory.create(firebaseApp), + auth = OpenFeedbackAuth.create(firebaseApp), + firestore = OpenFeedbackFirestore.create(firebaseApp), optimisticVoteCaching = OptimisticVoteCaching() ) diff --git a/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/mappers/UiMappers.kt b/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/mappers/UiMappers.kt index 8252711..6f0cbee 100644 --- a/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/mappers/UiMappers.kt +++ b/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/mappers/UiMappers.kt @@ -1,14 +1,17 @@ package io.openfeedback.android.viewmodels.mappers -import io.openfeedback.android.model.Project -import io.openfeedback.android.model.SessionVotes -import io.openfeedback.android.model.UserVote import io.openfeedback.android.viewmodels.models.UIComment import io.openfeedback.android.viewmodels.models.UIDot import io.openfeedback.android.viewmodels.models.UISessionFeedback import io.openfeedback.android.viewmodels.models.UISessionFeedbackWithColors import io.openfeedback.android.viewmodels.models.UIVoteItem +import io.openfeedback.model.Project +import io.openfeedback.model.SessionVotes +import io.openfeedback.model.UserVote +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toLocalDateTime import java.text.SimpleDateFormat +import java.util.Date import java.util.Locale import kotlin.math.absoluteValue import kotlin.random.Random @@ -19,18 +22,26 @@ fun convertToUiSessionFeedback( totalVotes: SessionVotes, locale: Locale ): UISessionFeedback { - val formatter = SimpleDateFormat("dd MMMM yyyy, hh:mm", locale) + val formatter = SimpleDateFormat("dd MMM, hh:mm", locale) val userUpVoteIds = userVotes.filter { it.voteId != null }.map { it.voteId!! } val userVoteIds = userVotes.map { it.voteItemId } return UISessionFeedback( commentValue = "", commentVoteItemId = project.voteItems.find { it.type == "text" }?.id, comments = totalVotes.comments.map { commentItem -> + val localDateTime = commentItem.value.createdAt.toLocalDateTime(TimeZone.currentSystemDefault()) UIComment( id = commentItem.value.id, voteItemId = commentItem.value.voteItemId, message = commentItem.value.text, - createdAt = formatter.format(commentItem.value.createdAt.toDate()), + createdAt = formatter.format(Date( + localDateTime.date.year, + localDateTime.date.monthNumber, + localDateTime.date.dayOfMonth, + localDateTime.time.hour, + localDateTime.time.minute, + localDateTime.time.second + )), upVotes = commentItem.value.plus.toInt(), dots = dots(commentItem.value.plus.toInt(), project.chipColors), votedByUser = userUpVoteIds.contains(commentItem.value.id) diff --git a/openfeedback/build.gradle.kts b/openfeedback/build.gradle.kts index 1e55f34..ac89215 100644 --- a/openfeedback/build.gradle.kts +++ b/openfeedback/build.gradle.kts @@ -1,24 +1,48 @@ - plugins { - id("io.openfeedback.plugins.lib") + id("io.openfeedback.plugins.lib.multiplatform") + id("io.openfeedback.plugins.publishing") + alias(libs.plugins.moko.resources.generator) } android { - namespace = "io.openfeedback.android" + namespace = "io.openfeedback" + sourceSets { + getByName("main").java.srcDirs("build/generated/moko/androidMain/src") + } } openfeedback { - configurePublishing("feedback-android-sdk") + configurePublishing("feedback-sdk") } -dependencies { - api(libs.kotlinx.serialization.json) - api(libs.kotlin.coroutines.core) - api(libs.kotlin.coroutines.android) - api(libs.kotlin.coroutines.play.services) +kotlin { + androidTarget() + + sourceSets { + val commonMain by getting { + dependencies { + api(libs.kotlin.coroutines.core) + api(libs.kotlinx.datetime) + api(libs.kotlinx.serialization.json) + + api(libs.gitlive.app) + api(libs.gitlive.firestore) + implementation(libs.gitlive.auth) + implementation(libs.gitlive.common) + + api(libs.moko.resources) + } + } + val androidMain by getting { + dependencies { + api(libs.firebase.common) + api(libs.firebase.firestore) + implementation(libs.firebase.auth) + } + } + } +} - // KMM Firestore - api(libs.gitlive.firestore) - api(libs.gitlive.auth) - implementation(libs.gitlive.common) +multiplatformResources { + multiplatformResourcesPackage = "io.openfeedback" } diff --git a/openfeedback/src/androidMain/kotlin/io/openfeedback/mappers/FirestoreToModelMappers.kt b/openfeedback/src/androidMain/kotlin/io/openfeedback/mappers/FirestoreToModelMappers.kt new file mode 100644 index 0000000..b43d33b --- /dev/null +++ b/openfeedback/src/androidMain/kotlin/io/openfeedback/mappers/FirestoreToModelMappers.kt @@ -0,0 +1,21 @@ +package io.openfeedback.mappers + +import com.google.firebase.Timestamp +import io.openfeedback.model.Comment +import kotlinx.datetime.Instant + +actual fun Map.convertToModel( + id: String, + voteItemId: String +): Comment { + val createdAt = this["createdAt"] as Timestamp + val updatedAt = this["updatedAt"] as Timestamp + return Comment( + id = id, + voteItemId = voteItemId, + text = this["text"] as String, + plus = this["plus"] as Long, + createdAt = Instant.fromEpochSeconds(createdAt.seconds, createdAt.nanoseconds), + updatedAt = Instant.fromEpochSeconds(updatedAt.seconds, updatedAt.nanoseconds) + ) +} diff --git a/openfeedback/src/commonMain/kotlin/io/.DS_Store b/openfeedback/src/commonMain/kotlin/io/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c442ffc06ae1fa930b62b051c187ece9b0c0bccf GIT binary patch literal 6148 zcmeHK!AiqG5S?wSX{bUE3VI88Em(ts#Y>3w2aM=Jr6#6oXv~(TwTDv3U4O_Q@q3)v z-HN65;z6X$gxNPcJCkMKhMg<`2!9kG0Mr4Xib`0rvH3x0oOD4-#zQF7J075mPYe-+ z3(@TOj||Y>ZGeP6?pp@m_wOEh(Kzo%sf;k@J?f`PK5RBWM5$a^TemFRs#&+elN<-b za5&2SaBxk%3n|lRW{1&b(j9l|Tc!nS9l(3j6?-Y#N-w8yZU&_!11V zRA!GDGs~alF){s0^Gmf!#9leotWFas;afT*;CwvS6PwRK@}RBIj7J5&;iD>QzkprJ}J g#!@NXK~;i&hYUo|V4)E`DEuR!XyAq!_)`Wx0qTcOK>z>% literal 0 HcmV?d00001 diff --git a/openfeedback/src/main/java/io/openfeedback/android/OpenFeedbackRepository.kt b/openfeedback/src/commonMain/kotlin/io/openfeedback/OpenFeedbackRepository.kt similarity index 84% rename from openfeedback/src/main/java/io/openfeedback/android/OpenFeedbackRepository.kt rename to openfeedback/src/commonMain/kotlin/io/openfeedback/OpenFeedbackRepository.kt index cac83ce..0f3251b 100644 --- a/openfeedback/src/main/java/io/openfeedback/android/OpenFeedbackRepository.kt +++ b/openfeedback/src/commonMain/kotlin/io/openfeedback/OpenFeedbackRepository.kt @@ -1,12 +1,12 @@ -package io.openfeedback.android +package io.openfeedback -import io.openfeedback.android.caches.OptimisticVoteCaching -import io.openfeedback.android.model.Project -import io.openfeedback.android.model.SessionVotes -import io.openfeedback.android.model.UserVote -import io.openfeedback.android.model.VoteStatus -import io.openfeedback.android.sources.OpenFeedbackAuth -import io.openfeedback.android.sources.OpenFeedbackFirestore +import io.openfeedback.caches.OptimisticVoteCaching +import io.openfeedback.model.Project +import io.openfeedback.model.SessionVotes +import io.openfeedback.model.UserVote +import io.openfeedback.model.VoteStatus +import io.openfeedback.sources.OpenFeedbackAuth +import io.openfeedback.sources.OpenFeedbackFirestore import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.emptyFlow diff --git a/openfeedback/src/main/java/io/openfeedback/android/caches/OptimisticVoteCaching.kt b/openfeedback/src/commonMain/kotlin/io/openfeedback/caches/OptimisticVoteCaching.kt similarity index 90% rename from openfeedback/src/main/java/io/openfeedback/android/caches/OptimisticVoteCaching.kt rename to openfeedback/src/commonMain/kotlin/io/openfeedback/caches/OptimisticVoteCaching.kt index 8cf89f7..03953df 100644 --- a/openfeedback/src/main/java/io/openfeedback/android/caches/OptimisticVoteCaching.kt +++ b/openfeedback/src/commonMain/kotlin/io/openfeedback/caches/OptimisticVoteCaching.kt @@ -1,7 +1,7 @@ -package io.openfeedback.android.caches +package io.openfeedback.caches -import io.openfeedback.android.model.SessionVotes -import io.openfeedback.android.model.VoteStatus +import io.openfeedback.model.SessionVotes +import io.openfeedback.model.VoteStatus import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update diff --git a/openfeedback/src/commonMain/kotlin/io/openfeedback/mappers/FirestoreToModelMappers.kt b/openfeedback/src/commonMain/kotlin/io/openfeedback/mappers/FirestoreToModelMappers.kt new file mode 100644 index 0000000..327157c --- /dev/null +++ b/openfeedback/src/commonMain/kotlin/io/openfeedback/mappers/FirestoreToModelMappers.kt @@ -0,0 +1,5 @@ +package io.openfeedback.mappers + +import io.openfeedback.model.Comment + +expect fun Map.convertToModel(id: String, voteItemId: String): Comment diff --git a/openfeedback/src/main/java/io/openfeedback/android/model/Model.kt b/openfeedback/src/commonMain/kotlin/io/openfeedback/model/Model.kt similarity index 86% rename from openfeedback/src/main/java/io/openfeedback/android/model/Model.kt rename to openfeedback/src/commonMain/kotlin/io/openfeedback/model/Model.kt index d20e6b2..153cf96 100644 --- a/openfeedback/src/main/java/io/openfeedback/android/model/Model.kt +++ b/openfeedback/src/commonMain/kotlin/io/openfeedback/model/Model.kt @@ -1,6 +1,6 @@ -package io.openfeedback.android.model +package io.openfeedback.model -import com.google.firebase.Timestamp +import kotlinx.datetime.Instant import kotlinx.serialization.Serializable @Serializable @@ -42,6 +42,6 @@ data class Comment( val voteItemId: String = "", val text: String = "", val plus: Long = 0L, - val createdAt: Timestamp, - val updatedAt: Timestamp + val createdAt: Instant, + val updatedAt: Instant ) diff --git a/openfeedback/src/main/java/io/openfeedback/android/sources/OpenFeedbackAuth.kt b/openfeedback/src/commonMain/kotlin/io/openfeedback/sources/OpenFeedbackAuth.kt similarity index 96% rename from openfeedback/src/main/java/io/openfeedback/android/sources/OpenFeedbackAuth.kt rename to openfeedback/src/commonMain/kotlin/io/openfeedback/sources/OpenFeedbackAuth.kt index d5c3815..990c985 100644 --- a/openfeedback/src/main/java/io/openfeedback/android/sources/OpenFeedbackAuth.kt +++ b/openfeedback/src/commonMain/kotlin/io/openfeedback/sources/OpenFeedbackAuth.kt @@ -1,4 +1,4 @@ -package io.openfeedback.android.sources +package io.openfeedback.sources import android.util.Log import dev.gitlive.firebase.Firebase diff --git a/openfeedback/src/main/java/io/openfeedback/android/sources/OpenFeedbackFirestore.kt b/openfeedback/src/commonMain/kotlin/io/openfeedback/sources/OpenFeedbackFirestore.kt similarity index 96% rename from openfeedback/src/main/java/io/openfeedback/android/sources/OpenFeedbackFirestore.kt rename to openfeedback/src/commonMain/kotlin/io/openfeedback/sources/OpenFeedbackFirestore.kt index f258a91..ba1eb16 100644 --- a/openfeedback/src/main/java/io/openfeedback/android/sources/OpenFeedbackFirestore.kt +++ b/openfeedback/src/commonMain/kotlin/io/openfeedback/sources/OpenFeedbackFirestore.kt @@ -1,4 +1,4 @@ -package io.openfeedback.android.sources +package io.openfeedback.sources import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseApp @@ -7,11 +7,11 @@ import dev.gitlive.firebase.firestore.FieldValue import dev.gitlive.firebase.firestore.FirebaseFirestore import dev.gitlive.firebase.firestore.firestore import dev.gitlive.firebase.firestore.where -import io.openfeedback.android.mappers.convertToModel -import io.openfeedback.android.model.Project -import io.openfeedback.android.model.SessionVotes -import io.openfeedback.android.model.UserVote -import io.openfeedback.android.model.VoteStatus +import io.openfeedback.mappers.convertToModel +import io.openfeedback.model.Project +import io.openfeedback.model.SessionVotes +import io.openfeedback.model.UserVote +import io.openfeedback.model.VoteStatus import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map diff --git a/openfeedback/src/main/res/values/strings.xml b/openfeedback/src/commonMain/resources/MR/base/strings.xml similarity index 100% rename from openfeedback/src/main/res/values/strings.xml rename to openfeedback/src/commonMain/resources/MR/base/strings.xml diff --git a/openfeedback/src/main/res/values-fr/strings.xml b/openfeedback/src/commonMain/resources/MR/fr/strings.xml similarity index 100% rename from openfeedback/src/main/res/values-fr/strings.xml rename to openfeedback/src/commonMain/resources/MR/fr/strings.xml diff --git a/openfeedback/src/main/res/drawable/openfeedback_dark.png b/openfeedback/src/commonMain/resources/MR/images/openfeedback_dark@1x.png similarity index 100% rename from openfeedback/src/main/res/drawable/openfeedback_dark.png rename to openfeedback/src/commonMain/resources/MR/images/openfeedback_dark@1x.png diff --git a/openfeedback/src/main/res/drawable/openfeedback_light.png b/openfeedback/src/commonMain/resources/MR/images/openfeedback_light@1x.png similarity index 100% rename from openfeedback/src/main/res/drawable/openfeedback_light.png rename to openfeedback/src/commonMain/resources/MR/images/openfeedback_light@1x.png diff --git a/openfeedback/src/main/java/io/openfeedback/android/FirebaseExtensions.kt b/openfeedback/src/main/java/io/openfeedback/android/FirebaseExtensions.kt deleted file mode 100644 index 6fb1e14..0000000 --- a/openfeedback/src/main/java/io/openfeedback/android/FirebaseExtensions.kt +++ /dev/null @@ -1,45 +0,0 @@ -package io.openfeedback.android - -import com.google.firebase.firestore.DocumentReference -import com.google.firebase.firestore.DocumentSnapshot -import com.google.firebase.firestore.MetadataChanges -import com.google.firebase.firestore.Query -import com.google.firebase.firestore.QuerySnapshot -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.callbackFlow -import kotlinx.coroutines.flow.conflate - -internal fun Query.toFlow(): Flow = callbackFlow { - val registration = addSnapshotListener(MetadataChanges.INCLUDE) { snapshot, exception -> - if (snapshot != null) { - runCatching { - trySend(snapshot) - } - } - if (exception != null) { - close(exception) - } - } - - awaitClose { - registration.remove() - } -}.conflate() - -internal fun DocumentReference.toFlow(): Flow = callbackFlow { - val registration = addSnapshotListener(MetadataChanges.INCLUDE) { snapshot, exception -> - if (snapshot != null) { - runCatching { - trySend(snapshot) - } - } - if (exception != null) { - close(exception) - } - } - - awaitClose { - registration.remove() - } -}.conflate() diff --git a/openfeedback/src/main/java/io/openfeedback/android/mappers/FirestoreToModelMappers.kt b/openfeedback/src/main/java/io/openfeedback/android/mappers/FirestoreToModelMappers.kt deleted file mode 100644 index 58efac0..0000000 --- a/openfeedback/src/main/java/io/openfeedback/android/mappers/FirestoreToModelMappers.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.openfeedback.android.mappers - -import com.google.firebase.Timestamp -import io.openfeedback.android.model.Comment - -internal fun Map.convertToModel( - id: String, - voteItemId: String -): Comment = Comment( - id = id, - voteItemId = voteItemId, - text = this["text"] as String, - plus = this["plus"] as Long, - createdAt = this["createdAt"] as Timestamp, - updatedAt = this["updatedAt"] as Timestamp -) diff --git a/settings.gradle.kts b/settings.gradle.kts index a670f6a..f14734f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,6 +8,7 @@ dependencyResolutionManagement { pluginManagement { repositories { + gradlePluginPortal() google() mavenCentral() }