diff --git a/.github/workflows/umbrella.yml b/.github/workflows/umbrella.yml index 72ea7f3d2a..f05f1ff508 100644 --- a/.github/workflows/umbrella.yml +++ b/.github/workflows/umbrella.yml @@ -4,11 +4,7 @@ on: push: branches: - develop - - makerdays/chat-claim - paths: - - 'app/authlib/**' - - 'app/feature/feature-claim-chat/**' - - 'app/shareddi/**' + - feat/help-center-kmp workflow_dispatch: concurrency: diff --git a/app/apollo/apollo-octopus-public/src/commonMain/graphql/com/hedvig/android/apollo/octopus/schema.graphqls b/app/apollo/apollo-octopus-public/src/commonMain/graphql/com/hedvig/android/apollo/octopus/schema.graphqls index 288983627b..d649e15147 100644 --- a/app/apollo/apollo-octopus-public/src/commonMain/graphql/com/hedvig/android/apollo/octopus/schema.graphqls +++ b/app/apollo/apollo-octopus-public/src/commonMain/graphql/com/hedvig/android/apollo/octopus/schema.graphqls @@ -1728,6 +1728,11 @@ type ExternalInsurer { displayName: String! insurelyId: String } +type FetchedExternalInsurance { + displayName: String! + subtitle: String + insurer: ExternalInsurer! +} type FirstVetAction { sections: [FirstVetSection!]! } @@ -2729,6 +2734,22 @@ type MemberPaymentAvailablePaymentMethod { True if the member can set up this payment method for payout. """ supportsPayout: Boolean! + """ + True if this method is already ACTIVE for member and can be chosen as default directly without setup, false if + this is a new payment method that the member has not yet set up. + If this is true, then the `details` field will be populated with the payment method details. If this is false, then + the `details` field will be null since the member has not yet set up this payment method. + If true then this method can be set up as default directly by calling `paymentMethodSetDefaultPayin` or + `paymentMethodSetDefaultPayout` mutation depending on if it's a payin or payout method. If false, then the + corresponding mutation for setting up this payment method should be called, eg. `paymentMethodSetupTrustly`, + `paymentMethodSetupSwishPayin` etc. + """ + isActive: Boolean! + """ + For already connected and ACTIVE methods, ie isActive=true, specific details of the actual connection - e.g. a bank + account reference, phone number for swish, or email/kivra for invoice. + """ + details: PaymentMethodDetails } type MemberPaymentChargeMethodInfo { """ @@ -2801,48 +2822,75 @@ type MemberPaymentInformation { } type MemberPaymentMethod { """ - The unique id of the payment method. This id is used for switching default and revoking payment methods. - """ - id: ID! - """ - Payment provider, eg Trustly, Swish, Nordea, Kivra etc. + Payment provider, eg Trustly, Swish, Nordea, Kivra etc. + This is used as the "identifier" of the payment method since there can only be one ACTIVE or PENDING payment method + per provider. """ provider: MemberPaymentProvider! """ - The payment method status - ACTIVE, PENDING, or PENDING_DEFAULT. - PENDING_DEFAULT means the payment method is awaiting activation and will become default once activated. + The payment method status - ACTIVE, PENDING. + If ACTIVE, the payment method is ready to use for payins or payouts depending on if it's a payin or payout method. + If PENDING, the payment method has been set up but is still awaiting activation and cannot be used for payins or + payouts until then. Once activated, the status will change to ACTIVE. """ status: MemberPaymentMethodStatus! """ - True if this is the default payment method. Only one ACTIVE payment method can be default at a time. - If status is PENDING then payment method will become the default once activated. + This is 'true' for only one of the members ACTIVE methods which is the default payment method that will be used for + charging or payout the member. For PENDING methods, this can also be 'true' if the member has chosen to set up this + payment method as default during the setup process. """ isDefault: Boolean! """ - Specific details of the actual connection - e.g. a bank account reference, phone number for swish, + Specific details of the actual connection if method is ACTIVE - e.g. a bank account reference, phone number for swish, or email/kivra for invoice. """ details: PaymentMethodDetails! } type MemberPaymentMethods { """ - List of active and pending payment payin methods for this member. + List of all member's ACTIVE and PENDING payment payin methods. + A member can have multiple ACTIVE payment methods with these constraints: + - Only one ACTIVE payment method per provider, eg. one Trustly, one Swish, one Nordea etc. + - Only one ACTIVE payment method can be default at a time. + A member can have multiple PENDING payment methods with these constraints: + - Only one PENDING payment method per provider, eg. one Trustly, one Swish, one Nordea etc. + So there can exist max two payment methods per provider, one ACTIVE and one PENDING. + If a PENDING payment method has isDefault=true, then it will become the default ACTIVE payment method once activated. """ payinMethods: [MemberPaymentMethod!]! """ - List of active and pending payment payout methods for this member. + List of all member's ACTIVE and PENDING payment payout methods. + A member can have multiple ACTIVE payment methods with these constraints: + - Only one ACTIVE payment method per provider, eg. one Trustly, one Swish, one Nordea etc. + - Only one ACTIVE payment method can be default at a time. + A member can have multiple PENDING payment methods with these constraints: + - Only one PENDING payment method per provider, eg. one Trustly, one Swish, one Nordea etc. + So there can exist max two payment methods per provider, one ACTIVE and one PENDING. + If a PENDING payment method has isDefault=true, then it will become the default ACTIVE payment method once activated. """ payoutMethods: [MemberPaymentMethod!]! """ - The default payment method for payin if any. + The default payment method to use for payins if any. + Note that there can exist a PENDING payment method in `payinMethods` list with `isDefault`=true, in that case this default + payment method will be replaced by it once the pending method is activated. """ defaultPayinMethod: MemberPaymentMethod """ - The default payment method for payout if any. + The default payment method to use for payouts if any. + Note that there can exist a PENDING payment method in `payoutMethods` list with `isDefault`=true, in that case this default + payment method will be replaced by it once the pending method is activated. """ defaultPayoutMethod: MemberPaymentMethod """ - The available payment methods that the member can choose from when setting up a new payment method. + The available payment methods that the member can choose from when setting up a new payment method. + This list can include both payment methods that the member has already set up and new payment methods that the + member has not yet set up but are available to them. For already set up payment methods, the `isActive` field will + be true and the `details` field will be populated with the payment method details. For new payment methods that the + member has not yet set up, the `isActive` field will be false and the `details` field will be null. + If member picks a new payment method to set up, the corresponding mutation for setting up that payment method should + be called, eg. `paymentMethodSetupTrustly`, `paymentMethodSetupSwishPayin` etc. + If member picks an already set up payment method to set up as default, then `paymentMethodSetDefaultPayin` or + `paymentMethodSetDefaultPayout` mutation should be called depending on if it's a payin or payout method. """ availableMethods: [MemberPaymentAvailablePaymentMethod!]! """ @@ -3392,9 +3440,9 @@ type Mutation { """ Setup invoice payment method for the member. Kivra will be used as the provider if supported, else mail. """ - paymentMethodSetupInvoicePayin(input: PaymentMethodSetupInvoicePayinInput!): PaymentMethodSetupOutput! + paymentMethodSetupInvoicePayin: PaymentMethodSetupOutput! """ - Setup Trustly payment payin and payout method for the member. + Setup Trustly payment payin and payout method for the member. Requires member consent via redirect to Trustly URL in response. """ paymentMethodSetupTrustly(input: PaymentMethodSetupTrustlyInput!): PaymentMethodSetupOutput! """ @@ -3406,17 +3454,19 @@ type Mutation { """ paymentMethodSetupSwishPayout(input: PaymentMethodSetupSwishInput!): PaymentMethodSetupOutput! """ - Setup Swish payin method for the member. + Setup Swish payin method for the member. Requires member consent in Swish app. """ paymentMethodSetupSwishPayin(input: PaymentMethodSetupSwishInput!): PaymentMethodSetupOutput! """ - Revoke an active payment method. The member will be required to set up a new payment method if they revoke their default one. + A member can have multiple ACTIVE payment methods where one of those is default. This mutation changes the + members default payment method for charging to any of his/hers other active payment methods. """ - paymentMethodRevoke(id: ID!): UserError + paymentMethodSetDefaultPayin(provider: MemberPaymentProvider!): UserError """ - Set an active payment method as default. + A member can have multiple ACTIVE payment methods where one of those is default. This mutation changes the + members default payment method for payouts to any of his/hers other active payment methods. """ - paymentMethodSetDefault(id: ID!): UserError + paymentMethodSetDefaultPayout(provider: MemberPaymentProvider!): UserError """ Start a conversation. This is effectively creating one, but with two slight differences from a regular "create something"-mutation: @@ -3707,17 +3757,7 @@ type PaymentMethodInvoiceDetails { """ email: String } -input PaymentMethodSetupInvoicePayinInput { - """ - Set up invoice payment method as default. - """ - setAsDefaultPayout: Boolean! -} input PaymentMethodSetupNordeaPayoutInput { - """ - Set up Nordea payout method as default. - """ - setAsDefault: Boolean! """ The clearing number for member's bank account. """ @@ -3756,24 +3796,12 @@ enum PaymentMethodSetupStatus { FAILED } input PaymentMethodSetupSwishInput { - """ - Set up Swish payment method as default. - """ - setAsDefault: Boolean! """ The Swish mobile number to use for payout or payin. """ phoneNumber: String! } input PaymentMethodSetupTrustlyInput { - """ - Set up Trustly payment method as default for payin. - """ - setAsDefaultPayin: Boolean! - """ - Set up Trustly payment method as default for payout. - """ - setAsDefaultPayout: Boolean! """ The URL to redirect the member back to after a successful setup after Trustly onboarding. """ @@ -3905,6 +3933,11 @@ type PriceIntent { When 'true' it means user has gone trough Insurely flow with that price intent """ hasCollectedInsurelyData: Boolean! + """ + List of external insurances fetched via Insurely that correspond to products Hedvig offers. + Null when no Insurely data collection has been associated with this price intent. + """ + fetchedExternalInsurances: [FetchedExternalInsurance!] } enum PriceIntentAnimal { CAT diff --git a/app/app/build.gradle.kts b/app/app/build.gradle.kts index f5f26cf90a..f50b1fb3d2 100644 --- a/app/app/build.gradle.kts +++ b/app/app/build.gradle.kts @@ -195,8 +195,7 @@ dependencies { implementation(projects.featureCrossSellSheet) implementation(projects.featureDeleteAccount) implementation(projects.featureEditCoinsured) - implementation(projects.featureFlagsAndroid) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) implementation(projects.featureForever) implementation(projects.featureHelpCenter) implementation(projects.featureHome) diff --git a/app/app/src/main/kotlin/com/hedvig/android/app/di/ApplicationModule.kt b/app/app/src/main/kotlin/com/hedvig/android/app/di/ApplicationModule.kt index b4d78717c5..3180531fb1 100644 --- a/app/app/src/main/kotlin/com/hedvig/android/app/di/ApplicationModule.kt +++ b/app/app/src/main/kotlin/com/hedvig/android/app/di/ApplicationModule.kt @@ -358,7 +358,7 @@ val applicationModule = module { ) } -private class AndroidBuildConfig() : AppBuildConfig { +private class AndroidBuildConfig : AppBuildConfig { override val debug: Boolean = BuildConfig.DEBUG override val applicationId: String = BuildConfig.APPLICATION_ID override val buildType: String = BuildConfig.BUILD_TYPE diff --git a/app/app/src/main/kotlin/com/hedvig/android/app/navigation/HedvigNavHost.kt b/app/app/src/main/kotlin/com/hedvig/android/app/navigation/HedvigNavHost.kt index 43fdab75f4..19f76be8a1 100644 --- a/app/app/src/main/kotlin/com/hedvig/android/app/navigation/HedvigNavHost.kt +++ b/app/app/src/main/kotlin/com/hedvig/android/app/navigation/HedvigNavHost.kt @@ -440,6 +440,7 @@ internal fun HedvigNavHost( helpCenterGraph( hedvigDeepLinkContainer = hedvigDeepLinkContainer, navController = navController, + onNavigateUp = navController::navigateUp, onNavigateToQuickLink = onNavigateToQuickLink@{ quickLinkDestination -> val destination: Destination = when (quickLinkDestination) { QuickLinkChangeAddress -> { diff --git a/app/core/core-datastore-public/build.gradle.kts b/app/core/core-datastore-public/build.gradle.kts index 2d541e69f2..151e4539c0 100644 --- a/app/core/core-datastore-public/build.gradle.kts +++ b/app/core/core-datastore-public/build.gradle.kts @@ -2,6 +2,7 @@ plugins { id("hedvig.multiplatform.library") id("hedvig.multiplatform.library.android") id("hedvig.gradle.plugin") + alias(libs.plugins.kmpNativeCoroutines) } kotlin { diff --git a/app/core/core-resources/build.gradle.kts b/app/core/core-resources/build.gradle.kts index 89668fcfeb..23f57b1ae5 100644 --- a/app/core/core-resources/build.gradle.kts +++ b/app/core/core-resources/build.gradle.kts @@ -33,7 +33,6 @@ lokalise { kotlin { androidLibrary { namespace = "hedvig.resources" - @Suppress("UnstableApiUsage") androidResources.enable = true } sourceSets { diff --git a/app/core/core-resources/src/commonMain/composeResources/drawable/pillow_hedvig.png b/app/core/core-resources/src/commonMain/composeResources/drawable/pillow_hedvig.png new file mode 100644 index 0000000000..7e9a452ab9 Binary files /dev/null and b/app/core/core-resources/src/commonMain/composeResources/drawable/pillow_hedvig.png differ diff --git a/app/data/data-addons/build.gradle.kts b/app/data/data-addons/build.gradle.kts index e2180dcc20..8b0ec31e99 100644 --- a/app/data/data-addons/build.gradle.kts +++ b/app/data/data-addons/build.gradle.kts @@ -22,7 +22,7 @@ dependencies { implementation(projects.apolloOctopusPublic) implementation(projects.coreCommonPublic) implementation(projects.coreDemoMode) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) testImplementation(libs.apollo.testingSupport) testImplementation(libs.assertK) diff --git a/app/data/data-changetier/build.gradle.kts b/app/data/data-changetier/build.gradle.kts index 0ee48dd9db..2b365576ab 100644 --- a/app/data/data-changetier/build.gradle.kts +++ b/app/data/data-changetier/build.gradle.kts @@ -25,7 +25,7 @@ dependencies { implementation(projects.dataContract) implementation(projects.dataCrossSellAfterFlow) implementation(projects.dataProductVariantPublic) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) implementation(projects.uiTiersAndAddons) testImplementation(libs.apollo.testingSupport) diff --git a/app/data/data-conversations/build.gradle.kts b/app/data/data-conversations/build.gradle.kts index f24062dd2f..71ad02e8ed 100644 --- a/app/data/data-conversations/build.gradle.kts +++ b/app/data/data-conversations/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("hedvig.jvm.library") + id("hedvig.multiplatform.library") id("hedvig.gradle.plugin") } @@ -7,10 +7,15 @@ hedvig { apollo("octopus") } -dependencies { - implementation(libs.apollo.normalizedCache) - implementation(libs.arrow.core) - implementation(libs.koin.core) - implementation(projects.apolloCore) - implementation(projects.apolloOctopusPublic) +kotlin { + sourceSets { + commonMain.dependencies { + implementation(libs.apollo.normalizedCache) + implementation(libs.arrow.core) + implementation(libs.koin.core) + implementation(projects.apolloCore) + implementation(projects.apolloOctopusPublic) + implementation(projects.loggingPublic) + } + } } diff --git a/app/data/data-conversations/src/main/graphql/QueryCbmNumberOfChatMessages.graphql b/app/data/data-conversations/src/commonMain/graphql/QueryCbmNumberOfChatMessages.graphql similarity index 100% rename from app/data/data-conversations/src/main/graphql/QueryCbmNumberOfChatMessages.graphql rename to app/data/data-conversations/src/commonMain/graphql/QueryCbmNumberOfChatMessages.graphql diff --git a/app/data/data-conversations/src/main/kotlin/com/hedvig/android/data/conversations/HasAnyActiveConversationUseCase.kt b/app/data/data-conversations/src/commonMain/kotlin/com/hedvig/android/data/conversations/HasAnyActiveConversationUseCase.kt similarity index 100% rename from app/data/data-conversations/src/main/kotlin/com/hedvig/android/data/conversations/HasAnyActiveConversationUseCase.kt rename to app/data/data-conversations/src/commonMain/kotlin/com/hedvig/android/data/conversations/HasAnyActiveConversationUseCase.kt diff --git a/app/data/data-conversations/src/main/kotlin/com/hedvig/android/data/conversations/di/DataConversationsModule.kt b/app/data/data-conversations/src/commonMain/kotlin/com/hedvig/android/data/conversations/di/DataConversationsModule.kt similarity index 100% rename from app/data/data-conversations/src/main/kotlin/com/hedvig/android/data/conversations/di/DataConversationsModule.kt rename to app/data/data-conversations/src/commonMain/kotlin/com/hedvig/android/data/conversations/di/DataConversationsModule.kt diff --git a/app/data/data-termination/build.gradle.kts b/app/data/data-termination/build.gradle.kts index e7d7fe9875..8059e0acef 100644 --- a/app/data/data-termination/build.gradle.kts +++ b/app/data/data-termination/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("hedvig.jvm.library") + id("hedvig.multiplatform.library") id("hedvig.gradle.plugin") } @@ -7,16 +7,20 @@ hedvig { apollo("octopus") } -dependencies { - implementation(libs.apollo.normalizedCache) - implementation(libs.apollo.runtime) - implementation(libs.arrow.core) - implementation(libs.koin.core) - implementation(libs.kotlinx.datetime) - implementation(projects.apolloCore) - implementation(projects.apolloOctopusPublic) - implementation(projects.coreCommonPublic) - implementation(projects.coreUiData) - implementation(projects.dataContract) - implementation(projects.featureFlagsPublic) +kotlin { + sourceSets { + commonMain.dependencies { + implementation(libs.apollo.normalizedCache) + implementation(libs.apollo.runtime) + implementation(libs.arrow.core) + implementation(libs.koin.core) + implementation(libs.kotlinx.datetime) + implementation(projects.apolloCore) + implementation(projects.apolloOctopusPublic) + implementation(projects.coreCommonPublic) + implementation(projects.coreUiData) + implementation(projects.dataContract) + implementation(projects.featureFlags) + } + } } diff --git a/app/data/data-termination/src/main/graphql/QueryContractsToTerminate.graphql b/app/data/data-termination/src/commonMain/graphql/QueryContractsToTerminate.graphql similarity index 100% rename from app/data/data-termination/src/main/graphql/QueryContractsToTerminate.graphql rename to app/data/data-termination/src/commonMain/graphql/QueryContractsToTerminate.graphql diff --git a/app/data/data-termination/src/main/kotlin/com/hedvig/android/data/termination/data/GetTerminatableContractsUseCase.kt b/app/data/data-termination/src/commonMain/kotlin/com/hedvig/android/data/termination/data/GetTerminatableContractsUseCase.kt similarity index 100% rename from app/data/data-termination/src/main/kotlin/com/hedvig/android/data/termination/data/GetTerminatableContractsUseCase.kt rename to app/data/data-termination/src/commonMain/kotlin/com/hedvig/android/data/termination/data/GetTerminatableContractsUseCase.kt diff --git a/app/data/data-termination/src/main/kotlin/com/hedvig/android/data/termination/di/TerminationDataModule.kt b/app/data/data-termination/src/commonMain/kotlin/com/hedvig/android/data/termination/di/TerminationDataModule.kt similarity index 100% rename from app/data/data-termination/src/main/kotlin/com/hedvig/android/data/termination/di/TerminationDataModule.kt rename to app/data/data-termination/src/commonMain/kotlin/com/hedvig/android/data/termination/di/TerminationDataModule.kt diff --git a/app/datadog/datadog-core/build.gradle.kts b/app/datadog/datadog-core/build.gradle.kts index 95dccf96b9..881a12e9e9 100644 --- a/app/datadog/datadog-core/build.gradle.kts +++ b/app/datadog/datadog-core/build.gradle.kts @@ -1,8 +1,12 @@ plugins { - id("hedvig.jvm.library") + id("hedvig.multiplatform.library") id("hedvig.gradle.plugin") } -dependencies { - implementation(libs.coroutines.core) +kotlin { + sourceSets { + commonMain.dependencies { + implementation(libs.coroutines.core) + } + } } diff --git a/app/datadog/datadog-core/src/main/kotlin/com/hedvig/android/datadog/core/attributestracking/DatadogAttributeProvider.kt b/app/datadog/datadog-core/src/commonMain/kotlin/com/hedvig/android/datadog/core/attributestracking/DatadogAttributeProvider.kt similarity index 100% rename from app/datadog/datadog-core/src/main/kotlin/com/hedvig/android/datadog/core/attributestracking/DatadogAttributeProvider.kt rename to app/datadog/datadog-core/src/commonMain/kotlin/com/hedvig/android/datadog/core/attributestracking/DatadogAttributeProvider.kt diff --git a/app/datadog/datadog-core/src/main/kotlin/com/hedvig/android/datadog/core/attributestracking/DatadogMemberIdProvider.kt b/app/datadog/datadog-core/src/commonMain/kotlin/com/hedvig/android/datadog/core/attributestracking/DatadogMemberIdProvider.kt similarity index 100% rename from app/datadog/datadog-core/src/main/kotlin/com/hedvig/android/datadog/core/attributestracking/DatadogMemberIdProvider.kt rename to app/datadog/datadog-core/src/commonMain/kotlin/com/hedvig/android/datadog/core/attributestracking/DatadogMemberIdProvider.kt diff --git a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/InteractiveComponentSize.kt b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/InteractiveComponentSize.kt index d15b8e7ef4..9577ebd853 100644 --- a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/InteractiveComponentSize.kt +++ b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/InteractiveComponentSize.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.isSpecified +import com.hedvig.android.design.system.hedvig.internal.identityHashCode import kotlin.math.roundToInt /** @@ -36,7 +37,7 @@ internal object MinimumInteractiveModifier : ModifierNodeElement Unit, onNavigateToQuickLink: (QuickLinkDestination.OuterDestination) -> Unit, onNavigateToInbox: () -> Unit, onNavigateToNewConversation: () -> Unit, @@ -80,7 +81,7 @@ fun NavGraphBuilder.helpCenterGraph( onNavigateToNewConversation = dropUnlessResumed { onNavigateToNewConversation() }, - onNavigateUp = navController::navigateUp, + onNavigateUp = onNavigateUp, ) } @@ -126,6 +127,7 @@ fun NavGraphBuilder.helpCenterGraph( sections = sections, navigateUp = navController::navigateUp, navigateBack = navController::popBackStack, + openUrl = openUrl, ) } navdestination(HelpCenterDestinations.Emergency) { diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/HelpCenterPresenter.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/HelpCenterPresenter.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/HelpCenterPresenter.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/HelpCenterPresenter.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/HelpCenterViewModel.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/HelpCenterViewModel.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/HelpCenterViewModel.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/HelpCenterViewModel.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/ShowNavigateToInboxViewModel.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/ShowNavigateToInboxViewModel.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/ShowNavigateToInboxViewModel.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/ShowNavigateToInboxViewModel.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/commonclaim/FirstVetDestination.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/commonclaim/FirstVetDestination.kt similarity index 81% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/commonclaim/FirstVetDestination.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/commonclaim/FirstVetDestination.kt index 9243d7033f..aed093100b 100644 --- a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/commonclaim/FirstVetDestination.kt +++ b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/commonclaim/FirstVetDestination.kt @@ -8,8 +8,13 @@ import com.hedvig.android.ui.emergency.FirstVetScreen import com.hedvig.android.ui.emergency.FirstVetSection @Composable -internal fun FirstVetDestination(sections: List, navigateUp: () -> Unit, navigateBack: () -> Unit) { - FirstVetScreen(sections, navigateUp, navigateBack) +internal fun FirstVetDestination( + sections: List, + navigateUp: () -> Unit, + navigateBack: () -> Unit, + openUrl: (String) -> Unit, +) { + FirstVetScreen(sections, navigateUp, navigateBack, openUrl) } @HedvigPreview @@ -34,6 +39,7 @@ private fun PreviewCommonClaimDestination() { ), {}, {}, + {}, ) } } diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/commonclaim/emergency/EmergencyDestination.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/commonclaim/emergency/EmergencyDestination.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/commonclaim/emergency/EmergencyDestination.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/commonclaim/emergency/EmergencyDestination.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetHelpCenterFAQUseCase.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetHelpCenterFAQUseCase.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetHelpCenterFAQUseCase.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetHelpCenterFAQUseCase.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetHelpCenterQuestionUseCase.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetHelpCenterQuestionUseCase.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetHelpCenterQuestionUseCase.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetHelpCenterQuestionUseCase.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetHelpCenterTopicUseCase.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetHelpCenterTopicUseCase.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetHelpCenterTopicUseCase.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetHelpCenterTopicUseCase.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetInsuranceForEditCoInsuredUseCase.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetInsuranceForEditCoInsuredUseCase.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetInsuranceForEditCoInsuredUseCase.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetInsuranceForEditCoInsuredUseCase.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetMemberActionsUseCase.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetMemberActionsUseCase.kt similarity index 71% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetMemberActionsUseCase.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetMemberActionsUseCase.kt index 7bc67ec078..a2a757b3f0 100644 --- a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetMemberActionsUseCase.kt +++ b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetMemberActionsUseCase.kt @@ -15,10 +15,6 @@ import com.hedvig.android.ui.emergency.FirstVetSection import kotlinx.coroutines.flow.first import octopus.MemberActionsQuery -internal interface GetMemberActionsUseCase { - suspend fun invoke(): Either -} - internal class GetMemberActionsUseCaseImpl( private val apolloClient: ApolloClient, private val featureManager: FeatureManager, @@ -59,36 +55,6 @@ internal class GetMemberActionsUseCaseImpl( } } -internal data class MemberAction( - val isCancelInsuranceEnabled: Boolean, - val isConnectPaymentEnabled: Boolean, - val isEditCoInsuredEnabled: Boolean, - val isEditCoOwnersEnabled: Boolean, - val isMovingEnabled: Boolean, - val isTravelCertificateEnabled: Boolean, - val isTierChangeEnabled: Boolean, - val sickAbroadAction: MemberActionWithDetails.SickAbroadAction?, - val firstVetAction: MemberActionWithDetails.FirstVetAction?, -) - -internal sealed interface MemberActionWithDetails { - data class SickAbroadAction( - val deflectData: DeflectData, - ) : MemberActionWithDetails - - data class FirstVetAction( - val sections: List, - ) : MemberActionWithDetails -} - -internal data class DeflectPartner( - val id: String, - val imageUrl: String?, - val phoneNumber: String?, - val url: String?, - val preferredImageHeight: Int?, -) - private fun MemberActionsQuery.Data.CurrentMember.MemberActions.FirstVetAction.toVetAction(): MemberActionWithDetails.FirstVetAction { val sections = this.sections.map { @@ -104,9 +70,9 @@ private fun MemberActionsQuery.Data.CurrentMember.MemberActions.FirstVetAction.t ) } -private fun MemberActionsQuery.Data.CurrentMember.MemberActions.SickAbroadDeflect?.toSickAbroadAction(): +private fun MemberActionsQuery.Data.CurrentMember.MemberActions.SickAbroadDeflect?.toSickAbroadAction(): MemberActionWithDetails.SickAbroadAction? { - if (this==null) return null + if (this == null) return null val partners = if (partners.isNotEmpty()) { DeflectData.DeflectPartnerContainer.ExtendedPartnerContainer( partners = partners.map { partner -> @@ -137,20 +103,20 @@ private fun MemberActionsQuery.Data.CurrentMember.MemberActions.SickAbroadDefle } val deflectData = DeflectData( - title = title, - infoText = infoText, - warningText = warningText, - partnersContainer = partners, - partnersInfo = partnersInfo?.let { - DeflectData.InfoBlock(it.title,it.description) - }, - content = content.let { - DeflectData.InfoBlock(it.title,it.description) - }, - faq = faq.map { faqItem -> - DeflectData.InfoBlock(faqItem.title,faqItem.description) - }, - buttonText = buttonTitle, - ) + title = title, + infoText = infoText, + warningText = warningText, + partnersContainer = partners, + partnersInfo = partnersInfo?.let { + DeflectData.InfoBlock(it.title, it.description) + }, + content = content.let { + DeflectData.InfoBlock(it.title, it.description) + }, + faq = faq.map { faqItem -> + DeflectData.InfoBlock(faqItem.title, faqItem.description) + }, + buttonText = buttonTitle, + ) return MemberActionWithDetails.SickAbroadAction(deflectData) } diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetQuickLinksUseCase.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetQuickLinksUseCase.kt similarity index 97% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetQuickLinksUseCase.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetQuickLinksUseCase.kt index 88b57633ba..b7c404828f 100644 --- a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/data/GetQuickLinksUseCase.kt +++ b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/GetQuickLinksUseCase.kt @@ -42,12 +42,16 @@ import hedvig.resources.Res import kotlinx.coroutines.flow.first import octopus.AvailableSelfServiceOnContractsQuery -internal class GetQuickLinksUseCase( +internal interface GetQuickLinksUseCase { + suspend fun invoke(): Either> +} + +internal class GetQuickLinksUseCaseImpl( private val apolloClient: ApolloClient, private val featureManager: FeatureManager, private val getMemberActionsUseCase: GetMemberActionsUseCase, -) { - suspend fun invoke(): Either> = either { +) : GetQuickLinksUseCase { + override suspend fun invoke(): Either> = either { val memberActionOptions = getMemberActionsUseCase.invoke().bind() buildList { @@ -142,7 +146,7 @@ internal class GetQuickLinksUseCase( ), ) } - if (memberActionOptions.sickAbroadAction!=null) { + if (memberActionOptions.sickAbroadAction != null) { val deflectData = memberActionOptions.sickAbroadAction.deflectData add( StandaloneQuickLink( diff --git a/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/MemberAction.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/MemberAction.kt new file mode 100644 index 0000000000..93bdf69269 --- /dev/null +++ b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/data/MemberAction.kt @@ -0,0 +1,40 @@ +package com.hedvig.android.feature.help.center.data + +import arrow.core.Either +import com.hedvig.android.core.common.ErrorMessage +import com.hedvig.android.shared.partners.deflect.DeflectData +import com.hedvig.android.ui.emergency.FirstVetSection + +internal interface GetMemberActionsUseCase { + suspend fun invoke(): Either +} + +internal data class MemberAction( + val isCancelInsuranceEnabled: Boolean, + val isConnectPaymentEnabled: Boolean, + val isEditCoInsuredEnabled: Boolean, + val isEditCoOwnersEnabled: Boolean, + val isMovingEnabled: Boolean, + val isTravelCertificateEnabled: Boolean, + val isTierChangeEnabled: Boolean, + val sickAbroadAction: MemberActionWithDetails.SickAbroadAction?, + val firstVetAction: MemberActionWithDetails.FirstVetAction?, +) + +internal sealed interface MemberActionWithDetails { + data class SickAbroadAction( + val deflectData: DeflectData, + ) : MemberActionWithDetails + + data class FirstVetAction( + val sections: List, + ) : MemberActionWithDetails +} + +internal data class DeflectPartner( + val id: String, + val imageUrl: String?, + val phoneNumber: String?, + val url: String?, + val preferredImageHeight: Int?, +) diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/di/HelpCenterModule.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/di/HelpCenterModule.kt similarity index 96% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/di/HelpCenterModule.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/di/HelpCenterModule.kt index 053df4eaa4..40c6d0d9e8 100644 --- a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/di/HelpCenterModule.kt +++ b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/di/HelpCenterModule.kt @@ -15,6 +15,7 @@ import com.hedvig.android.feature.help.center.data.GetInsuranceForEditCoInsuredU import com.hedvig.android.feature.help.center.data.GetMemberActionsUseCase import com.hedvig.android.feature.help.center.data.GetMemberActionsUseCaseImpl import com.hedvig.android.feature.help.center.data.GetQuickLinksUseCase +import com.hedvig.android.feature.help.center.data.GetQuickLinksUseCaseImpl import com.hedvig.android.feature.help.center.question.HelpCenterQuestionViewModel import com.hedvig.android.feature.help.center.topic.HelpCenterTopicViewModel import com.hedvig.android.featureflags.FeatureManager @@ -32,7 +33,7 @@ val helpCenterModule = module { } single { - GetQuickLinksUseCase( + GetQuickLinksUseCaseImpl( apolloClient = get(), featureManager = get(), getMemberActionsUseCase = get(), diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/home/HelpCenterHomeDestination.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/home/HelpCenterHomeDestination.kt similarity index 96% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/home/HelpCenterHomeDestination.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/home/HelpCenterHomeDestination.kt index 5c76ddcce0..65b46ef951 100644 --- a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/home/HelpCenterHomeDestination.kt +++ b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/home/HelpCenterHomeDestination.kt @@ -1,6 +1,5 @@ package com.hedvig.android.feature.help.center.home -import androidx.activity.compose.BackHandler import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.Spring @@ -23,13 +22,16 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.captionBar import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.BasicTextField @@ -50,9 +52,7 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.SolidColor -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview @@ -62,6 +62,9 @@ import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigationevent.NavigationEventInfo +import androidx.navigationevent.compose.NavigationEventHandler +import androidx.navigationevent.compose.rememberNavigationEventState import arrow.core.toNonEmptyListOrNull import com.hedvig.android.compose.ui.plus import com.hedvig.android.compose.ui.preview.PreviewContentWithProvidedParametersAnimatedOnClick @@ -121,10 +124,13 @@ import hedvig.resources.HC_TITLE import hedvig.resources.Res import hedvig.resources.SEARCH_NOTHING_FOUND import hedvig.resources.SEARCH_PLACEHOLDER +import hedvig.resources.blur_background import hedvig.resources.general_cancel_button import hedvig.resources.general_continue_button +import hedvig.resources.pillow_hedvig import kotlinx.coroutines.launch import org.jetbrains.compose.resources.getString +import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource @Composable @@ -289,9 +295,9 @@ private fun HelpCenterHomeScreen( focusRequester = focusRequester, modifier = Modifier .padding(horizontal = 16.dp) - .windowInsetsPadding( - WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal), - ), + .windowInsetsPadding(WindowInsets.statusBars.only(WindowInsetsSides.Horizontal)) + .windowInsetsPadding(WindowInsets.captionBar.only(WindowInsetsSides.Horizontal)) + .windowInsetsPadding(WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal)), onSearchChange = { if (it.isEmpty()) { searchQuery = null @@ -383,7 +389,7 @@ private fun ContentWithoutSearch( ) { Spacer(Modifier.height(32.dp)) Image( - painter = painterResource(hedvig.resources.R.drawable.pillow_hedvig), + painter = painterResource(Res.drawable.pillow_hedvig), contentDescription = null, modifier = Modifier .size(170.dp) @@ -437,7 +443,6 @@ private fun ContentWithoutSearch( Spacer(Modifier.height(32.dp)) } } - LocalConfiguration.current AnimatedVisibility( !questions.isEmpty(), ) { @@ -471,7 +476,7 @@ private fun SearchResults( onNavigateToQuestion: (questionId: String) -> Unit, onQuickActionsSelected: (QuickAction) -> Unit, ) { - BackHandler(true) { + NavigationEventHandler(state = rememberNavigationEventState(NavigationEventInfo.None), isBackEnabled = true) { onBackPressed() } diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/model/QuickLink.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/model/QuickAction.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/model/QuickLink.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/model/QuickAction.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/navigation/HelpCenterDestination.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/navigation/HelpCenterDestination.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/navigation/HelpCenterDestination.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/navigation/HelpCenterDestination.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/question/HelpCenterQuestionDestination.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/question/HelpCenterQuestionDestination.kt similarity index 95% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/question/HelpCenterQuestionDestination.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/question/HelpCenterQuestionDestination.kt index a24ce56fc9..512d58ee6a 100644 --- a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/question/HelpCenterQuestionDestination.kt +++ b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/question/HelpCenterQuestionDestination.kt @@ -17,13 +17,11 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.dropUnlessResumed -import com.halilibo.richtext.commonmark.Markdown import com.hedvig.android.compose.ui.plus import com.hedvig.android.design.system.hedvig.HedvigErrorSection import com.hedvig.android.design.system.hedvig.HedvigFullScreenCenterAlignedProgress @@ -33,7 +31,6 @@ import com.hedvig.android.design.system.hedvig.HedvigTheme import com.hedvig.android.design.system.hedvig.HighlightLabelDefaults.HighlightColor import com.hedvig.android.design.system.hedvig.HighlightLabelDefaults.HighlightShade.LIGHT import com.hedvig.android.design.system.hedvig.ProvideTextStyle -import com.hedvig.android.design.system.hedvig.RichText import com.hedvig.android.design.system.hedvig.Surface import com.hedvig.android.design.system.hedvig.TopAppBarWithBack import com.hedvig.android.feature.help.center.ShowNavigateToInboxViewModel @@ -44,6 +41,7 @@ import com.hedvig.android.feature.help.center.question.HelpCenterQuestionUiState import com.hedvig.android.feature.help.center.question.HelpCenterQuestionUiState.NoQuestionFound import com.hedvig.android.feature.help.center.question.HelpCenterQuestionUiState.Success import com.hedvig.android.feature.help.center.ui.HelpCenterSection +import com.hedvig.android.feature.help.center.ui.MarkdownText import com.hedvig.android.feature.help.center.ui.StillNeedHelpSection import hedvig.resources.GENERAL_ERROR_BODY import hedvig.resources.GENERAL_RETRY @@ -93,7 +91,7 @@ private fun HelpCenterQuestionScreen( title = stringResource(Res.string.HC_TITLE), onClick = onNavigateUp, ) - when (val state = uiState) { + when (uiState) { Failure -> { FailureScreen( onClick = onReload, @@ -116,7 +114,7 @@ private fun HelpCenterQuestionScreen( is Success -> { HelpCenterQuestionScreen( - faqItem = state.faqItem, + faqItem = uiState.faqItem, showNavigateToInboxButton = showNavigateToInboxButton, onNavigateToInbox = onNavigateToInbox, onNavigateToNewConversation = onNavigateToNewConversation, @@ -153,7 +151,6 @@ private fun HelpCenterQuestionScreen( onNavigateToInbox: () -> Unit, onNavigateToNewConversation: () -> Unit, ) { - LocalConfiguration.current Column( Modifier .fillMaxSize() @@ -185,11 +182,9 @@ private fun HelpCenterQuestionScreen( ProvideTextStyle( HedvigTheme.typography.bodySmall.copy(color = HedvigTheme.colorScheme.textSecondary), ) { - RichText { - Markdown( - content = faqItem.answer, - ) - } + MarkdownText( + markdown = faqItem.answer, + ) } }, ) diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/question/HelpCenterQuestionViewModel.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/question/HelpCenterQuestionViewModel.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/question/HelpCenterQuestionViewModel.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/question/HelpCenterQuestionViewModel.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/topic/HelpCenterTopicDestination.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/topic/HelpCenterTopicDestination.kt similarity index 99% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/topic/HelpCenterTopicDestination.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/topic/HelpCenterTopicDestination.kt index 82a1bc8f79..dfa18f810f 100644 --- a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/topic/HelpCenterTopicDestination.kt +++ b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/topic/HelpCenterTopicDestination.kt @@ -17,7 +17,6 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider import androidx.compose.ui.unit.dp @@ -180,7 +179,6 @@ private fun HelpCenterTopicScreen( ), ) } else { - LocalConfiguration.current Column( modifier = Modifier .fillMaxSize() diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/topic/HelpCenterTopicViewModel.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/topic/HelpCenterTopicViewModel.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/topic/HelpCenterTopicViewModel.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/topic/HelpCenterTopicViewModel.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/ui/HelpCenterSection.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/ui/HelpCenterSection.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/ui/HelpCenterSection.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/ui/HelpCenterSection.kt diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/ui/HelpCenterSectionWithClickableRows.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/ui/HelpCenterSectionWithClickableRows.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/ui/HelpCenterSectionWithClickableRows.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/ui/HelpCenterSectionWithClickableRows.kt diff --git a/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/ui/MarkdownText.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/ui/MarkdownText.kt new file mode 100644 index 0000000000..1a07ad8192 --- /dev/null +++ b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/ui/MarkdownText.kt @@ -0,0 +1,12 @@ +package com.hedvig.android.feature.help.center.ui + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +/** + * Renders Markdown content. + * On Android: Uses RichText library for full Markdown rendering + * On iOS/other platforms: Falls back to plain text + */ +@Composable +expect fun MarkdownText(markdown: String, modifier: Modifier = Modifier) diff --git a/app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/ui/StillNeedHelpSection.kt b/app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/ui/StillNeedHelpSection.kt similarity index 100% rename from app/feature/feature-help-center/src/main/kotlin/com/hedvig/android/feature/help/center/ui/StillNeedHelpSection.kt rename to app/feature/feature-help-center/src/commonMain/kotlin/com/hedvig/android/feature/help/center/ui/StillNeedHelpSection.kt diff --git a/app/feature/feature-help-center/src/jvmMain/kotlin/com/hedvig/android/feature/help/center/ui/MarkdownText.jvm.kt b/app/feature/feature-help-center/src/jvmMain/kotlin/com/hedvig/android/feature/help/center/ui/MarkdownText.jvm.kt new file mode 100644 index 0000000000..399edd5c35 --- /dev/null +++ b/app/feature/feature-help-center/src/jvmMain/kotlin/com/hedvig/android/feature/help/center/ui/MarkdownText.jvm.kt @@ -0,0 +1,13 @@ +package com.hedvig.android.feature.help.center.ui + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.halilibo.richtext.commonmark.Markdown +import com.hedvig.android.design.system.hedvig.RichText + +@Composable +actual fun MarkdownText(markdown: String, modifier: Modifier) { + RichText(modifier = modifier) { + Markdown(content = markdown) + } +} diff --git a/app/feature/feature-help-center/src/main/AndroidManifest.xml b/app/feature/feature-help-center/src/main/AndroidManifest.xml deleted file mode 100644 index 568741e54f..0000000000 --- a/app/feature/feature-help-center/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/app/feature/feature-help-center/src/nativeMain/kotlin/com/hedvig/android/feature/help/center/ui/HelpCenterViewController.kt b/app/feature/feature-help-center/src/nativeMain/kotlin/com/hedvig/android/feature/help/center/ui/HelpCenterViewController.kt new file mode 100644 index 0000000000..9d30ae4b20 --- /dev/null +++ b/app/feature/feature-help-center/src/nativeMain/kotlin/com/hedvig/android/feature/help/center/ui/HelpCenterViewController.kt @@ -0,0 +1,89 @@ +package com.hedvig.android.feature.help.center.ui + +import androidx.compose.ui.window.ComposeUIViewController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.rememberNavController +import coil3.ImageLoader +import com.hedvig.android.design.system.hedvig.HedvigTheme +import com.hedvig.android.feature.help.center.data.QuickLinkDestination +import com.hedvig.android.feature.help.center.helpCenterGraph +import com.hedvig.android.feature.help.center.navigation.HelpCenterDestination +import com.hedvig.android.navigation.core.HedvigDeepLinkContainer +import org.koin.compose.koinInject +import platform.UIKit.UIViewController + +@Suppress("unused", "FunctionName") // Used from iOS +fun HelpCenterViewController( + onNavigateUp: () -> Unit, + onNavigateToInbox: () -> Unit, + onNavigateToNewConversation: () -> Unit, + onNavigateToQuickLink: (QuickLinkDestination.OuterDestination) -> Unit, + openUrl: (String) -> Unit, + tryToDialPhone: (String) -> Unit, +): UIViewController { + return ComposeUIViewController { + HedvigTheme { + val navController = rememberNavController() + val imageLoader = koinInject() + NavHost( + navController = navController, + startDestination = HelpCenterDestination, + ) { + helpCenterGraph( + hedvigDeepLinkContainer = NoOpHedvigDeepLinkContainer, + navController = navController, + onNavigateUp = onNavigateUp, + onNavigateToQuickLink = onNavigateToQuickLink, + onNavigateToInbox = onNavigateToInbox, + onNavigateToNewConversation = onNavigateToNewConversation, + openUrl = openUrl, + tryToDialPhone = tryToDialPhone, + imageLoader = imageLoader + ) + } + } + } +} + +private object NoOpHedvigDeepLinkContainer : HedvigDeepLinkContainer { + override val home: List = emptyList() + override val helpCenter: List = emptyList() + override val helpCenterCommonTopic: List = emptyList() + override val helpCenterQuestion: List = emptyList() + override val insurances: List = emptyList() + override val claimFlow: List = emptyList() + override val contractWithoutContractId: List = emptyList() + override val contract: List = emptyList() + override val editCoInsuredWithoutContractId: List = emptyList() + override val editCoInsured: List = emptyList() + override val editCoOwners: List = emptyList() + override val terminateInsurance: List = emptyList() + override val forever: List = emptyList() + override val profile: List = emptyList() + override val connectPayment: List = emptyList() + override val directDebit: List = emptyList() + override val eurobonus: List = emptyList() + override val payments: List = emptyList() + override val deleteAccount: List = emptyList() + override val contactInfo: List = emptyList() + override val chat: List = emptyList() + override val inbox: List = emptyList() + override val conversation: List = emptyList() + override val travelAddon: List = emptyList() + override val travelAddonWithContractId: List = emptyList() + override val carAddon: List = emptyList() + override val carAddonWithContractId: List = emptyList() + override val travelCertificate: List = emptyList() + override val changeTierWithoutContractId: List = emptyList() + override val changeTierWithContractId: List = emptyList() + override val claimDetails: List = emptyList() + override val insuranceEvidence: List = emptyList() + override val moveContract: List = emptyList() + + override fun buildDeepLink(suffix: String): String { + return "" + } + + override val petIdWithoutContractId: List = emptyList() + override val petIdWithContractId: List = emptyList() +} diff --git a/app/feature/feature-help-center/src/nativeMain/kotlin/com/hedvig/android/feature/help/center/ui/MarkdownText.native.kt b/app/feature/feature-help-center/src/nativeMain/kotlin/com/hedvig/android/feature/help/center/ui/MarkdownText.native.kt new file mode 100644 index 0000000000..bf3f8be687 --- /dev/null +++ b/app/feature/feature-help-center/src/nativeMain/kotlin/com/hedvig/android/feature/help/center/ui/MarkdownText.native.kt @@ -0,0 +1,15 @@ +package com.hedvig.android.feature.help.center.ui + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.hedvig.android.design.system.hedvig.HedvigText + +@Composable +actual fun MarkdownText(markdown: String, modifier: Modifier) { + // Fallback to plain text for native platforms + // TODO ios: Find a KMP markdown library in the future + HedvigText( + text = markdown, + modifier = modifier, + ) +} diff --git a/app/feature/feature-help-center/src/test/kotlin/GetQuickLinksUseCaseTest.kt b/app/feature/feature-help-center/src/test/kotlin/GetQuickLinksUseCaseTest.kt index 2d19f1bf7b..526307cd33 100644 --- a/app/feature/feature-help-center/src/test/kotlin/GetQuickLinksUseCaseTest.kt +++ b/app/feature/feature-help-center/src/test/kotlin/GetQuickLinksUseCaseTest.kt @@ -11,7 +11,7 @@ import com.hedvig.android.apollo.test.TestNetworkTransportType import com.hedvig.android.core.common.ErrorMessage import com.hedvig.android.core.common.test.isRight import com.hedvig.android.feature.help.center.data.GetMemberActionsUseCase -import com.hedvig.android.feature.help.center.data.GetQuickLinksUseCase +import com.hedvig.android.feature.help.center.data.GetQuickLinksUseCaseImpl import com.hedvig.android.feature.help.center.data.MemberAction import com.hedvig.android.feature.help.center.data.QuickLinkDestination import com.hedvig.android.feature.help.center.model.QuickAction @@ -67,7 +67,7 @@ class GetQuickLinksUseCaseTest { val featureManager = FakeFeatureManager(fixedReturnForAll = true) val getMemberActionsUseCase = FakeGetMemberActionsUseCase() getMemberActionsUseCase.turbine.add(fakeMemberActionWithTier.right()) - val useCase = GetQuickLinksUseCase( + val useCase = GetQuickLinksUseCaseImpl( apolloClient = apolloClientWithGoodResponse, featureManager = featureManager, getMemberActionsUseCase = getMemberActionsUseCase, @@ -98,7 +98,7 @@ class GetQuickLinksUseCaseTest { val featureManager = FakeFeatureManager(fixedReturnForAll = true) val getMemberActionsUseCase = FakeGetMemberActionsUseCase() getMemberActionsUseCase.turbine.add(fakeMemberActionWithoutTier.right()) - val useCase = GetQuickLinksUseCase( + val useCase = GetQuickLinksUseCaseImpl( apolloClient = apolloClientWithGoodResponse, featureManager = featureManager, getMemberActionsUseCase = getMemberActionsUseCase, diff --git a/app/feature/feature-home/build.gradle.kts b/app/feature/feature-home/build.gradle.kts index 5554784f82..671e4f1567 100644 --- a/app/feature/feature-home/build.gradle.kts +++ b/app/feature/feature-home/build.gradle.kts @@ -45,7 +45,7 @@ dependencies { implementation(projects.dataConversations) implementation(projects.dataCrossSellAfterClaimClosed) implementation(projects.designSystemHedvig) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) implementation(projects.languageCore) implementation(projects.memberRemindersPublic) implementation(projects.memberRemindersUi) diff --git a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/navigation/HomeGraph.kt b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/navigation/HomeGraph.kt index 072b01417f..9f1a07d0da 100644 --- a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/navigation/HomeGraph.kt +++ b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/navigation/HomeGraph.kt @@ -76,6 +76,7 @@ fun NavGraphBuilder.homeGraph( sections, navigateUp = navController::navigateUp, navigateBack = navController::popBackStack, + openUrl = openUrl, ) } nestedGraphs() diff --git a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/FirstVetDestination.kt b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/FirstVetDestination.kt index 0ff43878cb..9480c830af 100644 --- a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/FirstVetDestination.kt +++ b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/FirstVetDestination.kt @@ -5,10 +5,16 @@ import com.hedvig.android.ui.emergency.FirstVetScreen import com.hedvig.android.ui.emergency.FirstVetSection @Composable -internal fun FirstVetDestination(sections: List, navigateUp: () -> Unit, navigateBack: () -> Unit) { +internal fun FirstVetDestination( + sections: List, + navigateUp: () -> Unit, + navigateBack: () -> Unit, + openUrl: (String) -> Unit, +) { FirstVetScreen( sections = sections, navigateUp = navigateUp, navigateBack = navigateBack, + openUrl = openUrl, ) } diff --git a/app/feature/feature-insurances/build.gradle.kts b/app/feature/feature-insurances/build.gradle.kts index 9e71111b52..b95f551ca5 100644 --- a/app/feature/feature-insurances/build.gradle.kts +++ b/app/feature/feature-insurances/build.gradle.kts @@ -38,7 +38,7 @@ dependencies { implementation(projects.dataDisplayItems) implementation(projects.dataProductVariantPublic) implementation(projects.designSystemHedvig) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) implementation(projects.languageCore) implementation(projects.moleculePublic) implementation(projects.navigationCommon) diff --git a/app/feature/feature-movingflow/build.gradle.kts b/app/feature/feature-movingflow/build.gradle.kts index 8d58185e6b..6e69ae001b 100644 --- a/app/feature/feature-movingflow/build.gradle.kts +++ b/app/feature/feature-movingflow/build.gradle.kts @@ -35,7 +35,7 @@ dependencies { implementation(projects.dataCrossSellAfterFlow) implementation(projects.dataProductVariantPublic) implementation(projects.designSystemHedvig) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) implementation(projects.moleculePublic) implementation(projects.navigationCommon) implementation(projects.navigationCompose) diff --git a/app/feature/feature-payments/build.gradle.kts b/app/feature/feature-payments/build.gradle.kts index 763237417d..0456d048cb 100644 --- a/app/feature/feature-payments/build.gradle.kts +++ b/app/feature/feature-payments/build.gradle.kts @@ -40,7 +40,7 @@ dependencies { implementation(projects.dataPayingMember) implementation(projects.dataSettingsDatastorePublic) implementation(projects.designSystemHedvig) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) implementation(projects.foreverUi) implementation(projects.languageCore) implementation(projects.languageData) diff --git a/app/feature/feature-profile/build.gradle.kts b/app/feature/feature-profile/build.gradle.kts index 5cc2b3e281..9f13300879 100644 --- a/app/feature/feature-profile/build.gradle.kts +++ b/app/feature/feature-profile/build.gradle.kts @@ -41,7 +41,7 @@ dependencies { implementation(projects.coreUiData) implementation(projects.dataSettingsDatastorePublic) implementation(projects.designSystemHedvig) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) implementation(projects.languageCore) implementation(projects.languageData) implementation(projects.memberRemindersPublic) diff --git a/app/feature/feature-terminate-insurance/build.gradle.kts b/app/feature/feature-terminate-insurance/build.gradle.kts index 5290ae86ca..27eae28e29 100644 --- a/app/feature/feature-terminate-insurance/build.gradle.kts +++ b/app/feature/feature-terminate-insurance/build.gradle.kts @@ -38,6 +38,7 @@ dependencies { implementation(projects.dataContract) implementation(projects.dataTermination) implementation(projects.designSystemHedvig) + implementation(projects.featureFlags) implementation(projects.languageCore) implementation(projects.moleculePublic) implementation(projects.navigationCommon) diff --git a/app/feature/feature-travel-certificate/build.gradle.kts b/app/feature/feature-travel-certificate/build.gradle.kts index 24cc51e199..baa03ba70b 100644 --- a/app/feature/feature-travel-certificate/build.gradle.kts +++ b/app/feature/feature-travel-certificate/build.gradle.kts @@ -30,7 +30,7 @@ dependencies { implementation(projects.dataAddons) implementation(projects.dataContract) implementation(projects.designSystemHedvig) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) implementation(projects.languageCore) implementation(projects.moleculePublic) implementation(projects.navigationActivity) diff --git a/app/featureflags/feature-flags-android/build.gradle.kts b/app/featureflags/feature-flags-android/build.gradle.kts deleted file mode 100644 index 9e4f325fa1..0000000000 --- a/app/featureflags/feature-flags-android/build.gradle.kts +++ /dev/null @@ -1,16 +0,0 @@ -plugins { - id("hedvig.android.library") - id("hedvig.gradle.plugin") -} - -dependencies { - api(libs.unleash) - - implementation(libs.coroutines.core) - implementation(libs.koin.core) - implementation(projects.authCorePublic) - implementation(projects.authEventCore) - implementation(projects.coreBuildConstants) - implementation(projects.coreCommonPublic) - implementation(projects.featureFlagsPublic) -} diff --git a/app/featureflags/feature-flags-public/build.gradle.kts b/app/featureflags/feature-flags-public/build.gradle.kts deleted file mode 100644 index a1bc0a3d59..0000000000 --- a/app/featureflags/feature-flags-public/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -plugins { - id("hedvig.jvm.library") - id("hedvig.gradle.plugin") -} - -dependencies { - implementation(libs.coroutines.core) - implementation(libs.koin.core) - implementation(projects.authCorePublic) - implementation(projects.authEventCore) - implementation(projects.coreBuildConstants) - implementation(projects.coreCommonPublic) -} diff --git a/app/featureflags/feature-flags-test/build.gradle.kts b/app/featureflags/feature-flags-test/build.gradle.kts index 5f2a6527a9..65adb4ad55 100644 --- a/app/featureflags/feature-flags-test/build.gradle.kts +++ b/app/featureflags/feature-flags-test/build.gradle.kts @@ -5,5 +5,5 @@ plugins { dependencies { implementation(libs.turbine) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) } diff --git a/app/featureflags/feature-flags/build.gradle.kts b/app/featureflags/feature-flags/build.gradle.kts new file mode 100644 index 0000000000..d8716f00a4 --- /dev/null +++ b/app/featureflags/feature-flags/build.gradle.kts @@ -0,0 +1,26 @@ +plugins { + id("hedvig.multiplatform.library") + id("hedvig.multiplatform.library.android") + id("hedvig.gradle.plugin") + alias(libs.plugins.kmpNativeCoroutines) +} + +hedvig { + serialization() +} + +kotlin { + sourceSets { + commonMain.dependencies { + implementation(libs.coroutines.core) + implementation(libs.koin.core) + } + androidMain.dependencies { + implementation(libs.unleash) + implementation(projects.authCorePublic) + implementation(projects.authEventCore) + implementation(projects.coreBuildConstants) + implementation(projects.coreCommonPublic) + } + } +} diff --git a/app/featureflags/feature-flags-android/src/main/kotlin/com/hedvig/android/featureflags/HedvigUnleashClient.kt b/app/featureflags/feature-flags/src/androidMain/kotlin/com/hedvig/android/featureflags/HedvigUnleashClient.kt similarity index 100% rename from app/featureflags/feature-flags-android/src/main/kotlin/com/hedvig/android/featureflags/HedvigUnleashClient.kt rename to app/featureflags/feature-flags/src/androidMain/kotlin/com/hedvig/android/featureflags/HedvigUnleashClient.kt diff --git a/app/featureflags/feature-flags-android/src/main/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt b/app/featureflags/feature-flags/src/androidMain/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt similarity index 95% rename from app/featureflags/feature-flags-android/src/main/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt rename to app/featureflags/feature-flags/src/androidMain/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt index 0f7a46181b..fca7781f02 100644 --- a/app/featureflags/feature-flags-android/src/main/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt +++ b/app/featureflags/feature-flags/src/androidMain/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt @@ -9,7 +9,7 @@ import com.hedvig.android.featureflags.HedvigUnleashClient import com.hedvig.android.featureflags.flags.UnleashFeatureFlagProvider import org.koin.dsl.module -val featureManagerModule = module { +actual val featureManagerModule = module { single { HedvigUnleashClient( androidContext = get().applicationContext, diff --git a/app/featureflags/feature-flags-android/src/main/kotlin/com/hedvig/android/featureflags/flags/UnleashFeatureFlagProvider.kt b/app/featureflags/feature-flags/src/androidMain/kotlin/com/hedvig/android/featureflags/flags/UnleashFeatureFlagProvider.kt similarity index 100% rename from app/featureflags/feature-flags-android/src/main/kotlin/com/hedvig/android/featureflags/flags/UnleashFeatureFlagProvider.kt rename to app/featureflags/feature-flags/src/androidMain/kotlin/com/hedvig/android/featureflags/flags/UnleashFeatureFlagProvider.kt diff --git a/app/featureflags/feature-flags-public/src/main/kotlin/com/hedvig/android/featureflags/FeatureManager.kt b/app/featureflags/feature-flags/src/commonMain/kotlin/com/hedvig/android/featureflags/FeatureManager.kt similarity index 72% rename from app/featureflags/feature-flags-public/src/main/kotlin/com/hedvig/android/featureflags/FeatureManager.kt rename to app/featureflags/feature-flags/src/commonMain/kotlin/com/hedvig/android/featureflags/FeatureManager.kt index 8e1041bd72..c475b01ce4 100644 --- a/app/featureflags/feature-flags-public/src/main/kotlin/com/hedvig/android/featureflags/FeatureManager.kt +++ b/app/featureflags/feature-flags/src/commonMain/kotlin/com/hedvig/android/featureflags/FeatureManager.kt @@ -1,8 +1,10 @@ package com.hedvig.android.featureflags import com.hedvig.android.featureflags.flags.Feature +import com.rickclephas.kmp.nativecoroutines.NativeCoroutines import kotlinx.coroutines.flow.Flow interface FeatureManager { + @NativeCoroutines fun isFeatureEnabled(feature: Feature): Flow } diff --git a/app/featureflags/feature-flags/src/commonMain/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt b/app/featureflags/feature-flags/src/commonMain/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt new file mode 100644 index 0000000000..34de889fe4 --- /dev/null +++ b/app/featureflags/feature-flags/src/commonMain/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt @@ -0,0 +1,5 @@ +package com.hedvig.android.featureflags.di + +import org.koin.core.module.Module + +expect val featureManagerModule: Module diff --git a/app/featureflags/feature-flags-public/src/main/kotlin/com/hedvig/android/featureflags/flags/Feature.kt b/app/featureflags/feature-flags/src/commonMain/kotlin/com/hedvig/android/featureflags/flags/Feature.kt similarity index 100% rename from app/featureflags/feature-flags-public/src/main/kotlin/com/hedvig/android/featureflags/flags/Feature.kt rename to app/featureflags/feature-flags/src/commonMain/kotlin/com/hedvig/android/featureflags/flags/Feature.kt diff --git a/app/featureflags/feature-flags/src/iosMain/kotlin/com/hedvig/android/featureflags/di/IosFeatureManager.kt b/app/featureflags/feature-flags/src/iosMain/kotlin/com/hedvig/android/featureflags/di/IosFeatureManager.kt new file mode 100644 index 0000000000..1e83c24fb2 --- /dev/null +++ b/app/featureflags/feature-flags/src/iosMain/kotlin/com/hedvig/android/featureflags/di/IosFeatureManager.kt @@ -0,0 +1,14 @@ +package com.hedvig.android.featureflags.di + +import com.hedvig.android.featureflags.FeatureManager +import com.hedvig.android.featureflags.flags.Feature +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.withContext + +class IosFeatureManager(private val isFeatureEnabledBlock: (Feature) -> Boolean) : FeatureManager { + override fun isFeatureEnabled(feature: Feature): Flow = flow { + emit(withContext(Dispatchers.Main.immediate) { isFeatureEnabledBlock(feature) }) + } +} diff --git a/app/featureflags/feature-flags/src/iosMain/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt b/app/featureflags/feature-flags/src/iosMain/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt new file mode 100644 index 0000000000..612bbc65a9 --- /dev/null +++ b/app/featureflags/feature-flags/src/iosMain/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt @@ -0,0 +1,5 @@ +package com.hedvig.android.featureflags.di + +import org.koin.dsl.module + +actual val featureManagerModule = module {} diff --git a/app/featureflags/feature-flags/src/jvmMain/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt b/app/featureflags/feature-flags/src/jvmMain/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt new file mode 100644 index 0000000000..d075054446 --- /dev/null +++ b/app/featureflags/feature-flags/src/jvmMain/kotlin/com/hedvig/android/featureflags/di/featureManagerModule.kt @@ -0,0 +1,11 @@ +package com.hedvig.android.featureflags.di + +import com.hedvig.android.featureflags.FeatureManager +import com.hedvig.android.featureflags.flags.NoopFeatureFlagProvider +import org.koin.dsl.module + +actual val featureManagerModule = module { + single { + NoopFeatureFlagProvider() + } +} diff --git a/app/featureflags/feature-flags/src/jvmMain/kotlin/com/hedvig/android/featureflags/flags/NoopFeatureFlagProvider.kt b/app/featureflags/feature-flags/src/jvmMain/kotlin/com/hedvig/android/featureflags/flags/NoopFeatureFlagProvider.kt new file mode 100644 index 0000000000..3033fdafd7 --- /dev/null +++ b/app/featureflags/feature-flags/src/jvmMain/kotlin/com/hedvig/android/featureflags/flags/NoopFeatureFlagProvider.kt @@ -0,0 +1,11 @@ +package com.hedvig.android.featureflags.flags + +import com.hedvig.android.featureflags.FeatureManager +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf + +internal class NoopFeatureFlagProvider : FeatureManager { + override fun isFeatureEnabled(feature: Feature): Flow { + return flowOf(false) + } +} diff --git a/app/language/language-core/src/nativeMain/kotlin/com/hedvig/android/language/LanguageService.native.kt b/app/language/language-core/src/nativeMain/kotlin/com/hedvig/android/language/LanguageService.native.kt index 52c839a00b..77bba8a054 100644 --- a/app/language/language-core/src/nativeMain/kotlin/com/hedvig/android/language/LanguageService.native.kt +++ b/app/language/language-core/src/nativeMain/kotlin/com/hedvig/android/language/LanguageService.native.kt @@ -5,18 +5,18 @@ import com.hedvig.android.core.locale.CommonLocale // todo ios internal class NativeLanguageService : LanguageService { override fun setLanguage(language: Language) { - TODO("Not yet implemented") + } override fun getSelectedLanguage(): Language? { - TODO("Not yet implemented") + return Language.EN_SE } override fun getLanguage(): Language { - TODO("Not yet implemented") + return Language.EN_SE } override fun getLocale(): CommonLocale { - TODO("Not yet implemented") + return CommonLocale(Language.EN_SE.toBcp47Format()) } } diff --git a/app/logging/logging-public/src/nativeMain/kotlin/com/hedvig/android/logger/IosLogcatLogger.kt b/app/logging/logging-public/src/nativeMain/kotlin/com/hedvig/android/logger/IosLogcatLogger.kt new file mode 100644 index 0000000000..279252ac08 --- /dev/null +++ b/app/logging/logging-public/src/nativeMain/kotlin/com/hedvig/android/logger/IosLogcatLogger.kt @@ -0,0 +1,28 @@ +package com.hedvig.android.logger + +import platform.Foundation.NSLog + +class IosLogcatLogger : LogcatLogger { + override fun log(priority: LogPriority, throwable: Throwable?, tag: String?, message: () -> String) { + val prefix = when (priority) { + LogPriority.VERBOSE -> "V" + LogPriority.DEBUG -> "D" + LogPriority.INFO -> "I" + LogPriority.WARN -> "W" + LogPriority.ERROR -> "E" + LogPriority.ASSERT -> "A" + } + val tagPart = if (tag != null) "[$tag] " else "" + val messagePart = message() + val throwablePart = if (throwable != null) "\n${throwable.stackTraceToString()}" else "" + NSLog("%s", "$prefix/$tagPart$messagePart$throwablePart") + } + + companion object { + fun install() { + if (!LogcatLogger.isInstalled) { + LogcatLogger.install(IosLogcatLogger()) + } + } + } +} diff --git a/app/member-reminders/member-reminders-public/build.gradle.kts b/app/member-reminders/member-reminders-public/build.gradle.kts index 7ff1c4d7cf..e1eebfbf95 100644 --- a/app/member-reminders/member-reminders-public/build.gradle.kts +++ b/app/member-reminders/member-reminders-public/build.gradle.kts @@ -28,7 +28,7 @@ dependencies { implementation(projects.coreDemoMode) implementation(projects.dataContract) implementation(projects.dataPayingMember) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) testImplementation(libs.apollo.annotations) testImplementation(libs.apollo.testingSupport) diff --git a/app/molecule/molecule-public/build.gradle.kts b/app/molecule/molecule-public/build.gradle.kts index 09f54b8a13..1f27ffc6b3 100644 --- a/app/molecule/molecule-public/build.gradle.kts +++ b/app/molecule/molecule-public/build.gradle.kts @@ -12,8 +12,8 @@ kotlin { sourceSets { commonMain.dependencies { api(libs.jetbrains.lifecycle.viewmodel) + api(libs.molecule) implementation(libs.coroutines.core) - implementation(libs.molecule) implementation(libs.jetbrains.compose.runtime) implementation(libs.coroutines.core) } diff --git a/app/molecule/molecule-public/src/nativeMain/kotlin/com/hedvig/android/molecule/public/MoleculeViewModel.native.kt b/app/molecule/molecule-public/src/nativeMain/kotlin/com/hedvig/android/molecule/public/MoleculeViewModel.native.kt index 6cd0164580..730d73638c 100644 --- a/app/molecule/molecule-public/src/nativeMain/kotlin/com/hedvig/android/molecule/public/MoleculeViewModel.native.kt +++ b/app/molecule/molecule-public/src/nativeMain/kotlin/com/hedvig/android/molecule/public/MoleculeViewModel.native.kt @@ -2,5 +2,6 @@ package com.hedvig.android.molecule.public import app.cash.molecule.DisplayLinkClock import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.Dispatchers -internal actual val mainDispatcher: CoroutineContext = DisplayLinkClock +internal actual val mainDispatcher: CoroutineContext = Dispatchers.Main + DisplayLinkClock diff --git a/app/navigation/navigation-compose-typed/build.gradle.kts b/app/navigation/navigation-compose-typed/build.gradle.kts index 6556e43c00..c5caff6eb5 100644 --- a/app/navigation/navigation-compose-typed/build.gradle.kts +++ b/app/navigation/navigation-compose-typed/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") } @@ -8,12 +9,16 @@ hedvig { compose() } -dependencies { - implementation(libs.androidx.navigation.common) - implementation(libs.androidx.navigation.runtime) - implementation(libs.jetbrains.compose.runtime) - implementation(libs.koin.composeViewModel) - implementation(libs.kotlinx.serialization.core) - implementation(projects.navigationCommon) - implementation(projects.navigationCompose) +kotlin { + sourceSets { + commonMain.dependencies { + implementation(libs.jetbrains.navigation.compose) + implementation(libs.jetbrains.compose.runtime) + implementation(libs.jetbrains.lifecycle.viewmodel) + implementation(libs.koin.composeViewModel) + implementation(libs.kotlinx.serialization.core) + implementation(projects.navigationCommon) + implementation(projects.navigationCompose) + } + } } diff --git a/app/navigation/navigation-compose-typed/src/main/kotlin/com/hedvig/android/navigation/compose/typed/DestinationScopedViewModel.kt b/app/navigation/navigation-compose-typed/src/commonMain/kotlin/com/hedvig/android/navigation/compose/typed/DestinationScopedViewModel.kt similarity index 100% rename from app/navigation/navigation-compose-typed/src/main/kotlin/com/hedvig/android/navigation/compose/typed/DestinationScopedViewModel.kt rename to app/navigation/navigation-compose-typed/src/commonMain/kotlin/com/hedvig/android/navigation/compose/typed/DestinationScopedViewModel.kt diff --git a/app/navigation/navigation-compose-typed/src/main/kotlin/com/hedvig/android/navigation/compose/typed/getRouteFromBackStack.kt b/app/navigation/navigation-compose-typed/src/commonMain/kotlin/com/hedvig/android/navigation/compose/typed/getRouteFromBackStack.kt similarity index 100% rename from app/navigation/navigation-compose-typed/src/main/kotlin/com/hedvig/android/navigation/compose/typed/getRouteFromBackStack.kt rename to app/navigation/navigation-compose-typed/src/commonMain/kotlin/com/hedvig/android/navigation/compose/typed/getRouteFromBackStack.kt diff --git a/app/navigation/navigation-compose-typed/src/main/AndroidManifest.xml b/app/navigation/navigation-compose-typed/src/main/AndroidManifest.xml deleted file mode 100644 index 568741e54f..0000000000 --- a/app/navigation/navigation-compose-typed/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/app/notification-badge-data/notification-badge-data-public/build.gradle.kts b/app/notification-badge-data/notification-badge-data-public/build.gradle.kts index 4fc395693e..6d35b9e6e4 100644 --- a/app/notification-badge-data/notification-badge-data-public/build.gradle.kts +++ b/app/notification-badge-data/notification-badge-data-public/build.gradle.kts @@ -16,7 +16,7 @@ dependencies { implementation(projects.apolloCore) implementation(projects.apolloOctopusPublic) implementation(projects.coreDemoMode) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) implementation(projects.languageCore) testImplementation(libs.assertK) diff --git a/app/notification/notification-firebase/build.gradle.kts b/app/notification/notification-firebase/build.gradle.kts index 8d5e4aa026..91349d8fd9 100644 --- a/app/notification/notification-firebase/build.gradle.kts +++ b/app/notification/notification-firebase/build.gradle.kts @@ -22,6 +22,6 @@ dependencies { implementation(projects.authEventCore) implementation(projects.coreCommonPublic) implementation(projects.coreDemoMode) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) implementation(projects.notificationCore) } diff --git a/app/shared/tier-comparison/build.gradle.kts b/app/shared/tier-comparison/build.gradle.kts index dd7c60bcfb..4e20430f5e 100644 --- a/app/shared/tier-comparison/build.gradle.kts +++ b/app/shared/tier-comparison/build.gradle.kts @@ -27,7 +27,7 @@ dependencies { implementation(projects.coreCommonPublic) implementation(projects.coreResources) implementation(projects.designSystemHedvig) - implementation(projects.featureFlagsPublic) + implementation(projects.featureFlags) implementation(projects.languageCore) implementation(projects.moleculePublic) } diff --git a/app/shareddi/build.gradle.kts b/app/shareddi/build.gradle.kts index a34d17f156..de8112e567 100644 --- a/app/shareddi/build.gradle.kts +++ b/app/shareddi/build.gradle.kts @@ -1,5 +1,3 @@ -import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi - plugins { id("hedvig.multiplatform.library") id("hedvig.multiplatform.library.android") @@ -13,6 +11,8 @@ kotlin { implementation(libs.apollo.engine.ktor) implementation(libs.apollo.normalizedCache) implementation(libs.apollo.runtime) + implementation(libs.coil.coil) + implementation(libs.coil.network.ktor) implementation(libs.koin.core) implementation(libs.ktor.client.auth) implementation(libs.ktor.client.logging) @@ -21,6 +21,8 @@ kotlin { implementation(projects.coreCommonPublic) implementation(projects.coreDatastorePublic) implementation(projects.featureClaimChat) + implementation(projects.featureFlags) + implementation(projects.featureHelpCenter) implementation(projects.languageCore) implementation(projects.networkClients) implementation(projects.permissionCore) diff --git a/app/shareddi/src/commonMain/kotlin/com/hedvig/android/shareddi/SharedModule.kt b/app/shareddi/src/commonMain/kotlin/com/hedvig/android/shareddi/SharedModule.kt index 9cdde84ded..574d17494d 100644 --- a/app/shareddi/src/commonMain/kotlin/com/hedvig/android/shareddi/SharedModule.kt +++ b/app/shareddi/src/commonMain/kotlin/com/hedvig/android/shareddi/SharedModule.kt @@ -1,15 +1,18 @@ package com.hedvig.android.shareddi -import com.apollographql.apollo.ApolloClient import com.hedvig.android.core.buildconstants.AppBuildConfig -import com.hedvig.android.core.datastore.di.dataStoreModule +import com.hedvig.android.core.buildconstants.di.buildConstantsModule import com.hedvig.android.network.clients.di.networkModule import org.koin.core.module.Module import org.koin.dsl.module fun sharedModule(appBuildConfig: AppBuildConfig) = module { single { appBuildConfig } - includes(platformModule, networkModule, dataStoreModule) + includes( + buildConstantsModule, + networkModule, + platformModule, + ) } internal expect val platformModule: Module diff --git a/app/shareddi/src/nativeMain/kotlin/com/hedvig/android/shareddi/SharedModule.native.kt b/app/shareddi/src/nativeMain/kotlin/com/hedvig/android/shareddi/SharedModule.native.kt index f567bad381..a4e84fa9a5 100644 --- a/app/shareddi/src/nativeMain/kotlin/com/hedvig/android/shareddi/SharedModule.native.kt +++ b/app/shareddi/src/nativeMain/kotlin/com/hedvig/android/shareddi/SharedModule.native.kt @@ -1,9 +1,13 @@ package com.hedvig.android.shareddi -import com.apollographql.apollo.ApolloClient -import com.apollographql.apollo.network.http.DefaultHttpEngine +import coil3.ImageLoader +import coil3.PlatformContext +import coil3.network.ktor3.KtorNetworkFetcherFactory +import com.hedvig.android.core.common.di.baseHttpClientQualifier import com.hedvig.android.core.datastore.DeviceIdFetcher +import com.hedvig.android.featureflags.FeatureManager import com.hedvig.android.network.clients.AccessTokenFetcher +import io.ktor.client.HttpClient import org.koin.core.module.Module import org.koin.dsl.module @@ -13,11 +17,25 @@ internal actual val platformModule: Module = module { /** * Like [platformModule] but allows for dynamic input, for pieces that need to be injected from iOS */ -internal fun iosPlatformModule(accessTokenFetcher: AccessTokenFetcher, deviceIdFetcher: DeviceIdFetcher) = module { +internal fun iosPlatformModule( + accessTokenFetcher: AccessTokenFetcher, + deviceIdFetcher: DeviceIdFetcher, + featureManager: FeatureManager, +) = module { single { accessTokenFetcher } single { deviceIdFetcher } + single { + featureManager + } + single { + ImageLoader.Builder(PlatformContext.INSTANCE) + .components { + add(KtorNetworkFetcherFactory(get(baseHttpClientQualifier))) + } + .build() + } } diff --git a/app/shareddi/src/nativeMain/kotlin/com/hedvig/android/shareddi/main.native.kt b/app/shareddi/src/nativeMain/kotlin/com/hedvig/android/shareddi/main.native.kt index 546fd8de09..7b2a498562 100644 --- a/app/shareddi/src/nativeMain/kotlin/com/hedvig/android/shareddi/main.native.kt +++ b/app/shareddi/src/nativeMain/kotlin/com/hedvig/android/shareddi/main.native.kt @@ -1,7 +1,13 @@ package com.hedvig.android.shareddi import com.hedvig.android.core.buildconstants.AppBuildConfig +import com.hedvig.android.core.buildconstants.di.buildConstantsModule import com.hedvig.android.core.datastore.DeviceIdFetcher +import com.hedvig.android.core.datastore.di.dataStoreModule +import com.hedvig.android.data.conversations.di.dataConversationsModule +import com.hedvig.android.feature.help.center.di.helpCenterModule +import com.hedvig.android.featureflags.FeatureManager +import com.hedvig.android.language.di.languageModule import com.hedvig.android.network.clients.AccessTokenFetcher import com.hedvig.android.permission.di.noopPermissionModule import com.hedvig.feature.claim.chat.di.claimChatModule @@ -11,13 +17,18 @@ import org.koin.core.context.startKoin fun initKoin( accessTokenFetcher: AccessTokenFetcher, deviceIdFetcher: DeviceIdFetcher, + featureManager: FeatureManager, appBuildConfig: AppBuildConfig, ) { startKoin { modules( - iosPlatformModule(accessTokenFetcher, deviceIdFetcher), + iosPlatformModule(accessTokenFetcher, deviceIdFetcher, featureManager), sharedModule(appBuildConfig), + dataStoreModule, + languageModule, + dataConversationsModule, claimChatModule, + helpCenterModule, noopPermissionModule, ) } diff --git a/app/ui/ui-emergency/build.gradle.kts b/app/ui/ui-emergency/build.gradle.kts index 43a1db82fe..a9cafd2b20 100644 --- a/app/ui/ui-emergency/build.gradle.kts +++ b/app/ui/ui-emergency/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("hedvig.android.library") + id("hedvig.multiplatform.library") id("hedvig.gradle.plugin") } @@ -8,14 +8,19 @@ hedvig { compose() } -dependencies { - implementation(libs.androidx.compose.foundation) - implementation(libs.androidx.compose.foundationLayout) - implementation(libs.jetbrains.compose.runtime) - implementation(libs.jetbrains.compose.ui) - implementation(libs.kotlinx.serialization.core) - implementation(projects.coreResources) - implementation(projects.coreUiData) - implementation(projects.dataContract) - implementation(projects.designSystemHedvig) +kotlin { + sourceSets { + commonMain.dependencies { + implementation(libs.jetbrains.compose.foundation) + implementation(libs.jetbrains.compose.foundation.layout) + implementation(libs.jetbrains.compose.runtime) + implementation(libs.jetbrains.compose.ui) + implementation(libs.kotlinx.serialization.core) + implementation(projects.coreResources) + implementation(projects.coreUiData) + implementation(projects.dataContract) + implementation(projects.designSystemHedvig) + implementation(projects.loggingPublic) + } + } } diff --git a/app/ui/ui-emergency/src/main/kotlin/com/hedvig/android/ui/emergency/FirstVetScreen.kt b/app/ui/ui-emergency/src/commonMain/kotlin/com/hedvig/android/ui/emergency/FirstVetScreen.kt similarity index 95% rename from app/ui/ui-emergency/src/main/kotlin/com/hedvig/android/ui/emergency/FirstVetScreen.kt rename to app/ui/ui-emergency/src/commonMain/kotlin/com/hedvig/android/ui/emergency/FirstVetScreen.kt index f7c32fab00..f5509c5c9f 100644 --- a/app/ui/ui-emergency/src/main/kotlin/com/hedvig/android/ui/emergency/FirstVetScreen.kt +++ b/app/ui/ui-emergency/src/commonMain/kotlin/com/hedvig/android/ui/emergency/FirstVetScreen.kt @@ -1,7 +1,5 @@ package com.hedvig.android.ui.emergency -import android.content.Intent -import android.net.Uri import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -14,7 +12,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.semantics.heading import androidx.compose.ui.semantics.hideFromAccessibility import androidx.compose.ui.semantics.semantics @@ -43,9 +40,9 @@ fun FirstVetScreen( sections: List, navigateUp: () -> Unit, navigateBack: () -> Unit, + openUrl: (String) -> Unit, modifier: Modifier = Modifier, ) { - val context = LocalContext.current HedvigScaffold( topAppBarText = stringResource(Res.string.HC_QUICK_ACTIONS_FIRSTVET_TITLE), navigateUp = navigateUp, @@ -98,9 +95,7 @@ fun FirstVetScreen( ?: stringResource(Res.string.SUBMIT_CLAIM_GLASS_DAMAGE_ONLINE_BOOKING_BUTTON), onClick = { val url = section.url ?: "https://firstvet-se.go.link/kHxkt" - context.startActivity( - Intent(Intent.ACTION_VIEW, Uri.parse(url)), - ) + openUrl(url) }, modifier = Modifier.fillMaxWidth(), ) @@ -137,6 +132,7 @@ private fun PreviewFirstVetScreen() { }, {}, {}, + {}, ) } } diff --git a/app/ui/ui-emergency/src/main/AndroidManifest.xml b/app/ui/ui-emergency/src/main/AndroidManifest.xml deleted file mode 100644 index 568741e54f..0000000000 --- a/app/ui/ui-emergency/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/app/umbrella/build.gradle.kts b/app/umbrella/build.gradle.kts index 74234899a8..dfb1907ae2 100644 --- a/app/umbrella/build.gradle.kts +++ b/app/umbrella/build.gradle.kts @@ -2,7 +2,10 @@ import org.gradle.api.internal.catalog.DelegatingProjectDependency import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework plugins { + alias(libs.plugins.composeKotlinCompilerGradlePlugin) + alias(libs.plugins.composeJetbrainsCompilerGradlePlugin) id("hedvig.multiplatform.library") + id("hedvig.multiplatform.library.android") id("hedvig.gradle.plugin") alias(libs.plugins.kmpNativeCoroutines) } @@ -15,18 +18,24 @@ kotlin { val xcf = XCFramework(frameworkName) val projectsToExport: List = listOf( projects.authlib, - projects.featureClaimChat, + projects.coreBuildConstants, + projects.coreDatastorePublic, + projects.featureFlags, + projects.featureHelpCenter, + projects.loggingPublic, + projects.networkClients, projects.shareddi, ) listOf( - iosX64(), iosArm64(), iosSimulatorArm64(), ).forEach { iosTarget -> iosTarget.binaries.framework { + isStatic = true for (projectToExport in projectsToExport) { export(projectToExport) } + binaryOption("bundleId", frameworkName) baseName = frameworkName xcf.add(this) } diff --git a/build-logic/convention/src/main/kotlin/KotlinMultiplatformAndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/KotlinMultiplatformAndroidLibraryConventionPlugin.kt index 23a7f87d39..24e7e601cc 100644 --- a/build-logic/convention/src/main/kotlin/KotlinMultiplatformAndroidLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/KotlinMultiplatformAndroidLibraryConventionPlugin.kt @@ -52,7 +52,6 @@ private fun Project.configureKotlinAndroidMultiplatform() { project.configure { targets.withType(KotlinMultiplatformAndroidLibraryTarget::class.java) { - @Suppress("UnstableApiUsage") androidResources.enable = true compileSdk = libs.versions.compileSdkVersion.get().toInt() minSdk = libs.versions.minSdkVersion.get().toInt() @@ -73,8 +72,6 @@ private fun Project.configureKotlinAndroidMultiplatform() { } } configureAutomaticNamespace(path, namespace, { namespace = it }) - // https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-multiplatform-resources-setup.html#resources-in-the-androidlibrary-target - experimentalProperties["android.experimental.kmp.enableAndroidResources"] = true } } diff --git a/build-logic/convention/src/main/kotlin/KotlinMultiplatformLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/KotlinMultiplatformLibraryConventionPlugin.kt index 8ffbd9db61..d3631f856c 100644 --- a/build-logic/convention/src/main/kotlin/KotlinMultiplatformLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/KotlinMultiplatformLibraryConventionPlugin.kt @@ -37,7 +37,6 @@ private fun Project.configureKotlinMultiplatform() { } listOf( - iosX64(), iosArm64(), iosSimulatorArm64(), ) diff --git a/gradle.properties b/gradle.properties index 3f95d650a4..a751673dbf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -39,4 +39,7 @@ android.dependency.excludeLibraryComponentsFromConstraints=true android.r8.strictFullModeForKeepRules=false android.r8.optimizedResourceShrinking=false android.builtInKotlin=false -android.newDsl=false \ No newline at end of file +android.newDsl=false + +kotlin.native.cacheKind.iosSimulatorArm64=none +kotlin.native.binary.forceNativeThreadStateForFunctions=org_jetbrains_skia_DirectContext__1nFlushAndSubmit;org_jetbrains_skia_Canvas__1nDrawPicture diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b9e5952f56..add36ec2d3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,8 +20,8 @@ doctor = "0.12.1" easylauncher = "6.4.1" googleServices = "4.4.4" gradleDevelocity = "4.3.2" -kmpNativeCoroutines = "1.0.1" -kotlin = "2.3.10" +kmpNativeCoroutines = "1.0.2" +kotlin = "2.3.20" kotlinter = "5.4.2" ksp = "2.3.2" ktor = "3.4.0" @@ -33,10 +33,10 @@ squareSortDependencies = "0.16" # Other versions sorted alphabetically accompanist = "0.37.3" rive = "11.2.1" -androidx-activity-compose = "1.12.3" -androidx-activity-core = "1.12.3" +androidx-activity-compose = "1.13.0" +androidx-activity-core = "1.13.0" androidx-annotation = "1.9.1" -androidx-composeBom = "2026.01.01" +androidx-composeBom = "2026.03.01" androidx-datastore = "1.2.0" androidx-junit = "1.3.0" androidx-lifecycle = "2.10.0" @@ -44,22 +44,22 @@ androidx-navigation = "2.9.7" androidx-other-appCompat = "1.7.1" androidx-other-browser = "1.9.0" androidx-other-constraintLayout = "2.2.0" -androidx-other-core = "1.17.0" +androidx-other-core = "1.18.0" androidx-other-splashscreen = "1.2.0" androidx-other-startup = "1.2.0" androidx-other-workManager = "2.11.1" androidx-test = "1.7.0" androidx-testRunners = "1.7.0" -androidx-ui-alpha = "1.10.2" +androidx-ui-alpha = "1.10.6" androidxGraphicsShapes = "1.1.0" -jetbrains-animation = "1.10.0" -jetbrains-compose = "1.10.0" -jetbrains-navigationevent = "1.0.0" +jetbrains-animation = "1.11.0-beta01" +jetbrains-compose = "1.11.0-beta01" +jetbrains-navigationevent = "1.0.1" jetbrains-graphics = "1.0.0-alpha09" -jetbrains-lifecycle = "2.9.6" -jetbrains-material = "1.10.0" -jetbrains-material3 = "1.10.0-alpha05" -jetbrains-navigation = "2.9.1" +jetbrains-lifecycle = "2.10.0" +jetbrains-material = "1.11.0-beta01" +jetbrains-material3 = "1.11.0-alpha05" +jetbrains-navigation = "2.9.2" arrow = "2.2.1.1" assertK = "0.28.1" atomicfu = "0.31.0" @@ -74,7 +74,7 @@ firebaseCrashlyticsBuildtools = "3.0.6" junit = "4.13.2" koinBom = "4.1.1" kotlinx-serialization = "1.10.0" -kotlinxDatetime = "0.7.1" +kotlinxDatetime = "0.7.1-0.6.x-compat" media3 = "1.9.2" modalSheet = "0.7.0" navigationRecentsUrlSharing = "1.0.0" diff --git a/gradle/projectDependencyGraph.gradle b/gradle/projectDependencyGraph.gradle index 81c1678bf9..2235a196cf 100644 --- a/gradle/projectDependencyGraph.gradle +++ b/gradle/projectDependencyGraph.gradle @@ -53,7 +53,8 @@ task generateProjectDependencyGraph { project.configurations.all { config -> config.dependencies .withType(ProjectDependency) - .collect { it.dependencyProject } + .collect { rootProject.findProject(it.path) } + .findAll { it != null } .each { dependency -> projects.add(project) projects.add(dependency) diff --git a/micro-apps/umbrella-consumer/umbrella-consumer.xcodeproj/project.pbxproj b/micro-apps/umbrella-consumer/umbrella-consumer.xcodeproj/project.pbxproj index b5dc700d0b..5884840711 100644 --- a/micro-apps/umbrella-consumer/umbrella-consumer.xcodeproj/project.pbxproj +++ b/micro-apps/umbrella-consumer/umbrella-consumer.xcodeproj/project.pbxproj @@ -6,6 +6,18 @@ objectVersion = 77; objects = { +/* Begin PBXBuildFile section */ + 558DDBF52F76ACAE00B1F12F /* DatadogCore in Frameworks */ = {isa = PBXBuildFile; productRef = 558DDBF42F76ACAE00B1F12F /* DatadogCore */; }; + 558DDBF72F76ACAE00B1F12F /* DatadogCrashReporting in Frameworks */ = {isa = PBXBuildFile; productRef = 558DDBF62F76ACAE00B1F12F /* DatadogCrashReporting */; }; + 558DDBF92F76ACAE00B1F12F /* DatadogFlags in Frameworks */ = {isa = PBXBuildFile; productRef = 558DDBF82F76ACAE00B1F12F /* DatadogFlags */; }; + 558DDBFB2F76ACAE00B1F12F /* DatadogLogs in Frameworks */ = {isa = PBXBuildFile; productRef = 558DDBFA2F76ACAE00B1F12F /* DatadogLogs */; }; + 558DDBFD2F76ACAE00B1F12F /* DatadogProfiling in Frameworks */ = {isa = PBXBuildFile; productRef = 558DDBFC2F76ACAE00B1F12F /* DatadogProfiling */; }; + 558DDBFF2F76ACAE00B1F12F /* DatadogRUM in Frameworks */ = {isa = PBXBuildFile; productRef = 558DDBFE2F76ACAE00B1F12F /* DatadogRUM */; }; + 558DDC012F76ACAE00B1F12F /* DatadogSessionReplay in Frameworks */ = {isa = PBXBuildFile; productRef = 558DDC002F76ACAE00B1F12F /* DatadogSessionReplay */; }; + 558DDC032F76ACAE00B1F12F /* DatadogTrace in Frameworks */ = {isa = PBXBuildFile; productRef = 558DDC022F76ACAE00B1F12F /* DatadogTrace */; }; + 558DDC052F76ACAE00B1F12F /* DatadogWebViewTracking in Frameworks */ = {isa = PBXBuildFile; productRef = 558DDC042F76ACAE00B1F12F /* DatadogWebViewTracking */; }; +/* End PBXBuildFile section */ + /* Begin PBXFileReference section */ 55D8AB952EBE16C700E53763 /* umbrella-consumer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "umbrella-consumer.app"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -36,6 +48,15 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 558DDC052F76ACAE00B1F12F /* DatadogWebViewTracking in Frameworks */, + 558DDBFD2F76ACAE00B1F12F /* DatadogProfiling in Frameworks */, + 558DDBFB2F76ACAE00B1F12F /* DatadogLogs in Frameworks */, + 558DDBF72F76ACAE00B1F12F /* DatadogCrashReporting in Frameworks */, + 558DDC012F76ACAE00B1F12F /* DatadogSessionReplay in Frameworks */, + 558DDBF52F76ACAE00B1F12F /* DatadogCore in Frameworks */, + 558DDBFF2F76ACAE00B1F12F /* DatadogRUM in Frameworks */, + 558DDBF92F76ACAE00B1F12F /* DatadogFlags in Frameworks */, + 558DDC032F76ACAE00B1F12F /* DatadogTrace in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -79,6 +100,15 @@ ); name = "umbrella-consumer"; packageProductDependencies = ( + 558DDBF42F76ACAE00B1F12F /* DatadogCore */, + 558DDBF62F76ACAE00B1F12F /* DatadogCrashReporting */, + 558DDBF82F76ACAE00B1F12F /* DatadogFlags */, + 558DDBFA2F76ACAE00B1F12F /* DatadogLogs */, + 558DDBFC2F76ACAE00B1F12F /* DatadogProfiling */, + 558DDBFE2F76ACAE00B1F12F /* DatadogRUM */, + 558DDC002F76ACAE00B1F12F /* DatadogSessionReplay */, + 558DDC022F76ACAE00B1F12F /* DatadogTrace */, + 558DDC042F76ACAE00B1F12F /* DatadogWebViewTracking */, ); productName = "umbrella-consumer"; productReference = 55D8AB952EBE16C700E53763 /* umbrella-consumer.app */; @@ -108,6 +138,9 @@ ); mainGroup = 55D8AB8C2EBE16C700E53763; minimizedProjectReferenceProxies = 1; + packageReferences = ( + 558DDBF32F76ACAE00B1F12F /* XCRemoteSwiftPackageReference "dd-sdk-ios" */, + ); preferredProjectObjectVersion = 77; productRefGroup = 55D8AB962EBE16C700E53763 /* Products */; projectDirPath = ""; @@ -145,7 +178,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "cd \"$SRCROOT\"\ncd ../..\nexport JAVA_HOME=\"/Library/Java/JavaVirtualMachines/zulu-23.jdk/Contents/Home\"\n./gradlew :umbrella:embedAndSignAppleFrameworkForXcode\n"; + shellScript = "if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \\\"YES\\\"\"\n exit 0\nfi\ncd \"$SRCROOT\"\ncd ../..\nexport JAVA_HOME=\"/Library/Java/JavaVirtualMachines/zulu-23.jdk/Contents/Home\"\n./gradlew :umbrella:embedAndSignAppleFrameworkForXcode\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -213,7 +246,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 26.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.6; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -271,7 +304,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 26.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.6; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; @@ -296,8 +329,9 @@ INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + IPHONEOS_DEPLOYMENT_TARGET = 16.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -330,8 +364,9 @@ INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + IPHONEOS_DEPLOYMENT_TARGET = 16.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -371,6 +406,65 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 558DDBF32F76ACAE00B1F12F /* XCRemoteSwiftPackageReference "dd-sdk-ios" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/DataDog/dd-sdk-ios.git"; + requirement = { + kind = exactVersion; + version = 3.6.1; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 558DDBF42F76ACAE00B1F12F /* DatadogCore */ = { + isa = XCSwiftPackageProductDependency; + package = 558DDBF32F76ACAE00B1F12F /* XCRemoteSwiftPackageReference "dd-sdk-ios" */; + productName = DatadogCore; + }; + 558DDBF62F76ACAE00B1F12F /* DatadogCrashReporting */ = { + isa = XCSwiftPackageProductDependency; + package = 558DDBF32F76ACAE00B1F12F /* XCRemoteSwiftPackageReference "dd-sdk-ios" */; + productName = DatadogCrashReporting; + }; + 558DDBF82F76ACAE00B1F12F /* DatadogFlags */ = { + isa = XCSwiftPackageProductDependency; + package = 558DDBF32F76ACAE00B1F12F /* XCRemoteSwiftPackageReference "dd-sdk-ios" */; + productName = DatadogFlags; + }; + 558DDBFA2F76ACAE00B1F12F /* DatadogLogs */ = { + isa = XCSwiftPackageProductDependency; + package = 558DDBF32F76ACAE00B1F12F /* XCRemoteSwiftPackageReference "dd-sdk-ios" */; + productName = DatadogLogs; + }; + 558DDBFC2F76ACAE00B1F12F /* DatadogProfiling */ = { + isa = XCSwiftPackageProductDependency; + package = 558DDBF32F76ACAE00B1F12F /* XCRemoteSwiftPackageReference "dd-sdk-ios" */; + productName = DatadogProfiling; + }; + 558DDBFE2F76ACAE00B1F12F /* DatadogRUM */ = { + isa = XCSwiftPackageProductDependency; + package = 558DDBF32F76ACAE00B1F12F /* XCRemoteSwiftPackageReference "dd-sdk-ios" */; + productName = DatadogRUM; + }; + 558DDC002F76ACAE00B1F12F /* DatadogSessionReplay */ = { + isa = XCSwiftPackageProductDependency; + package = 558DDBF32F76ACAE00B1F12F /* XCRemoteSwiftPackageReference "dd-sdk-ios" */; + productName = DatadogSessionReplay; + }; + 558DDC022F76ACAE00B1F12F /* DatadogTrace */ = { + isa = XCSwiftPackageProductDependency; + package = 558DDBF32F76ACAE00B1F12F /* XCRemoteSwiftPackageReference "dd-sdk-ios" */; + productName = DatadogTrace; + }; + 558DDC042F76ACAE00B1F12F /* DatadogWebViewTracking */ = { + isa = XCSwiftPackageProductDependency; + package = 558DDBF32F76ACAE00B1F12F /* XCRemoteSwiftPackageReference "dd-sdk-ios" */; + productName = DatadogWebViewTracking; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 55D8AB8D2EBE16C700E53763 /* Project object */; } diff --git a/micro-apps/umbrella-consumer/umbrella-consumer.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/micro-apps/umbrella-consumer/umbrella-consumer.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000000..2d1eba0f77 --- /dev/null +++ b/micro-apps/umbrella-consumer/umbrella-consumer.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,42 @@ +{ + "originHash" : "ecc3edec2d3d8492b2aafc6cd36445ca859b5fde20181e9e4a9c7d388015e111", + "pins" : [ + { + "identity" : "dd-sdk-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/DataDog/dd-sdk-ios.git", + "state" : { + "revision" : "8291deb7abd083a2432c6ec323960c495ebdc76c", + "version" : "3.6.1" + } + }, + { + "identity" : "kscrash", + "kind" : "remoteSourceControl", + "location" : "https://github.com/kstenerud/KSCrash.git", + "state" : { + "revision" : "95a8895d75f3c22aa9ad9f2a15d2fbd97b0a55e2", + "version" : "2.5.1" + } + }, + { + "identity" : "opentelemetry-swift-core", + "kind" : "remoteSourceControl", + "location" : "https://github.com/open-telemetry/opentelemetry-swift-core", + "state" : { + "revision" : "240c8d5e36c3c7b774ed961325369f0b1f2c965f", + "version" : "2.3.0" + } + }, + { + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "b601256eab081c0f92f059e12818ac1d4f178ff7", + "version" : "1.3.0" + } + } + ], + "version" : 3 +} diff --git a/micro-apps/umbrella-consumer/umbrella-consumer/ContentView.swift b/micro-apps/umbrella-consumer/umbrella-consumer/ContentView.swift index bac5b60fc8..bd1bd116b6 100644 --- a/micro-apps/umbrella-consumer/umbrella-consumer/ContentView.swift +++ b/micro-apps/umbrella-consumer/umbrella-consumer/ContentView.swift @@ -3,16 +3,31 @@ import HedvigShared struct ContentView: View { var body: some View { - VStack { - ClaimChatViewController() - } - .padding() + HelpCenterViewController().ignoresSafeArea(.all) } } -struct ClaimChatViewController: UIViewControllerRepresentable { +struct HelpCenterViewController: UIViewControllerRepresentable { + @Environment(\.dismiss) private var dismiss + func makeUIViewController(context: Context) -> UIViewController { - return ClaimChatViewControllerKt.ClaimChatViewController() + return HelpCenterViewControllerKt.HelpCenterViewController( + onNavigateUp: { dismiss() }, + onNavigateToInbox: {}, + onNavigateToNewConversation: {}, + onNavigateToQuickLink: { _ in }, + openUrl: { url in + if let nsUrl = URL(string: url) { + UIApplication.shared.open(nsUrl) + } + }, + tryToDialPhone: { number in + let cleaned = number.components(separatedBy: .whitespaces).joined() + if let url = URL(string: "tel://\(cleaned)") { + UIApplication.shared.open(url) + } + } + ) } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { diff --git a/micro-apps/umbrella-consumer/umbrella-consumer/IosInterfaces.swift b/micro-apps/umbrella-consumer/umbrella-consumer/IosInterfaces.swift new file mode 100644 index 0000000000..c7bc648e1f --- /dev/null +++ b/micro-apps/umbrella-consumer/umbrella-consumer/IosInterfaces.swift @@ -0,0 +1,67 @@ +import HedvigShared +import SwiftUI + +class IosAccessTokenFetcher: AccessTokenFetcher { + let keychainAbstraction: KeychainAbstraction + + init(_ keychainAbstraction: KeychainAbstraction) { + self.keychainAbstraction = keychainAbstraction + } + + func fetch() async throws -> String? { + return try await keychainAbstraction.getToken() + } +} + +protocol KeychainAbstraction { + func getToken() async throws -> String +} + +class IosKeychainAbstraction: KeychainAbstraction { + func getToken() async throws -> String { + try await Task.sleep(for: .seconds(1)) + return "eyJraWQiOiJCSnd5VGNnek5WUmpmX0VuZjFKUFgxd3lrUjZSMElOTXRiR015UkduVkhNIiwiYWxnIjoiUlMyNTYifQ.eyJpbXBlcnNvbmF0ZWQtYnkiOiJhZG1fNWNmOTA4ZjAtMGZhMi00ZGE0LWExNzAtMjcyNjQwNTc3MDVhIiwic3ViIjoibWVtXzc4MjU4MDMwIiwiZXhwIjoxNzc2MTY4NjM2LCJpYXQiOjE3NzYxNjUwMzZ9.e7kF2qY3vBJyhrklZEIZ46AUp3AnmnEifgAF2ZzM7s6d9DfiQV4twpzXKWBt-ad376rUVndF2C0i--7lu0lYcje0460Hoo6ta929R3fFpeHpqJZ-Tqg-GHSRIeouZFpKXCrgbAjxzW3Vgtdkt6yG_NRER809PtwzpcIf66dJ3FrQ-p5hc7IyzF5KJ7aOAIJQIHlRuPK-1eKSwgRYBbO98f1LjewMrG_bXPlabZ2s7VBokiWPLX0TkDTI8A7CydMDP3lqWBwKvSbjnhSE6jPuRBoDTN0hSAbF1tCF5tibH6pE0EJcyBdO3IyX75AfqKAqeH3WMmIV7FcCXY3X4B4_6A" + } +} + +class IosDeviceIdFetcher: DeviceIdFetcher { + func fetch() async throws -> String? { + return UIDevice.current.identifierForVendor?.uuidString + } +} + +func iosFeatureManager() -> FeatureManager { + return IosFeatureManager( + isFeatureEnabledBlock: { feature in + switch feature { + default: false + } + } + ) +} + +class IosAppBuildConfig: AppBuildConfig { + var appFlavor: Flavor = Flavor.develop + + var applicationId: String = "" + + var brand: String = "" + + var buildType: String = "" + + var debug: Bool = true + + var device: String = "" + + var manufacturer: String = "" + + var model: String = "" + + var osReleaseVersion: String = "" + + var osSdkVersion: Int32 = 0 + + var versionCode: Int32 = 0 + + var versionName: String = "" +} diff --git a/micro-apps/umbrella-consumer/umbrella-consumer/umbrella_consumerApp.swift b/micro-apps/umbrella-consumer/umbrella-consumer/umbrella_consumerApp.swift index f89f5fe87b..28ce0416e8 100644 --- a/micro-apps/umbrella-consumer/umbrella-consumer/umbrella_consumerApp.swift +++ b/micro-apps/umbrella-consumer/umbrella-consumer/umbrella_consumerApp.swift @@ -3,36 +3,28 @@ import HedvigShared @main struct umbrella_consumerApp: App { - init() { - let keychain = IosKeychainAbstraction() - Main_nativeKt.doInitKoin(accessTokenFetcher: IosAccessTokenFetcher(keychain)) - } var body: some Scene { WindowGroup { ContentView() } } -} - -class IosAccessTokenFetcher: AccessTokenFetcher { - let keychainAbstraction: KeychainAbstraction - - init(_ keychainAbstraction: KeychainAbstraction) { - self.keychainAbstraction = keychainAbstraction - } - func fetch() async throws -> String? { - return try await keychainAbstraction.getToken() - } -} - -protocol KeychainAbstraction { - func getToken() async throws -> String + @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate } -class IosKeychainAbstraction: KeychainAbstraction { - func getToken() async throws -> String { - try await Task.sleep(for: .seconds(2)) - return "eyJraWQiOiJCSnd5VGNnek5WUmpmX0VuZjFKUFgxd3lrUjZSMElOTXRiR015UkduVkhNIiwiYWxnIjoiUlMyNTYifQ.eyJpbXBlcnNvbmF0ZWQtYnkiOiJhZG1fNWNmOTA4ZjAtMGZhMi00ZGE0LWExNzAtMjcyNjQwNTc3MDVhIiwic3ViIjoibWVtXzQ1NTQ2OTk5NyIsImV4cCI6MTc2Mjc4NDQyMiwiaWF0IjoxNzYyNzgwODIyfQ.OiSA4vQvWUunCV91RkwyW7zbsjQNjjl-SzTavkDLHr8m_xlZzAnnawHvssp8Lbhx880rSVJi-fE-akrZUYucnvlrP99Tht-G6L_igoeIIG66yFrvyUV6UAtqEyENJFptr_p-7BN-M5zkWuy1y3cunJDUXS0GGj8xsQ9CF9RAu0XkzVa-9Qeo7c2Ya73rHylR8yV8_AVaZ9fVl8bgeJGBnjjK_QT8Nbi7EuS2BKfB4TGPFp2phJnHu1Xio4Nx1CKNt4MiAsm2YYF8apEaquajyDngsstvjcUrnRU2ajmvY5s8UN4ErMAswSgKd_XondVZ_OokJHNTDXIE2Kj-StOYig" +class AppDelegate: UIResponder, UIApplicationDelegate { + // Run initializers on app launch + func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil + ) -> Bool { + Main_nativeKt.doInitKoin( + accessTokenFetcher: IosAccessTokenFetcher(IosKeychainAbstraction()), + deviceIdFetcher: IosDeviceIdFetcher(), + featureManager: iosFeatureManager(), + appBuildConfig: IosAppBuildConfig(), + ) + IosLogcatLogger.companion.install() + return true } } diff --git a/misc/images/modularization-graph.png b/misc/images/modularization-graph.png index 4cedb36ef2..001bde35da 100644 Binary files a/misc/images/modularization-graph.png and b/misc/images/modularization-graph.png differ