diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/AboutScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/AboutScreen.kt index c5381e1f9..1858181c5 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/AboutScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/AboutScreen.kt @@ -239,7 +239,7 @@ object AboutScreen : Screen() { } } - private fun getFormattedBuildTime(): String { + internal fun getFormattedBuildTime(): String { return try { val inputDf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.US) inputDf.timeZone = TimeZone.getTimeZone("UTC") diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/debug/DebugInfoScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/debug/DebugInfoScreen.kt index 0cd65d96f..807fa2107 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/debug/DebugInfoScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/debug/DebugInfoScreen.kt @@ -1,29 +1,133 @@ package eu.kanade.presentation.more.settings.screen.debug -import androidx.annotation.StringRes +import android.os.Build +import android.webkit.WebView import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.produceState +import androidx.compose.ui.platform.LocalContext +import androidx.profileinstaller.ProfileVerifier import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.more.settings.Preference -import eu.kanade.presentation.more.settings.screen.SearchableSettings +import eu.kanade.presentation.more.settings.PreferenceScaffold +import eu.kanade.presentation.more.settings.screen.AboutScreen +import eu.kanade.presentation.util.Screen import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.util.system.DeviceUtil +import kotlinx.coroutines.guava.await -object DebugInfoScreen : SearchableSettings { - @ReadOnlyComposable +object DebugInfoScreen : Screen() { @Composable - @StringRes - override fun getTitleRes() = R.string.pref_debug_info - - @Composable - override fun getPreferences(): List { + override fun Content() { val navigator = LocalNavigator.currentOrThrow + PreferenceScaffold( + titleRes = R.string.pref_debug_info, + onBackPressed = navigator::pop, + itemsProvider = { + listOf( + Preference.PreferenceItem.TextPreference( + title = WorkerInfoScreen.title, + onClick = { navigator.push(WorkerInfoScreen) }, + ), + getAppInfoGroup(), + getDeviceInfoGroup(), + ) + }, + ) + } - return listOf( - Preference.PreferenceItem.TextPreference( - title = WorkerInfoScreen.title, - onClick = { navigator.push(WorkerInfoScreen) }, + @Composable + private fun getAppInfoGroup(): Preference.PreferenceGroup { + return Preference.PreferenceGroup( + title = "App info", + preferenceItems = listOf( + Preference.PreferenceItem.TextPreference( + title = "Version", + subtitle = AboutScreen.getVersionName(false), + ), + Preference.PreferenceItem.TextPreference( + title = "Build time", + subtitle = AboutScreen.getFormattedBuildTime(), + ), + getProfileVerifierPreference(), + Preference.PreferenceItem.TextPreference( + title = "WebView version", + subtitle = getWebViewVersion(), + ), ), ) } + + @Composable + @ReadOnlyComposable + private fun getWebViewVersion(): String { + val webView = WebView.getCurrentWebViewPackage() ?: return "how did you get here?" + val pm = LocalContext.current.packageManager + val label = webView.applicationInfo.loadLabel(pm) + val version = webView.versionName + return "$label $version" + } + + @Composable + private fun getProfileVerifierPreference(): Preference.PreferenceItem.TextPreference { + val status by produceState(initialValue = "-") { + val result = ProfileVerifier.getCompilationStatusAsync().await().profileInstallResultCode + value = when (result) { + ProfileVerifier.CompilationStatus.RESULT_CODE_NO_PROFILE -> "No profile installed" + ProfileVerifier.CompilationStatus.RESULT_CODE_COMPILED_WITH_PROFILE -> "Compiled" + ProfileVerifier.CompilationStatus.RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING -> "Compiled non-matching" + ProfileVerifier.CompilationStatus.RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ, + ProfileVerifier.CompilationStatus.RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE, + ProfileVerifier.CompilationStatus.RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST, + -> "Error $result" + ProfileVerifier.CompilationStatus.RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION -> "Not supported" + ProfileVerifier.CompilationStatus.RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION -> "Pending compilation" + else -> "Unknown code $result" + } + } + return Preference.PreferenceItem.TextPreference( + title = "Profile compilation status", + subtitle = status, + ) + } + + private fun getDeviceInfoGroup(): Preference.PreferenceGroup { + val items = mutableListOf( + Preference.PreferenceItem.TextPreference( + title = "Model", + subtitle = "${Build.MANUFACTURER} ${Build.MODEL} (${Build.DEVICE})", + ), + ) + + if (DeviceUtil.oneUiVersion != null) { + items += Preference.PreferenceItem.TextPreference( + title = "OneUI version", + subtitle = "${DeviceUtil.oneUiVersion}", + ) + } else if (DeviceUtil.miuiMajorVersion != null) { + items += Preference.PreferenceItem.TextPreference( + title = "MIUI version", + subtitle = "${DeviceUtil.miuiMajorVersion}", + ) + } + + val androidVersion = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + Build.VERSION.RELEASE_OR_PREVIEW_DISPLAY + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + Build.VERSION.RELEASE_OR_CODENAME + } else { + Build.VERSION.RELEASE + } + items += Preference.PreferenceItem.TextPreference( + title = "Android version", + subtitle = "$androidVersion (${Build.DISPLAY})", + ) + + return Preference.PreferenceGroup( + title = "Device info", + preferenceItems = items, + ) + } } diff --git a/core/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt b/core/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt index 7f3f6eaaf..57950eda3 100644 --- a/core/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt @@ -14,15 +14,15 @@ object DeviceUtil { /** * Extracts the MIUI major version code from a string like "V12.5.3.0.QFGMIXM". * - * @return MIUI major version code (e.g., 13) or -1 if can't be parsed. + * @return MIUI major version code (e.g., 13) or null if can't be parsed. */ val miuiMajorVersion by lazy { - if (!isMiui) return@lazy -1 + if (!isMiui) return@lazy null Build.VERSION.INCREMENTAL .substringBefore('.') .trimStart('V') - .toIntOrNull() ?: -1 + .toIntOrNull() } @SuppressLint("PrivateApi") @@ -45,6 +45,20 @@ object DeviceUtil { Build.MANUFACTURER.equals("samsung", ignoreCase = true) } + val oneUiVersion by lazy { + try { + val semPlatformIntField = Build.VERSION::class.java.getDeclaredField("SEM_PLATFORM_INT") + val version = semPlatformIntField.getInt(null) - 90000 + if (version < 0) { + 1.0 + } else { + ((version / 10000).toString() + "." + version % 10000 / 100).toDouble() + } + } catch (e: Exception) { + null + } + } + val invalidDefaultBrowsers = listOf( "android", "com.huawei.android.internal.app", diff --git a/gradle/kotlinx.versions.toml b/gradle/kotlinx.versions.toml index b60b0ac03..17361bba1 100644 --- a/gradle/kotlinx.versions.toml +++ b/gradle/kotlinx.versions.toml @@ -10,6 +10,7 @@ gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = " coroutines-bom = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-bom", version = "1.6.4" } coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core" } coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android" } +coroutines-guava = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-guava" } serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization_version" } serialization-json-okio = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json-okio", version.ref = "serialization_version" } @@ -19,7 +20,7 @@ serialization-xml-core = { module = "io.github.pdvrieze.xmlutil:core-android", v serialization-xml = { module = "io.github.pdvrieze.xmlutil:serialization-android", version.ref = "xml_serialization_version" } [bundles] -coroutines = ["coroutines-core", "coroutines-android"] +coroutines = ["coroutines-core", "coroutines-android", "coroutines-guava"] serialization = ["serialization-json", "serialization-json-okio", "serialization-protobuf", "serialization-xml-core", "serialization-xml"] [plugins]