diff --git a/app/src/main/kotlin/dev/aaa1115910/bv/activities/MainActivity.kt b/app/src/main/kotlin/dev/aaa1115910/bv/activities/MainActivity.kt index 2d43785a..2bba84ab 100644 --- a/app/src/main/kotlin/dev/aaa1115910/bv/activities/MainActivity.kt +++ b/app/src/main/kotlin/dev/aaa1115910/bv/activities/MainActivity.kt @@ -3,18 +3,42 @@ package dev.aaa1115910.bv.activities import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import dev.aaa1115910.bv.screen.HomeScreen +import dev.aaa1115910.bv.screen.RegionBlockScreen import dev.aaa1115910.bv.ui.theme.BVTheme +import dev.aaa1115910.bv.util.NetworkUtil +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { - installSplashScreen() + var keepSplashScreen = true + installSplashScreen().apply { + setKeepOnScreenCondition { keepSplashScreen } + } super.onCreate(savedInstanceState) + setContent { + val scope = rememberCoroutineScope() + var isMainlandChina by remember { mutableStateOf(false) } + + LaunchedEffect(Unit) { + scope.launch(Dispatchers.Default) { + isMainlandChina = NetworkUtil.isMainlandChina() + keepSplashScreen = false + } + } + BVTheme { - HomeScreen() + if (isMainlandChina) RegionBlockScreen() else HomeScreen() } } } diff --git a/app/src/main/kotlin/dev/aaa1115910/bv/component/Disclaimer.kt b/app/src/main/kotlin/dev/aaa1115910/bv/component/Disclaimer.kt deleted file mode 100644 index 91b6c471..00000000 --- a/app/src/main/kotlin/dev/aaa1115910/bv/component/Disclaimer.kt +++ /dev/null @@ -1,41 +0,0 @@ -package dev.aaa1115910.bv.component - -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.setValue -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import dev.aaa1115910.bv.R -import dev.burnoo.compose.rememberpreference.rememberBooleanPreference - -@Composable -fun Disclaimer() { - var show by rememberBooleanPreference( - keyName = "disclaimer", - initialValue = false, - defaultValue = true - ) - - if (show) { - AlertDialog( - title = { Text(text = stringResource(R.string.disclaimer_dialog_title)) }, - text = { - Text( - text = stringResource(R.string.disclaimer_dialog_text), - style = MaterialTheme.typography.bodyLarge, - textAlign = TextAlign.Center - ) - }, - onDismissRequest = { }, - confirmButton = { - TextButton(onClick = { show = false }) { - Text(text = stringResource(R.string.confirm)) - } - } - ) - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/dev/aaa1115910/bv/screen/RegionBlockScreen.kt b/app/src/main/kotlin/dev/aaa1115910/bv/screen/RegionBlockScreen.kt new file mode 100644 index 00000000..bf8bc3db --- /dev/null +++ b/app/src/main/kotlin/dev/aaa1115910/bv/screen/RegionBlockScreen.kt @@ -0,0 +1,129 @@ +package dev.aaa1115910.bv.screen + +import android.app.Activity +import android.graphics.BitmapFactory +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.ImageBitmapConfig +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import dev.aaa1115910.bv.R +import dev.aaa1115910.bv.ui.theme.BVTheme +import io.github.g0dkar.qrcode.QRCode +import io.github.g0dkar.qrcode.render.Colors +import okhttp3.internal.toHexString +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import kotlin.system.exitProcess + +@Composable +fun RegionBlockScreen( + modifier: Modifier = Modifier +) { + val context = LocalContext.current + var qrImage by remember { mutableStateOf(ImageBitmap(1, 1, ImageBitmapConfig.Argb8888)) } + val primaryColorHex = + "#" + MaterialTheme.colorScheme.primary.toArgb().toHexString().substring(2) + + LaunchedEffect(Unit) { + println(primaryColorHex) + val output = ByteArrayOutputStream() + QRCode("扫码也没有用的!") + .render(darkColor = Colors.css(primaryColorHex)) + .writeImage(output) + val input = ByteArrayInputStream(output.toByteArray()) + qrImage = BitmapFactory.decodeStream(input).asImageBitmap() + } + + DisposableEffect(key1 = Unit) { + onDispose { + (context as Activity).finish() + exitProcess(0) + } + } + + Surface( + modifier = modifier, + color = MaterialTheme.colorScheme.primary + ) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(84.dp), + contentAlignment = Alignment.CenterStart + ) { + Column( + verticalArrangement = Arrangement.spacedBy(24.dp) + ) { + Text( + text = stringResource(R.string.region_block_character_painting), + fontSize = 100.sp + ) + Column { + Text( + text = stringResource(R.string.region_block_title), + style = MaterialTheme.typography.titleLarge + ) + Text( + text = stringResource(R.string.region_block_subtitle), + style = MaterialTheme.typography.titleLarge + ) + } + Row( + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Box( + modifier = Modifier + .size(80.dp) + .background(Color.White), + contentAlignment = Alignment.Center + ) { + Image( + modifier = Modifier.size(64.dp), + bitmap = qrImage, + contentDescription = null + ) + } + Column { + Text(text = stringResource(R.string.region_block_solution_title)) + Text(text = stringResource(R.string.region_block_solution_text)) + } + } + } + } + } +} + +@Preview(device = "id:tv_1080p") +@Composable +private fun RegionBlockScreenPreview() { + BVTheme { + RegionBlockScreen() + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/dev/aaa1115910/bv/ui/theme/Theme.kt b/app/src/main/kotlin/dev/aaa1115910/bv/ui/theme/Theme.kt index 6b2c4df8..e1cc39ce 100644 --- a/app/src/main/kotlin/dev/aaa1115910/bv/ui/theme/Theme.kt +++ b/app/src/main/kotlin/dev/aaa1115910/bv/ui/theme/Theme.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat -import dev.aaa1115910.bv.component.Disclaimer import dev.aaa1115910.bv.component.FpsMonitor import dev.aaa1115910.bv.util.Prefs @@ -77,8 +76,6 @@ fun BVTheme( } else { content() } - - if (!view.isInEditMode) Disclaimer() } } } diff --git a/app/src/main/kotlin/dev/aaa1115910/bv/util/NetworkUtil.kt b/app/src/main/kotlin/dev/aaa1115910/bv/util/NetworkUtil.kt new file mode 100644 index 00000000..e563e34b --- /dev/null +++ b/app/src/main/kotlin/dev/aaa1115910/bv/util/NetworkUtil.kt @@ -0,0 +1,41 @@ +package dev.aaa1115910.bv.util + +import io.ktor.client.HttpClient +import io.ktor.client.engine.okhttp.OkHttp +import io.ktor.client.request.get +import io.ktor.client.statement.bodyAsText +import mu.KotlinLogging + +object NetworkUtil { + private lateinit var client: HttpClient + private const val LOC_CHECK_URL = "https://www.cloudflare.com/cdn-cgi/trace" + private val logger = KotlinLogging.logger { } + var networkCheckResult: Map = emptyMap() + + init { + createClient() + } + + private fun createClient() { + client = HttpClient(OkHttp) + } + + suspend fun isMainlandChina(): Boolean { + return runCatching { + val result = client.get(LOC_CHECK_URL).bodyAsText() + logger.info { "Network result:\n$result" } + + networkCheckResult = result + .lines() + .filter { it!="" } + .associate { + val splits = it.split("=") + splits[0] to splits[1] + } + + require(networkCheckResult["loc"] != "CN") { "BV doesn't support use in mainland China" } + + false + }.getOrDefault(true) + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d481a520..be335c7f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8,9 +8,6 @@ 刚刚 %1$d 分钟前 - 依据国家现行相关政策规定\n请确认在非互联网电视端使用 - 注意了! - 用户身份认证已失效,请重新登录 已加载 %1$d 条数据 @@ -38,6 +35,13 @@ 字幕底部间距 视频比例 视频编码 + 请先购买影片再进行观看\n不支持试看 + + :( + 不要在中国大陆地区使用该应用 + 该问题的解决方法就是: + 您无法在中国大陆区域使用 Bug Video + 不支持的使用地区 1080P 高清 1080P60 高帧率 @@ -88,8 +92,6 @@ 当前版本: %1$s 最新版本: %1$s - 请先购买影片再进行观看\n不支持试看 - 个人收藏 历史记录 登录