diff --git a/app/shared/forever-ui/build.gradle.kts b/app/shared/forever-ui/build.gradle.kts index 742e0b1c19..6e262c8d59 100644 --- a/app/shared/forever-ui/build.gradle.kts +++ b/app/shared/forever-ui/build.gradle.kts @@ -1,5 +1,6 @@ plugins { - id("hedvig.android.library") + id("hedvig.multiplatform.library") + id("hedvig.multiplatform.library.android") id("hedvig.gradle.plugin") } @@ -10,22 +11,40 @@ hedvig { viewModels() } -dependencies { - implementation(libs.androidx.other.core) - implementation(libs.apollo.normalizedCache) - implementation(libs.arrow.core) - implementation(libs.coroutines.core) - implementation(libs.jetbrains.lifecycle.runtime.compose) - implementation(projects.apolloCore) - implementation(projects.apolloOctopusPublic) - implementation(projects.composeUi) - implementation(projects.coreBuildConstants) - implementation(projects.coreCommonPublic) - implementation(projects.coreDemoMode) - implementation(projects.coreResources) - implementation(projects.coreUiData) - implementation(projects.designSystemHedvig) - implementation(projects.languageCore) - implementation(projects.moleculePublic) - implementation(projects.pullrefresh) +kotlin { + sourceSets { + commonMain.dependencies { + implementation(libs.apollo.api) + implementation(libs.apollo.normalizedCache) + implementation(libs.apollo.runtime) + implementation(libs.arrow.core) + implementation(libs.coroutines.core) + implementation(libs.jetbrains.compose.animation) + implementation(libs.jetbrains.compose.foundation) + implementation(libs.jetbrains.compose.runtime) + implementation(libs.jetbrains.compose.ui) + implementation(libs.jetbrains.compose.ui.tooling.preview) + implementation(libs.jetbrains.lifecycle.runtime.compose) + implementation(libs.uri.kmp) + implementation(projects.apolloCore) + implementation(projects.apolloOctopusPublic) + implementation(projects.composeUi) + implementation(projects.coreBuildConstants) + implementation(projects.coreCommonPublic) + implementation(projects.coreDemoMode) + implementation(projects.coreResources) + implementation(projects.coreUiData) + implementation(projects.designSystemHedvig) + implementation(projects.languageCore) + implementation(projects.moleculePublic) + implementation(projects.pullrefresh) + } + androidMain.dependencies { + implementation(libs.androidx.other.core) + } + jvmTest.dependencies { + implementation(libs.assertK) + implementation(libs.junit) + } + } } diff --git a/app/shared/forever-ui/src/main/AndroidManifest.xml b/app/shared/forever-ui/src/androidMain/AndroidManifest.xml similarity index 100% rename from app/shared/forever-ui/src/main/AndroidManifest.xml rename to app/shared/forever-ui/src/androidMain/AndroidManifest.xml diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ContextExt.kt b/app/shared/forever-ui/src/androidMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ContextExt.kt similarity index 100% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ContextExt.kt rename to app/shared/forever-ui/src/androidMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ContextExt.kt diff --git a/app/shared/forever-ui/src/androidMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralSharing.android.kt b/app/shared/forever-ui/src/androidMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralSharing.android.kt new file mode 100644 index 0000000000..f221846d95 --- /dev/null +++ b/app/shared/forever-ui/src/androidMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralSharing.android.kt @@ -0,0 +1,34 @@ +package com.hedvig.android.shared.foreverui.ui.ui + +import android.content.Intent +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.platform.LocalContext +import hedvig.resources.REFERRALS_SHARE_SHEET_TITLE +import hedvig.resources.Res +import org.jetbrains.compose.resources.stringResource + +@Composable +internal actual fun rememberShareHandler(): (text: String) -> Unit { + val context = LocalContext.current + val shareSheetTitle = stringResource(Res.string.REFERRALS_SHARE_SHEET_TITLE) + return remember(context, shareSheetTitle) { + { text -> + context.showShareSheet(shareSheetTitle) { intent -> + intent.putExtra( + Intent.EXTRA_TEXT, + text, + ) + intent.type = "text/plain" + } + } + } +} + +@Composable +internal actual fun rememberCopyToClipboard(): (text: String) -> Unit { + val context = LocalContext.current + return remember(context) { + { text -> context.copyToClipboard(text) } + } +} diff --git a/app/shared/forever-ui/src/main/graphql/MutationMemberReferralInformationCodeUpdate.graphql b/app/shared/forever-ui/src/commonMain/graphql/MutationMemberReferralInformationCodeUpdate.graphql similarity index 100% rename from app/shared/forever-ui/src/main/graphql/MutationMemberReferralInformationCodeUpdate.graphql rename to app/shared/forever-ui/src/commonMain/graphql/MutationMemberReferralInformationCodeUpdate.graphql diff --git a/app/shared/forever-ui/src/main/graphql/QueryFullReferrals.graphql b/app/shared/forever-ui/src/commonMain/graphql/QueryFullReferrals.graphql similarity index 100% rename from app/shared/forever-ui/src/main/graphql/QueryFullReferrals.graphql rename to app/shared/forever-ui/src/commonMain/graphql/QueryFullReferrals.graphql diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverData.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverData.kt similarity index 100% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverData.kt rename to app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverData.kt diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverRepository.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverRepository.kt similarity index 100% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverRepository.kt rename to app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverRepository.kt diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverRepositoryDemo.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverRepositoryDemo.kt similarity index 100% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverRepositoryDemo.kt rename to app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverRepositoryDemo.kt diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverRepositoryImpl.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverRepositoryImpl.kt similarity index 100% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverRepositoryImpl.kt rename to app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/data/ForeverRepositoryImpl.kt diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/data/SwitchingForeverRepository.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/data/SwitchingForeverRepository.kt similarity index 100% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/data/SwitchingForeverRepository.kt rename to app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/data/SwitchingForeverRepository.kt diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/DiscountPieChart.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/DiscountPieChart.kt similarity index 100% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/DiscountPieChart.kt rename to app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/DiscountPieChart.kt diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/DiscountText.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/DiscountText.kt similarity index 100% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/DiscountText.kt rename to app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/DiscountText.kt diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/EditCodeBottomSheet.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/EditCodeBottomSheet.kt similarity index 100% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/EditCodeBottomSheet.kt rename to app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/EditCodeBottomSheet.kt diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverDestination.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverDestination.kt similarity index 97% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverDestination.kt rename to app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverDestination.kt index 504c2fbe38..c3e95881d6 100644 --- a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverDestination.kt +++ b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverDestination.kt @@ -1,6 +1,5 @@ package com.hedvig.android.shared.foreverui.ui.ui -import android.content.Intent import androidx.compose.animation.AnimatedContent import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -35,7 +34,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.heading @@ -86,7 +84,6 @@ import com.hedvig.android.shared.foreverui.ui.ui.ForeverUiState.Success import hedvig.resources.FOREVER_TAB_MONTHLY_DISCOUNT import hedvig.resources.OFFER_COST_AND_PREMIUM_PERIOD_ABBREVIATION import hedvig.resources.REFERRALS_INFO_BUTTON_CONTENT_DESCRIPTION -import hedvig.resources.REFERRALS_SHARE_SHEET_TITLE import hedvig.resources.REFERRAL_SMS_MESSAGE import hedvig.resources.Res import hedvig.resources.TAB_REFERRALS_TITLE @@ -106,8 +103,7 @@ import org.jetbrains.compose.resources.stringResource @Composable fun ForeverDestination(viewModel: ForeverViewModel) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() - val context = LocalContext.current - val shareSheetTitle = stringResource(Res.string.REFERRALS_SHARE_SHEET_TITLE) + val shareText = rememberShareHandler() val coroutineScope = rememberCoroutineScope() val resourceEnvironment = rememberResourceEnvironment() ForeverScreen( @@ -126,13 +122,7 @@ fun ForeverDestination(viewModel: ForeverViewModel) { incentive.toString(), viewModel.referralShareUrl(code), ) - context.showShareSheet(shareSheetTitle) { intent -> - intent.putExtra( - Intent.EXTRA_TEXT, - string, - ) - intent.type = "text/plain" - } + shareText(string) } }, ) @@ -465,10 +455,10 @@ private fun ForeverScrollableContent( @Composable internal fun ReferralCodeCard(campaignCode: String, modifier: Modifier = Modifier) { - val context = LocalContext.current + val copyToClipboard = rememberCopyToClipboard() HedvigBigCard( onClick = { - context.copyToClipboard(campaignCode) + copyToClipboard(campaignCode) }, enabled = true, modifier = modifier.fillMaxWidth(), diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverExplanationBottomSheet.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverExplanationBottomSheet.kt similarity index 100% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverExplanationBottomSheet.kt rename to app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverExplanationBottomSheet.kt diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverViewModel.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverViewModel.kt similarity index 99% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverViewModel.kt rename to app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverViewModel.kt index 47c8813e24..186acc0d2c 100644 --- a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverViewModel.kt +++ b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ForeverViewModel.kt @@ -1,6 +1,5 @@ package com.hedvig.android.shared.foreverui.ui.ui -import android.net.Uri import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -9,6 +8,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import arrow.core.raise.either +import com.eygraber.uri.Uri import com.hedvig.android.core.buildconstants.HedvigBuildConstants import com.hedvig.android.core.common.di.ActivityRetainedScope import com.hedvig.android.core.common.di.HedvigViewModel diff --git a/app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralList.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralList.kt similarity index 100% rename from app/shared/forever-ui/src/main/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralList.kt rename to app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralList.kt diff --git a/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralSharing.kt b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralSharing.kt new file mode 100644 index 0000000000..cc213eeac1 --- /dev/null +++ b/app/shared/forever-ui/src/commonMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralSharing.kt @@ -0,0 +1,9 @@ +package com.hedvig.android.shared.foreverui.ui.ui + +import androidx.compose.runtime.Composable + +@Composable +internal expect fun rememberShareHandler(): (text: String) -> Unit + +@Composable +internal expect fun rememberCopyToClipboard(): (text: String) -> Unit diff --git a/app/shared/forever-ui/src/jvmMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralSharing.jvm.kt b/app/shared/forever-ui/src/jvmMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralSharing.jvm.kt new file mode 100644 index 0000000000..685cc09d23 --- /dev/null +++ b/app/shared/forever-ui/src/jvmMain/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralSharing.jvm.kt @@ -0,0 +1,18 @@ +package com.hedvig.android.shared.foreverui.ui.ui + +import androidx.compose.runtime.Composable +import java.awt.Toolkit +import java.awt.datatransfer.StringSelection + +/** + * There is no system share sheet on the JVM, so sharing puts the text on the system clipboard. + */ +@Composable +internal actual fun rememberShareHandler(): (text: String) -> Unit = ::copyToSystemClipboard + +@Composable +internal actual fun rememberCopyToClipboard(): (text: String) -> Unit = ::copyToSystemClipboard + +private fun copyToSystemClipboard(text: String) { + Toolkit.getDefaultToolkit().systemClipboard.setContents(StringSelection(text), null) +} diff --git a/app/shared/forever-ui/src/jvmTest/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralCodeUrlEncodingTest.kt b/app/shared/forever-ui/src/jvmTest/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralCodeUrlEncodingTest.kt new file mode 100644 index 0000000000..158f9a98a8 --- /dev/null +++ b/app/shared/forever-ui/src/jvmTest/kotlin/com/hedvig/android/shared/foreverui/ui/ui/ReferralCodeUrlEncodingTest.kt @@ -0,0 +1,43 @@ +package com.hedvig.android.shared.foreverui.ui.ui + +import assertk.assertThat +import assertk.assertions.isEqualTo +import com.eygraber.uri.Uri +import org.junit.Test + +/** + * [ForeverViewModel.referralShareUrl] percent-encodes the referral code with [Uri.encode]. The expected values are what + * `android.net.Uri.encode` produces: letters, digits and `_-!.~'()*` stay as they are, everything else becomes UTF-8 + * percent-encoded, and a space becomes `%20`. + */ +class ReferralCodeUrlEncodingTest { + @Test + fun `letters and digits are unchanged`() { + assertThat(Uri.encode("HEDV1G")).isEqualTo("HEDV1G") + assertThat(Uri.encode("abc123")).isEqualTo("abc123") + } + + @Test + fun `unreserved punctuation is unchanged`() { + assertThat(Uri.encode("_-!.~'()*")).isEqualTo("_-!.~'()*") + } + + @Test + fun `space becomes percent 20`() { + assertThat(Uri.encode("MY CODE")).isEqualTo("MY%20CODE") + } + + @Test + fun `reserved characters are percent-encoded`() { + assertThat(Uri.encode("A+B")).isEqualTo("A%2BB") + assertThat(Uri.encode("A/B")).isEqualTo("A%2FB") + assertThat(Uri.encode("A&B")).isEqualTo("A%26B") + assertThat(Uri.encode("A%B")).isEqualTo("A%25B") + } + + @Test + fun `non-ASCII characters are percent-encoded as UTF-8`() { + assertThat(Uri.encode("KÖD")).isEqualTo("K%C3%96D") + assertThat(Uri.encode("å")).isEqualTo("%C3%A5") + } +}