From 6509d918a62f6a966bfaa6285a75ca2f1b136019 Mon Sep 17 00:00:00 2001 From: DatLag Date: Tue, 19 Mar 2024 00:57:53 +0100 Subject: [PATCH] check if open as default is enabled --- .../dev/datlag/burningseries/MainActivity.kt | 14 +++++ .../shared/other/DomainVerifier.kt | 43 +++++++++++++++ .../home/component/DeviceContent.android.kt | 54 ++++++++++++++++++- .../commonMain/resources/MR/base/strings.xml | 5 ++ .../commonMain/resources/MR/de/strings.xml | 5 ++ 5 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 app/shared/src/androidMain/kotlin/dev/datlag/burningseries/shared/other/DomainVerifier.kt diff --git a/app/android/src/androidMain/kotlin/dev/datlag/burningseries/MainActivity.kt b/app/android/src/androidMain/kotlin/dev/datlag/burningseries/MainActivity.kt index ea904b2c..de8c759f 100644 --- a/app/android/src/androidMain/kotlin/dev/datlag/burningseries/MainActivity.kt +++ b/app/android/src/androidMain/kotlin/dev/datlag/burningseries/MainActivity.kt @@ -25,6 +25,7 @@ import dev.datlag.burningseries.model.common.safeCast import dev.datlag.burningseries.shared.App import dev.datlag.burningseries.shared.SharedRes import dev.datlag.burningseries.shared.common.lifecycle.LocalLifecycleOwner +import dev.datlag.burningseries.shared.other.DomainVerifier import dev.datlag.burningseries.shared.ui.* import dev.datlag.burningseries.shared.ui.custom.Permission import dev.datlag.burningseries.shared.ui.navigation.NavHostComponent @@ -63,6 +64,7 @@ class MainActivity : AppCompatActivity() { Kast.setup(this) SmallIcon = R.drawable.ic_launcher_foreground + DomainVerifier.verify(this) setContent { CompositionLocalProvider( @@ -119,6 +121,18 @@ class MainActivity : AppCompatActivity() { Kast.dispose() } + override fun onStart() { + super.onStart() + + DomainVerifier.verify(this) + } + + override fun onResume() { + super.onResume() + + DomainVerifier.verify(this) + } + override fun dispatchKeyEvent(event: KeyEvent?): Boolean { return (KeyEventDispatcher.invoke(event) ?: false) || super.dispatchKeyEvent(event) } diff --git a/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/shared/other/DomainVerifier.kt b/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/shared/other/DomainVerifier.kt new file mode 100644 index 00000000..f0f68efa --- /dev/null +++ b/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/shared/other/DomainVerifier.kt @@ -0,0 +1,43 @@ +package dev.datlag.burningseries.shared.other + +import android.content.Context +import android.content.Intent +import android.content.pm.verify.domain.DomainVerificationManager +import android.content.pm.verify.domain.DomainVerificationUserState +import android.net.Uri +import android.os.Build +import android.provider.Settings +import androidx.annotation.ChecksSdkIntAtLeast +import androidx.core.content.ContextCompat +import kotlinx.coroutines.flow.MutableStateFlow + +data object DomainVerifier { + + @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.S) + val supported: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S + val verified: MutableStateFlow = MutableStateFlow(false) + + @Suppress("NewApi") + fun verify(context: Context) { + if (supported) { + val manager = ContextCompat.getSystemService(context, DomainVerificationManager::class.java) + val userState = manager?.getDomainVerificationUserState(context.packageName) + val unapprovedDomains = userState?.hostToStateMap?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_NONE } + + unapprovedDomains?.let { count -> + verified.compareAndSet(false, count.isEmpty()) + } + } + } + + @Suppress("NewApi") + fun enable(context: Context) { + if (supported) { + val intent = Intent( + Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS, + Uri.parse("package:${context.packageName}") + ) + ContextCompat.startActivity(context, intent, null) + } + } +} \ No newline at end of file diff --git a/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.android.kt b/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.android.kt index 6ddcf11b..61eb42ec 100644 --- a/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.android.kt +++ b/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.android.kt @@ -4,17 +4,24 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.grid.LazyGridScope import androidx.compose.material3.* +import androidx.compose.runtime.SideEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import dev.datlag.burningseries.model.Release import dev.datlag.burningseries.shared.SharedRes import dev.datlag.burningseries.shared.common.header import dev.datlag.burningseries.shared.common.lifecycle.collectAsStateWithLifecycle import dev.datlag.burningseries.shared.common.openInBrowser +import dev.datlag.burningseries.shared.other.DomainVerifier +import dev.datlag.burningseries.shared.rememberIsTv import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.flow.StateFlow @@ -59,8 +66,51 @@ actual fun LazyGridScope.DeviceContent(release: StateFlow, onDeviceRea Text(text = stringResource(SharedRes.strings.github)) } } - } else if (!reachable) { - Text(text = stringResource(SharedRes.strings.enable_custom_dns)) + } else { + val context = LocalContext.current + val verified by DomainVerifier.verified.collectAsStateWithLifecycle() + + SideEffect { + DomainVerifier.verify(context) + } + + if (!rememberIsTv() && !verified && DomainVerifier.supported) { + Column( + modifier = Modifier.padding(top = 16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = stringResource(SharedRes.strings.open_domains_title), + style = MaterialTheme.typography.headlineLarge, + fontWeight = FontWeight.Bold + ) + Text( + text = buildAnnotatedString { + withStyle( + SpanStyle( + fontWeight = FontWeight.Bold + ) + ) { + append(stringResource(SharedRes.strings.open_domains_text_1)) + } + appendLine() + append(stringResource(SharedRes.strings.open_domains_text_2)) + appendLine() + append(stringResource(SharedRes.strings.open_domains_text_3)) + } + ) + Button( + modifier = Modifier.fillMaxWidth(), + onClick = { + DomainVerifier.enable(context) + } + ) { + Text(text = stringResource(SharedRes.strings.enable)) + } + } + } else if (!reachable) { + Text(text = stringResource(SharedRes.strings.enable_custom_dns)) + } } } } \ No newline at end of file diff --git a/app/shared/src/commonMain/resources/MR/base/strings.xml b/app/shared/src/commonMain/resources/MR/base/strings.xml index 5395b04e..e4594e9d 100644 --- a/app/shared/src/commonMain/resources/MR/base/strings.xml +++ b/app/shared/src/commonMain/resources/MR/base/strings.xml @@ -87,4 +87,9 @@ Gaming and E-Sport content AniFlow Sync your Anime watch progress with AniList or MyAnimeList. (Currently under development) + Enable + Open Links + You are not protected against fake domains right now! + Additionally you can view Burning-Series search results directly in this app then. + Make sure to check the option to open supported links and add every link below. \ No newline at end of file diff --git a/app/shared/src/commonMain/resources/MR/de/strings.xml b/app/shared/src/commonMain/resources/MR/de/strings.xml index 762d48c6..d6e6c96b 100644 --- a/app/shared/src/commonMain/resources/MR/de/strings.xml +++ b/app/shared/src/commonMain/resources/MR/de/strings.xml @@ -87,4 +87,9 @@ Gaming und E-Sport Infos AniFlow Synchronisier deinen Anime Fortschritt mit AniList oder MyAnimeList. (Momentan in der Entwicklung) + Aktivieren + Links öffnen + Du bist momentan nicht vor Fake-Seiten geschützt! + Zusätzlich kannst du dann Burning-Series Suchergebnisse in der App sehen. + Aktiviere einfach die Option unterstützte Links zu öffnen und füge diese darunter hinzu. \ No newline at end of file