mirror of
https://github.com/null2264/yokai.git
synced 2025-07-17 22:36:55 +00:00
feat: Start using moko for i18n
This commit is contained in:
parent
872cc92c93
commit
6d531fbb5c
19 changed files with 171 additions and 44 deletions
|
@ -155,6 +155,7 @@ android {
|
|||
|
||||
dependencies {
|
||||
implementation(projects.core)
|
||||
implementation(projects.i18n)
|
||||
implementation(projects.sourceApi)
|
||||
|
||||
// Compose
|
||||
|
|
|
@ -17,7 +17,6 @@ import android.net.wifi.WifiManager
|
|||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import android.provider.Settings
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.ColorInt
|
||||
|
@ -103,30 +102,6 @@ fun Context.contextCompatDrawable(@DrawableRes resource: Int): Drawable? {
|
|||
return ContextCompat.getDrawable(this, resource)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts to dp.
|
||||
*/
|
||||
val Int.pxToDp: Int
|
||||
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
|
||||
|
||||
val Float.pxToDp: Float
|
||||
get() = (this / Resources.getSystem().displayMetrics.density)
|
||||
|
||||
/**
|
||||
* Converts to px.
|
||||
*/
|
||||
val Int.dpToPx: Int
|
||||
get() = this.toFloat().dpToPx.toInt()
|
||||
|
||||
val Int.spToPx: Int
|
||||
get() = this.toFloat().spToPx.toInt()
|
||||
|
||||
val Float.spToPx: Float
|
||||
get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this, Resources.getSystem().displayMetrics)
|
||||
|
||||
val Float.dpToPx: Float
|
||||
get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics)
|
||||
|
||||
/** Converts to px and takes into account LTR/RTL layout */
|
||||
fun Float.dpToPxEnd(resources: Resources): Float {
|
||||
return this * resources.displayMetrics.density * if (resources.isLTR) 1 else -1
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
package eu.kanade.tachiyomi.util.system
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.hardware.display.DisplayManager
|
||||
import android.os.Build
|
||||
import android.view.Display
|
||||
import android.view.Window
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import co.touchlab.kermit.Logger
|
||||
|
||||
|
||||
object DeviceUtil {
|
||||
|
||||
val isMiui by lazy {
|
||||
getSystemProperty("ro.miui.ui.version.name")?.isNotEmpty() ?: false
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the MIUI major version code from a string like "V12.5.3.0.QFGMIXM".
|
||||
*
|
||||
* @return MIUI major version code (e.g., 13) or null if can't be parsed.
|
||||
*/
|
||||
val miuiMajorVersion by lazy {
|
||||
if (!isMiui) return@lazy null
|
||||
|
||||
Build.VERSION.INCREMENTAL
|
||||
.substringBefore('.')
|
||||
.trimStart('V')
|
||||
.toIntOrNull()
|
||||
}
|
||||
|
||||
@SuppressLint("PrivateApi")
|
||||
fun isMiuiOptimizationDisabled(): Boolean {
|
||||
val sysProp = getSystemProperty("persist.sys.miui_optimization")
|
||||
if (sysProp == "0" || sysProp == "false") {
|
||||
return true
|
||||
}
|
||||
|
||||
return try {
|
||||
Class.forName("android.miui.AppOpsUtils")
|
||||
.getDeclaredMethod("isXOptMode")
|
||||
.invoke(null) as Boolean
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
val isSamsung by lazy {
|
||||
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",
|
||||
"com.zui.resolver",
|
||||
)
|
||||
|
||||
@SuppressLint("PrivateApi")
|
||||
private fun getSystemProperty(key: String?): String? {
|
||||
return try {
|
||||
Class.forName("android.os.SystemProperties")
|
||||
.getDeclaredMethod("get", String::class.java)
|
||||
.invoke(null, key) as String
|
||||
} catch (e: Exception) {
|
||||
Logger.w(e) { "Unable to use SystemProperties.get" }
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val isVivo by lazy {
|
||||
val prop = getSystemProperty("ro.vivo.os.name")
|
||||
!prop.isNullOrBlank() &&
|
||||
prop.contains("funtouch", true)
|
||||
}
|
||||
|
||||
fun setLegacyCutoutMode(window: Window, mode: LegacyCutoutMode) {
|
||||
when (mode) {
|
||||
LegacyCutoutMode.SHORT_EDGES -> {
|
||||
// Vivo doesn't support this, user had to set it from Settings
|
||||
/*
|
||||
if (isVivo) {
|
||||
}
|
||||
*/
|
||||
}
|
||||
LegacyCutoutMode.NEVER -> {
|
||||
// Vivo doesn't support this, user had to set it from Settings
|
||||
/*
|
||||
if (isVivo) {
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun hasCutout(context: Activity?): CutoutSupport {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (context?.getSystemService<DisplayManager>()
|
||||
?.getDisplay(Display.DEFAULT_DISPLAY)?.cutout != null)
|
||||
return CutoutSupport.EXTENDED
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
val displayCutout = context?.window?.decorView?.rootWindowInsets?.displayCutout
|
||||
if (displayCutout?.safeInsetTop != null || displayCutout?.safeInsetBottom != null)
|
||||
return CutoutSupport.MODERN
|
||||
} else if (isVivo) {
|
||||
// https://swsdl.vivo.com.cn/appstore/developer/uploadfile/20180328/20180328152252602.pdf
|
||||
try {
|
||||
@SuppressLint("PrivateApi")
|
||||
val ftFeature = context?.classLoader
|
||||
?.loadClass("android.util.FtFeature")
|
||||
val isFeatureSupportMethod = ftFeature?.getMethod(
|
||||
"isFeatureSupport",
|
||||
Int::class.javaPrimitiveType,
|
||||
)
|
||||
val isNotchOnScreen = 0x00000020
|
||||
val isSupported = isFeatureSupportMethod?.invoke(ftFeature, isNotchOnScreen) as Boolean
|
||||
if (isSupported) return CutoutSupport.LEGACY
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
} else if (isMiui) {
|
||||
try {
|
||||
@SuppressLint("PrivateApi")
|
||||
val sysProp = context?.classLoader?.loadClass("android.os.SystemProperties")
|
||||
val method = sysProp?.getMethod("getInt", String::class.java, Int::class.javaPrimitiveType)
|
||||
val rt = method?.invoke(sysProp, "ro.miui.notch", 0) as Int
|
||||
if (rt == 1) return CutoutSupport.LEGACY
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
return CutoutSupport.NONE
|
||||
}
|
||||
|
||||
fun getCutoutHeight(context: Activity?, cutoutSupport: CutoutSupport): Number {
|
||||
return when (cutoutSupport) {
|
||||
CutoutSupport.MODERN -> {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P)
|
||||
throw IllegalStateException("Modern cutout only available on Android P or higher")
|
||||
context?.window?.decorView?.rootWindowInsets?.displayCutout?.safeInsetTop ?: 0
|
||||
}
|
||||
CutoutSupport.EXTENDED -> {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
|
||||
throw IllegalStateException("Extended cutout only available on Android Q or higher")
|
||||
context?.window?.decorView?.rootWindowInsets?.displayCutout?.boundingRectTop?.height()?.toFloat() ?: 0f
|
||||
}
|
||||
CutoutSupport.LEGACY -> {
|
||||
if (isVivo) {
|
||||
val insetCompat = context?.window?.decorView?.rootWindowInsets?.let {
|
||||
WindowInsetsCompat.toWindowInsetsCompat(it)
|
||||
}
|
||||
val statusBarHeight = insetCompat?.getInsets(WindowInsetsCompat.Type.statusBars())?.top
|
||||
?: 24.dpToPx // 24dp is "standard" height for Android since Marshmallow
|
||||
var notchHeight = 32.dpToPx
|
||||
if (notchHeight < statusBarHeight) {
|
||||
notchHeight = statusBarHeight
|
||||
}
|
||||
notchHeight
|
||||
} else if (isMiui) {
|
||||
val resourceId = context?.resources?.getIdentifier("notch_height",
|
||||
"dimen", "android") ?: 0
|
||||
if (resourceId > 0) {
|
||||
context?.resources?.getDimensionPixelSize(resourceId) ?: 0
|
||||
} else {
|
||||
0
|
||||
}
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
|
||||
enum class CutoutSupport {
|
||||
NONE,
|
||||
LEGACY, // Pre-Android P, the start of this hell
|
||||
MODERN, // Android P
|
||||
EXTENDED, // Android Q
|
||||
}
|
||||
|
||||
enum class LegacyCutoutMode {
|
||||
SHORT_EDGES,
|
||||
NEVER,
|
||||
}
|
||||
}
|
|
@ -1116,12 +1116,6 @@
|
|||
<string name="file_picker_error">No file picker app found</string>
|
||||
<string name="file_picker_uri_permission_unsupported">Failed to acquire persistent folder access. The app may behave unexpectedly.</string>
|
||||
|
||||
<!-- Webview -->
|
||||
<string name="failed_to_bypass_cloudflare">Failed to bypass Cloudflare</string>
|
||||
<string name="please_update_webview">Please update the WebView app for better compatibility</string>
|
||||
<!-- Do not translate "WebView" -->
|
||||
<string name="webview_is_required">WebView is required for Tachiyomi</string>
|
||||
|
||||
<!-- App widget -->
|
||||
<string name="appwidget_updates_description">See your recently updated library entries</string>
|
||||
<string name="appwidget_unavailable_locked">Widget not available when app lock is enabled</string>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue