diff --git a/shared/di/src/androidMain/kotlin/fr/androidmakers/di/DomainModule.android.kt b/shared/di/src/androidMain/kotlin/fr/androidmakers/di/DomainModule.android.kt index 4cf999f1..3d6f9f01 100644 --- a/shared/di/src/androidMain/kotlin/fr/androidmakers/di/DomainModule.android.kt +++ b/shared/di/src/androidMain/kotlin/fr/androidmakers/di/DomainModule.android.kt @@ -2,14 +2,10 @@ package fr.androidmakers.di import fr.androidmakers.domain.interactor.OpenMapUseCase import fr.androidmakers.domain.interactor.ShareSessionUseCase -import fr.androidmakers.domain.utils.UrlOpener import org.koin.core.module.dsl.factoryOf -import org.koin.core.module.dsl.singleOf import org.koin.dsl.module actual val domainPlatformModule = module { - singleOf(::UrlOpener) - factoryOf(::OpenMapUseCase) factoryOf(::ShareSessionUseCase) } diff --git a/shared/di/src/commonMain/kotlin/fr/androidmakers/di/DomainModule.kt b/shared/di/src/commonMain/kotlin/fr/androidmakers/di/DomainModule.kt index 1b9d6f23..eb4d59b7 100644 --- a/shared/di/src/commonMain/kotlin/fr/androidmakers/di/DomainModule.kt +++ b/shared/di/src/commonMain/kotlin/fr/androidmakers/di/DomainModule.kt @@ -10,7 +10,6 @@ import fr.androidmakers.domain.interactor.MergeBookmarksUseCase import fr.androidmakers.domain.interactor.OpenBlueskyAccountUseCase import fr.androidmakers.domain.interactor.OpenCocUseCase import fr.androidmakers.domain.interactor.OpenFaqUseCase -import fr.androidmakers.domain.interactor.OpenLinkUseCase import fr.androidmakers.domain.interactor.OpenPartnerLinkUseCase import fr.androidmakers.domain.interactor.OpenXAccountUseCase import fr.androidmakers.domain.interactor.OpenXHashtagUseCase @@ -37,6 +36,5 @@ val domainModule = module { factoryOf(::GetPartnersUseCase) factoryOf(::GetFavoriteSessionsUseCase) factoryOf(::OpenPartnerLinkUseCase) - factoryOf(::OpenLinkUseCase) factoryOf(::ApplyForAppClinicUseCase) } diff --git a/shared/di/src/iosMain/kotlin/fr/androidmakers/di/DomainModule.ios.kt b/shared/di/src/iosMain/kotlin/fr/androidmakers/di/DomainModule.ios.kt index 4cf999f1..3d6f9f01 100644 --- a/shared/di/src/iosMain/kotlin/fr/androidmakers/di/DomainModule.ios.kt +++ b/shared/di/src/iosMain/kotlin/fr/androidmakers/di/DomainModule.ios.kt @@ -2,14 +2,10 @@ package fr.androidmakers.di import fr.androidmakers.domain.interactor.OpenMapUseCase import fr.androidmakers.domain.interactor.ShareSessionUseCase -import fr.androidmakers.domain.utils.UrlOpener import org.koin.core.module.dsl.factoryOf -import org.koin.core.module.dsl.singleOf import org.koin.dsl.module actual val domainPlatformModule = module { - singleOf(::UrlOpener) - factoryOf(::OpenMapUseCase) factoryOf(::ShareSessionUseCase) } diff --git a/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/PlatformContext.android.kt b/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/PlatformContext.android.kt index 0a54876c..a29b8e68 100644 --- a/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/PlatformContext.android.kt +++ b/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/PlatformContext.android.kt @@ -1,5 +1,3 @@ package fr.androidmakers.domain -import android.content.Context - -actual class PlatformContext(val context: Context) +actual typealias PlatformContext = android.content.Context diff --git a/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/interactor/OpenMapUseCase.android.kt b/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/interactor/OpenMapUseCase.android.kt index f57df72a..472b435c 100644 --- a/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/interactor/OpenMapUseCase.android.kt +++ b/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/interactor/OpenMapUseCase.android.kt @@ -1,14 +1,13 @@ package fr.androidmakers.domain.interactor +import android.content.ActivityNotFoundException +import android.content.Context import android.content.Intent import android.net.Uri -import fr.androidmakers.domain.PlatformContext -import fr.androidmakers.domain.utils.UrlOpener +import androidx.core.net.toUri -actual class OpenMapUseCase( - private val urlOpener: UrlOpener -) { - actual operator fun invoke(platformContext: PlatformContext, coordinates: String, name: String) { +actual class OpenMapUseCase() { + actual operator fun invoke(context: Context, coordinates: String, name: String) { val venueCoordinatesUri = Uri.Builder() .scheme("geo") .encodedAuthority(coordinates) @@ -16,13 +15,15 @@ actual class OpenMapUseCase( .build() try { val intent = Intent(Intent.ACTION_VIEW, venueCoordinatesUri) - platformContext.context.startActivity(intent) - } catch (e: Exception) { - // Open in Webview - urlOpener.openUrl( - platformContext = platformContext, - url = "https://www.google.com/maps/?q=" + coordinates.filter { it != ' ' } - ) + context.startActivity(intent) + } catch (_: ActivityNotFoundException) { + // Open in browser + val fallbackUri = ("https://www.google.com/maps/?q=" + coordinates.filter { it != ' ' }).toUri() + try { + val intent = Intent(Intent.ACTION_VIEW, fallbackUri) + context.startActivity(intent) + } catch (_: ActivityNotFoundException) { + } } } } diff --git a/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/interactor/ShareSessionUseCase.android.kt b/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/interactor/ShareSessionUseCase.android.kt index afdac9a2..70d76cb6 100644 --- a/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/interactor/ShareSessionUseCase.android.kt +++ b/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/interactor/ShareSessionUseCase.android.kt @@ -1,18 +1,17 @@ package fr.androidmakers.domain.interactor +import android.content.Context import androidx.core.app.ShareCompat -import fr.androidmakers.domain.PlatformContext import fr.androidmakers.domain.model.Session import fr.androidmakers.domain.model.Speaker actual class ShareSessionUseCase { actual operator fun invoke( - platformContext: PlatformContext, + context: Context, session: Session, speakers: List, formattedDateAndRoom: String ) { - val context = platformContext.context val shareText = if (speakers.isEmpty()) { "%s: %s (%s)".format( // TODO put this in resources diff --git a/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/utils/UrlOpener.android.kt b/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/utils/UrlOpener.android.kt deleted file mode 100644 index 12a29489..00000000 --- a/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/utils/UrlOpener.android.kt +++ /dev/null @@ -1,19 +0,0 @@ -package fr.androidmakers.domain.utils - -import android.content.ActivityNotFoundException -import android.content.Intent -import android.net.Uri -import fr.androidmakers.domain.PlatformContext - -actual class UrlOpener { - actual fun openUrl(platformContext: PlatformContext, url: String): Boolean { - return try { - val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) - platformContext.context.startActivity(intent) - true - } catch (anfe: ActivityNotFoundException) { - anfe.printStackTrace() - false - } - } -} diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/PlatformContext.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/PlatformContext.kt index e61ba053..fd570232 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/PlatformContext.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/PlatformContext.kt @@ -1,3 +1,3 @@ package fr.androidmakers.domain -expect class PlatformContext +expect abstract class PlatformContext diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/ApplyForAppClinicUseCase.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/ApplyForAppClinicUseCase.kt index 914854ba..85c93def 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/ApplyForAppClinicUseCase.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/ApplyForAppClinicUseCase.kt @@ -1,13 +1,10 @@ package fr.androidmakers.domain.interactor -import fr.androidmakers.domain.PlatformContext import fr.androidmakers.domain.model.APPLY_FOR_APP_CLINIC_MAILTO_URL import fr.androidmakers.domain.utils.UrlOpener -class ApplyForAppClinicUseCase( - private val urlOpener: UrlOpener -) { - operator fun invoke(platformContext: PlatformContext) { - urlOpener.openUrl(platformContext, APPLY_FOR_APP_CLINIC_MAILTO_URL) +class ApplyForAppClinicUseCase() { + operator fun invoke(urlOpener: UrlOpener) { + urlOpener.openUrl(APPLY_FOR_APP_CLINIC_MAILTO_URL) } } diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenBlueskyAccountUseCase.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenBlueskyAccountUseCase.kt index e66de605..004468ec 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenBlueskyAccountUseCase.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenBlueskyAccountUseCase.kt @@ -1,12 +1,9 @@ package fr.androidmakers.domain.interactor -import fr.androidmakers.domain.PlatformContext import fr.androidmakers.domain.utils.UrlOpener -class OpenBlueskyAccountUseCase( - private val urlOpener: UrlOpener -) { - operator fun invoke(platformContext: PlatformContext) { - urlOpener.openUrl(platformContext, "https://bsky.app/search?q=%23AMxDC25") +class OpenBlueskyAccountUseCase() { + operator fun invoke(urlOpener: UrlOpener) { + urlOpener.openUrl("https://bsky.app/search?q=%23AMxDC25") } } diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenCocUseCase.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenCocUseCase.kt index 1a7d8806..96d02ab6 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenCocUseCase.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenCocUseCase.kt @@ -1,12 +1,10 @@ package fr.androidmakers.domain.interactor -import fr.androidmakers.domain.PlatformContext import fr.androidmakers.domain.utils.Constants import fr.androidmakers.domain.utils.UrlOpener -class OpenCocUseCase( - private val urlOpener: UrlOpener -) { - operator fun invoke(platformContext: PlatformContext) = - urlOpener.openUrl(platformContext, Constants.Urls.coc) +class OpenCocUseCase() { + operator fun invoke(urlOpener: UrlOpener) { + urlOpener.openUrl(Constants.Urls.coc) + } } diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenFaqUseCase.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenFaqUseCase.kt index f5423a6b..8bb74e5f 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenFaqUseCase.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenFaqUseCase.kt @@ -1,12 +1,10 @@ package fr.androidmakers.domain.interactor -import fr.androidmakers.domain.PlatformContext import fr.androidmakers.domain.utils.Constants import fr.androidmakers.domain.utils.UrlOpener -class OpenFaqUseCase( - private val urlOpener: UrlOpener -) { - operator fun invoke(platformContext: PlatformContext) = - urlOpener.openUrl(platformContext, Constants.Urls.faq) +class OpenFaqUseCase() { + operator fun invoke(urlOpener: UrlOpener) { + urlOpener.openUrl(Constants.Urls.faq) + } } diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenLinkUseCase.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenLinkUseCase.kt deleted file mode 100644 index 097653ff..00000000 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenLinkUseCase.kt +++ /dev/null @@ -1,12 +0,0 @@ -package fr.androidmakers.domain.interactor - -import fr.androidmakers.domain.PlatformContext -import fr.androidmakers.domain.utils.UrlOpener - -class OpenLinkUseCase( - private val urlOpener: UrlOpener -) { - operator fun invoke(platformContext: PlatformContext, url: String) { - urlOpener.openUrl(platformContext, url) - } -} diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenMapUseCase.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenMapUseCase.kt index 2112e9a8..8b24285b 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenMapUseCase.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenMapUseCase.kt @@ -3,5 +3,5 @@ package fr.androidmakers.domain.interactor import fr.androidmakers.domain.PlatformContext expect class OpenMapUseCase { - operator fun invoke(platformContext: PlatformContext, coordinates: String, name: String) + operator fun invoke(context: PlatformContext, coordinates: String, name: String) } diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenPartnerLinkUseCase.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenPartnerLinkUseCase.kt index bfa3eb67..bb4eb2fb 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenPartnerLinkUseCase.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenPartnerLinkUseCase.kt @@ -1,13 +1,10 @@ package fr.androidmakers.domain.interactor -import fr.androidmakers.domain.PlatformContext import fr.androidmakers.domain.model.Partner import fr.androidmakers.domain.utils.UrlOpener -class OpenPartnerLinkUseCase( - private val urlOpener: UrlOpener -) { - operator fun invoke(platformContext: PlatformContext, partner: Partner) { - urlOpener.openUrl(platformContext, partner.url) +class OpenPartnerLinkUseCase() { + operator fun invoke(urlOpener: UrlOpener, partner: Partner) { + urlOpener.openUrl(partner.url) } } diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenXAccountUseCase.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenXAccountUseCase.kt index 1443a93f..220c9004 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenXAccountUseCase.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenXAccountUseCase.kt @@ -1,15 +1,12 @@ package fr.androidmakers.domain.interactor -import fr.androidmakers.domain.PlatformContext import fr.androidmakers.domain.utils.Constants import fr.androidmakers.domain.utils.UrlOpener -class OpenXAccountUseCase( - private val urlOpener: UrlOpener -) { - operator fun invoke(platformContext: PlatformContext) { - if (!urlOpener.openUrl(platformContext, Constants.Urls.xAccountApp)) { - urlOpener.openUrl(platformContext, Constants.Urls.xAccountWeb) +class OpenXAccountUseCase() { + operator fun invoke(urlOpener: UrlOpener) { + if (!urlOpener.openUrl(Constants.Urls.xAccountApp)) { + urlOpener.openUrl(Constants.Urls.xAccountWeb) } } } diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenXHashtagUseCase.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenXHashtagUseCase.kt index 27e47efb..5069f0e7 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenXHashtagUseCase.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenXHashtagUseCase.kt @@ -1,15 +1,12 @@ package fr.androidmakers.domain.interactor -import fr.androidmakers.domain.PlatformContext import fr.androidmakers.domain.utils.Constants import fr.androidmakers.domain.utils.UrlOpener -class OpenXHashtagUseCase( - private val urlOpener: UrlOpener -) { - operator fun invoke(platformContext: PlatformContext) { - if (!urlOpener.openUrl(platformContext, Constants.Urls.xHashtagApp)) { - urlOpener.openUrl(platformContext, Constants.Urls.xHashtagWeb) +class OpenXHashtagUseCase() { + operator fun invoke(urlOpener: UrlOpener) { + if (!urlOpener.openUrl(Constants.Urls.xHashtagApp)) { + urlOpener.openUrl(Constants.Urls.xHashtagWeb) } } } diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenYoutubeUseCase.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenYoutubeUseCase.kt index ac6ff5c1..d73006be 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenYoutubeUseCase.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/OpenYoutubeUseCase.kt @@ -1,16 +1,13 @@ package fr.androidmakers.domain.interactor -import fr.androidmakers.domain.PlatformContext import fr.androidmakers.domain.utils.Constants import fr.androidmakers.domain.utils.UrlOpener -class OpenYoutubeUseCase( - private val urlOpener: UrlOpener -) { - operator fun invoke(platformContext: PlatformContext) { +class OpenYoutubeUseCase() { + operator fun invoke(urlOpener: UrlOpener) { // Try to open the application first - if (!urlOpener.openUrl(platformContext, Constants.Urls.youtubeApp)) { - urlOpener.openUrl(platformContext, Constants.Urls.youtubeWeb) + if (!urlOpener.openUrl(Constants.Urls.youtubeApp)) { + urlOpener.openUrl(Constants.Urls.youtubeWeb) } } } diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/ShareSessionUseCase.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/ShareSessionUseCase.kt index 54a2becd..3cd2f722 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/ShareSessionUseCase.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/interactor/ShareSessionUseCase.kt @@ -7,7 +7,7 @@ import fr.androidmakers.domain.model.Speaker // TODO to be improved expect class ShareSessionUseCase { operator fun invoke( - platformContext: PlatformContext, + context: PlatformContext, session: Session, speakers: List, formattedDateAndRoom: String diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/utils/UrlOpener.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/utils/UrlOpener.kt index c294822b..739c6848 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/utils/UrlOpener.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/utils/UrlOpener.kt @@ -1,7 +1,5 @@ package fr.androidmakers.domain.utils -import fr.androidmakers.domain.PlatformContext - -expect class UrlOpener { - fun openUrl(platformContext: PlatformContext, url: String): Boolean +interface UrlOpener { + fun openUrl(url: String): Boolean } diff --git a/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/PlatformContext.ios.kt b/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/PlatformContext.ios.kt index f379e3f9..f327e2fb 100644 --- a/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/PlatformContext.ios.kt +++ b/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/PlatformContext.ios.kt @@ -1,3 +1,7 @@ package fr.androidmakers.domain -actual object PlatformContext +actual abstract class PlatformContext private constructor() { + companion object { + val INSTANCE = object : PlatformContext() {} + } +} diff --git a/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/interactor/OpenMapUseCase.ios.kt b/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/interactor/OpenMapUseCase.ios.kt index 145e339c..505af770 100644 --- a/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/interactor/OpenMapUseCase.ios.kt +++ b/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/interactor/OpenMapUseCase.ios.kt @@ -2,23 +2,13 @@ package fr.androidmakers.domain.interactor import fr.androidmakers.domain.PlatformContext import kotlinx.cinterop.ExperimentalForeignApi -import kotlinx.cinterop.NativePtr -import kotlinx.cinterop.cValuesOf -import kotlinx.cinterop.objcPtr -import platform.CoreLocation.CLGeocoder -import platform.CoreLocation.CLLocationCoordinate2D import platform.CoreLocation.CLLocationCoordinate2DMake -import platform.CoreLocation.CLLocationDegrees -import platform.Foundation.NSLocale -import platform.Foundation.NSNumberFormatter -import platform.Foundation.NSNumberFormatterDecimalStyle -import platform.Foundation.NSNumberFormatterStyle import platform.MapKit.MKMapItem import platform.MapKit.MKPlacemark actual class OpenMapUseCase { @OptIn(ExperimentalForeignApi::class) - actual operator fun invoke(platformContext: PlatformContext, coordinates: String, name: String) { + actual operator fun invoke(context: PlatformContext, coordinates: String, name: String) { val coordinateArray = coordinates.split(",") if (coordinateArray.size == 2) { val latitude = coordinateArray[0].toDoubleOrNull() diff --git a/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/interactor/ShareSessionUseCase.ios.kt b/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/interactor/ShareSessionUseCase.ios.kt index 397bcd10..b061d0d6 100644 --- a/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/interactor/ShareSessionUseCase.ios.kt +++ b/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/interactor/ShareSessionUseCase.ios.kt @@ -10,7 +10,7 @@ import platform.UIKit.UIApplication actual class ShareSessionUseCase { actual operator fun invoke( - platformContext: PlatformContext, + context: PlatformContext, session: Session, speakers: List, formattedDateAndRoom: String diff --git a/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/utils/UrlOpener.ios.kt b/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/utils/UrlOpener.ios.kt deleted file mode 100644 index 289dd176..00000000 --- a/shared/domain/src/iosMain/kotlin/fr/androidmakers/domain/utils/UrlOpener.ios.kt +++ /dev/null @@ -1,25 +0,0 @@ -package fr.androidmakers.domain.utils - -import fr.androidmakers.domain.PlatformContext -import platform.Foundation.NSURL -import platform.UIKit.UIApplication -import platform.darwin.dispatch_async -import platform.darwin.dispatch_get_main_queue - -actual class UrlOpener { - actual fun openUrl(platformContext: PlatformContext, url: String): Boolean { - val urlObj = NSURL(string = url) - return if (UIApplication.sharedApplication.canOpenURL(urlObj)) { - val application = UIApplication.sharedApplication - - application.openURL(url = urlObj, options = emptyMap()) { - if (!it) { - println("Could not open $url") - } - } - true - } else { - false - } - } -} diff --git a/shared/ui/src/androidMain/kotlin/com/androidmakers/ui/MainLayout.android.kt b/shared/ui/src/androidMain/kotlin/com/androidmakers/ui/MainLayout.android.kt index a9c085de..7dd16ad7 100644 --- a/shared/ui/src/androidMain/kotlin/com/androidmakers/ui/MainLayout.android.kt +++ b/shared/ui/src/androidMain/kotlin/com/androidmakers/ui/MainLayout.android.kt @@ -16,4 +16,4 @@ actual val defaultPopEnterTransition: EnterTransition = fadeIn() + scaleIn(initi actual val defaultPopExitTransition: ExitTransition = fadeOut() + scaleOut(targetScale = 0.9f) @Composable -actual fun getPlatformContext(): PlatformContext = PlatformContext(LocalContext.current) +actual fun getPlatformContext(): PlatformContext = LocalContext.current diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/di/ViewModelModule.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/di/ViewModelModule.kt index c3436704..3e656681 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/di/ViewModelModule.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/di/ViewModelModule.kt @@ -15,8 +15,8 @@ val viewModelModule = module { viewModelOf(::SpeakerListViewModel) viewModelOf(::SponsorsViewModel) viewModelOf(::VenueViewModel) - viewModel { (speakerId: String) -> SpeakerDetailsViewModel(speakerId, get(), get()) } + viewModel { (speakerId: String) -> SpeakerDetailsViewModel(speakerId, get()) } viewModelOf(::AgendaViewModel) - viewModel { (sessionId: String) -> SessionDetailViewModel(sessionId, get(), get(), get(), get(), get(), get(), get(), get()) } + viewModel { (sessionId: String) -> SessionDetailViewModel(sessionId, get(), get(), get(), get(), get(), get(), get()) } viewModelOf(::AboutViewModel) } diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/about/AboutScreen.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/about/AboutScreen.kt index 90e619f0..dc380c0b 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/about/AboutScreen.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/about/AboutScreen.kt @@ -25,9 +25,10 @@ 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.LocalUriHandler import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import com.androidmakers.ui.getPlatformContext +import com.androidmakers.ui.common.toUrlOpener import fr.paug.androidmakers.ui.Res import fr.paug.androidmakers.ui.about_android_makers import fr.paug.androidmakers.ui.code_of_conduct @@ -55,18 +56,18 @@ fun AboutScreen( .padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterVertically) ) { - val platformContext = getPlatformContext() + val urlOpener = LocalUriHandler.current.toUrlOpener() IntroCard( - onFaqClick = { viewModel.openFaq(platformContext) }, - onCocClick = { viewModel.openCoc(platformContext) } + onFaqClick = { viewModel.openFaq(urlOpener) }, + onCocClick = { viewModel.openCoc(urlOpener) } ) SocialCard( - { viewModel.openXHashtag(platformContext) }, - { viewModel.openBlueSkyAccount(platformContext) }, - { viewModel.openXAccount(platformContext) }, - { viewModel.openYoutube(platformContext) } + { viewModel.openXHashtag(urlOpener) }, + { viewModel.openBlueSkyAccount(urlOpener) }, + { viewModel.openXAccount(urlOpener) }, + { viewModel.openYoutube(urlOpener) } ) Text( @@ -86,7 +87,6 @@ private fun IntroCard( onFaqClick: () -> Unit, onCocClick: () -> Unit ) { - val darkMode = isSystemInDarkTheme() Column(Modifier.padding(vertical = 8.dp)) { Image( modifier = Modifier diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaLayout.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaLayout.kt index 2e1f0e43..071c8d33 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaLayout.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaLayout.kt @@ -27,12 +27,13 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.androidmakers.ui.common.EmojiUtils import com.androidmakers.ui.common.LceLayout import com.androidmakers.ui.common.SessionFilter -import com.androidmakers.ui.getPlatformContext +import com.androidmakers.ui.common.toUrlOpener import com.androidmakers.ui.model.AgendaState import com.androidmakers.ui.model.Lce import com.androidmakers.ui.model.UISession @@ -78,7 +79,7 @@ fun AgendaLayout( } }, content = { - val context = getPlatformContext() + val urlOpener = LocalUriHandler.current.toUrlOpener() AgendaPagerOrLoading( uiStateLce = uiStateLce, @@ -86,7 +87,7 @@ fun AgendaLayout( onRefresh = viewModel::refresh, sessionFilters = sessionFilters, onSessionClick = { onSessionClick(it.id) }, - onApplyForAppClinicClick = { viewModel.applyForAppClinic(context) }, + onApplyForAppClinicClick = { viewModel.applyForAppClinic(urlOpener) }, onSessionBookmark = viewModel::setSessionBookmark, ) } diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaViewModel.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaViewModel.kt index f4c29d54..821ee692 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaViewModel.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaViewModel.kt @@ -6,12 +6,12 @@ import com.androidmakers.ui.common.SessionFilter import com.androidmakers.ui.model.AgendaState import com.androidmakers.ui.model.Lce import com.androidmakers.ui.model.UISession -import fr.androidmakers.domain.PlatformContext import fr.androidmakers.domain.interactor.ApplyForAppClinicUseCase import fr.androidmakers.domain.interactor.GetAgendaUseCase import fr.androidmakers.domain.interactor.SetSessionBookmarkUseCase import fr.androidmakers.domain.model.Room import fr.androidmakers.domain.repo.BookmarksRepository +import fr.androidmakers.domain.utils.UrlOpener import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -57,7 +57,7 @@ class AgendaViewModel( setSessionBookmarkUseCase(uiSession.id, bookmark) } - fun applyForAppClinic(platformContext: PlatformContext) { - applyForAppClinicUseCase(platformContext) + fun applyForAppClinic(urlOpener: UrlOpener) { + applyForAppClinicUseCase(urlOpener) } } diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/SessionDetailLayout.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/SessionDetailLayout.kt index cb56a763..97c7ebd3 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/SessionDetailLayout.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/SessionDetailLayout.kt @@ -49,6 +49,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -57,6 +58,7 @@ import coil3.compose.AsyncImage import com.androidmakers.ui.common.EmojiUtils import com.androidmakers.ui.common.LoadingLayout import com.androidmakers.ui.common.separatorColor +import com.androidmakers.ui.common.toUrlOpener import com.androidmakers.ui.getPlatformContext import com.androidmakers.ui.model.Lce import com.androidmakers.ui.model.SessionDetailState @@ -90,7 +92,8 @@ fun SessionDetailScreen( onBackClick: () -> Unit, ) { val sessionDetailState by viewModel.sessionDetailState.collectAsState() - val platformContext = getPlatformContext() + val context = getPlatformContext() + val urlOpener = LocalUriHandler.current.toUrlOpener() SessionDetailLayout( sessionDetailState = sessionDetailState, @@ -99,13 +102,13 @@ fun SessionDetailScreen( viewModel.bookmark(it) }, onShareSession = { - viewModel.shareSession(platformContext) + viewModel.shareSession(context) }, onOpenLink = { - viewModel.openLink(platformContext, it) + viewModel.openLink(urlOpener, it) }, onApplyForAppClinic = { - viewModel.applyForAppClinic(platformContext) + viewModel.applyForAppClinic(urlOpener) } ) } diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/SessionDetailViewModel.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/SessionDetailViewModel.kt index 32618be0..4ae0d6d7 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/SessionDetailViewModel.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/SessionDetailViewModel.kt @@ -6,7 +6,6 @@ import com.androidmakers.ui.model.Lce import com.androidmakers.ui.model.SessionDetailState import fr.androidmakers.domain.PlatformContext import fr.androidmakers.domain.interactor.ApplyForAppClinicUseCase -import fr.androidmakers.domain.interactor.OpenLinkUseCase import fr.androidmakers.domain.interactor.SetSessionBookmarkUseCase import fr.androidmakers.domain.interactor.ShareSessionUseCase import fr.androidmakers.domain.model.SocialsItem @@ -14,6 +13,7 @@ import fr.androidmakers.domain.repo.BookmarksRepository import fr.androidmakers.domain.repo.RoomsRepository import fr.androidmakers.domain.repo.SessionsRepository import fr.androidmakers.domain.repo.SpeakersRepository +import fr.androidmakers.domain.utils.UrlOpener import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow @@ -34,7 +34,6 @@ class SessionDetailViewModel( private val speakersRepository: SpeakersRepository, private val setSessionBookmarkUseCase: SetSessionBookmarkUseCase, private val shareSessionUseCase: ShareSessionUseCase, - private val openLinkUseCase: OpenLinkUseCase, private val applyForAppClinicUseCase: ApplyForAppClinicUseCase, ) : ViewModel() { @@ -77,12 +76,12 @@ class SessionDetailViewModel( } } - fun shareSession(platformContext: PlatformContext) = viewModelScope.launch { + fun shareSession(context: PlatformContext) = viewModelScope.launch { val lce = sessionDetailState.first { it !is Lce.Loading } if (lce is Lce.Content) { val state = lce.content shareSessionUseCase( - platformContext = platformContext, + context = context, session = state.session, speakers = state.speakers, formattedDateAndRoom = state.formattedDateAndRoom @@ -90,11 +89,11 @@ class SessionDetailViewModel( } } - fun openLink(platformContext: PlatformContext, socialsItem: SocialsItem) { - socialsItem.url?.let { openLinkUseCase(platformContext, it) } + fun openLink(urlOpener: UrlOpener, socialsItem: SocialsItem) { + socialsItem.url?.let { urlOpener.openUrl(it) } } - fun applyForAppClinic(platformContext: PlatformContext) { - applyForAppClinicUseCase(platformContext) + fun applyForAppClinic(urlOpener: UrlOpener) { + applyForAppClinicUseCase(urlOpener) } } diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/common/UriHandlerExtensions.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/common/UriHandlerExtensions.kt new file mode 100644 index 00000000..ef60bfe0 --- /dev/null +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/common/UriHandlerExtensions.kt @@ -0,0 +1,18 @@ +package com.androidmakers.ui.common + +import androidx.compose.ui.platform.UriHandler +import fr.androidmakers.domain.utils.UrlOpener + +private class UriHandlerUrlOpener(private val uriHandler: UriHandler) : UrlOpener { + override fun openUrl(url: String): Boolean { + return try { + uriHandler.openUri(url) + true + } catch (e: IllegalArgumentException) { + e.printStackTrace() + false + } + } +} + +fun UriHandler.toUrlOpener(): UrlOpener = UriHandlerUrlOpener(this) diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/speakers/SpeakerDetailViewModel.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/speakers/SpeakerDetailViewModel.kt index f1153b13..74edfe7e 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/speakers/SpeakerDetailViewModel.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/speakers/SpeakerDetailViewModel.kt @@ -4,11 +4,10 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.androidmakers.ui.model.Lce import com.androidmakers.ui.model.toLce -import fr.androidmakers.domain.PlatformContext -import fr.androidmakers.domain.interactor.OpenLinkUseCase import fr.androidmakers.domain.model.SocialsItem import fr.androidmakers.domain.model.Speaker import fr.androidmakers.domain.repo.SpeakersRepository +import fr.androidmakers.domain.utils.UrlOpener import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map @@ -17,7 +16,6 @@ import kotlinx.coroutines.flow.stateIn class SpeakerDetailsViewModel( speakerId: String, speakersRepository: SpeakersRepository, - private val openLinkUseCase: OpenLinkUseCase, ) : ViewModel() { val uiState: StateFlow> = speakersRepository @@ -34,8 +32,8 @@ class SpeakerDetailsViewModel( initialValue = Lce.Loading ) - fun openSpeakerLink(platformContext: PlatformContext, socialsItem: SocialsItem) { - socialsItem.url?.let { openLinkUseCase(platformContext, it) } + fun openSpeakerLink(urlOpener: UrlOpener, socialsItem: SocialsItem) { + socialsItem.url?.let { urlOpener.openUrl(it) } } } diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/speakers/SpeakerDetailsScreen.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/speakers/SpeakerDetailsScreen.kt index ec5f4c35..531a9025 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/speakers/SpeakerDetailsScreen.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/speakers/SpeakerDetailsScreen.kt @@ -25,12 +25,13 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage import com.androidmakers.ui.common.LoadingLayout import com.androidmakers.ui.common.SocialButtons -import com.androidmakers.ui.getPlatformContext +import com.androidmakers.ui.common.toUrlOpener import com.androidmakers.ui.model.Lce import fr.androidmakers.domain.model.SocialsItem import fr.paug.androidmakers.ui.Res @@ -52,10 +53,10 @@ fun SpeakerDetailsRoute( } is Lce.Content -> { - val platformContext = getPlatformContext() + val urlOpener = LocalUriHandler.current.toUrlOpener() SpeakerDetailsScreen( uiState = state.content, - onSocialItemClick = { speakerDetailsViewModel.openSpeakerLink(platformContext, it) }, + onSocialItemClick = { speakerDetailsViewModel.openSpeakerLink(urlOpener, it) }, onBackClick = onBackClick ) } diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/sponsors/SponsorScreen.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/sponsors/SponsorScreen.kt index 5a9455b7..6fc8ef6f 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/sponsors/SponsorScreen.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/sponsors/SponsorScreen.kt @@ -18,10 +18,11 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage -import com.androidmakers.ui.getPlatformContext +import com.androidmakers.ui.common.toUrlOpener import com.androidmakers.ui.model.Lce import fr.androidmakers.domain.model.Partner import fr.androidmakers.domain.model.PartnerGroup @@ -31,11 +32,11 @@ import org.koin.compose.viewmodel.koinViewModel fun SponsorsScreen() { val viewModel = koinViewModel() val sponsors by viewModel.values.collectAsState() - val platformContext = getPlatformContext() + val urlOpener = LocalUriHandler.current.toUrlOpener() SponsorsView( partnerList = sponsors, - onSponsorClick = { viewModel.openPartnerLink(platformContext, it) } + onSponsorClick = { viewModel.openPartnerLink(urlOpener, it) } ) } diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/venue/VenuePager.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/venue/VenuePager.kt index dff2f505..8aef9c1f 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/venue/VenuePager.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/venue/VenuePager.kt @@ -94,11 +94,11 @@ fun VenuePager() { name = venue.name, coordinates = venue.coordinates, ) - val platformContext = getPlatformContext() + val context = getPlatformContext() VenueLayout( uiVenue = uiVenue, onClickOnMap = { - viewModel.openMapUseCase(platformContext, uiVenue.coordinates.orEmpty(), uiVenue.name) + viewModel.openMapUseCase(context, uiVenue.coordinates.orEmpty(), uiVenue.name) } ) } diff --git a/shared/ui/src/iosMain/kotlin/com/androidmakers/ui/MainLayout.ios.kt b/shared/ui/src/iosMain/kotlin/com/androidmakers/ui/MainLayout.ios.kt index e67cd6b5..00e6353d 100644 --- a/shared/ui/src/iosMain/kotlin/com/androidmakers/ui/MainLayout.ios.kt +++ b/shared/ui/src/iosMain/kotlin/com/androidmakers/ui/MainLayout.ios.kt @@ -13,4 +13,4 @@ actual val defaultPopEnterTransition: EnterTransition = slideInHorizontally(init actual val defaultPopExitTransition: ExitTransition = slideOutHorizontally(targetOffsetX = { it }) @Composable -actual fun getPlatformContext(): PlatformContext = PlatformContext +actual fun getPlatformContext(): PlatformContext = PlatformContext.INSTANCE