Step 2: Add the remaining dynamic manager configurations
This commit is contained in:
@@ -0,0 +1,264 @@
|
|||||||
|
package com.sukisu.ultra.ui.component
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.Security
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.sukisu.ultra.Natives
|
||||||
|
import com.sukisu.ultra.R
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import top.yukonga.miuix.kmp.basic.ButtonDefaults
|
||||||
|
import top.yukonga.miuix.kmp.basic.Card
|
||||||
|
import top.yukonga.miuix.kmp.basic.Icon
|
||||||
|
import top.yukonga.miuix.kmp.basic.Text
|
||||||
|
import top.yukonga.miuix.kmp.basic.TextButton
|
||||||
|
import top.yukonga.miuix.kmp.basic.TextField
|
||||||
|
import top.yukonga.miuix.kmp.extra.SuperArrow
|
||||||
|
import top.yukonga.miuix.kmp.extra.SuperDialog
|
||||||
|
import top.yukonga.miuix.kmp.extra.SuperSwitch
|
||||||
|
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun DynamicManagerCard() {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 12.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val prefs = remember { context.getSharedPreferences("settings", Context.MODE_PRIVATE) }
|
||||||
|
|
||||||
|
var isDynEnabled by rememberSaveable {
|
||||||
|
mutableStateOf(
|
||||||
|
Natives.getDynamicManager()?.isValid() == true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
var dynSize by rememberSaveable {
|
||||||
|
mutableStateOf(
|
||||||
|
Natives.getDynamicManager()?.size?.toString() ?: ""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
var dynHash by rememberSaveable {
|
||||||
|
mutableStateOf(
|
||||||
|
Natives.getDynamicManager()?.hash ?: ""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val showDynDialog = rememberSaveable { mutableStateOf(false) }
|
||||||
|
|
||||||
|
SuperArrow(
|
||||||
|
title = stringResource(R.string.dynamic_manager_title),
|
||||||
|
summary = if (isDynEnabled) {
|
||||||
|
stringResource(R.string.dynamic_manager_enabled_summary, dynSize)
|
||||||
|
} else {
|
||||||
|
stringResource(R.string.dynamic_manager_disabled)
|
||||||
|
},
|
||||||
|
leftAction = {
|
||||||
|
Icon(
|
||||||
|
Icons.Rounded.Security,
|
||||||
|
modifier = Modifier.padding(end = 16.dp),
|
||||||
|
contentDescription = stringResource(R.string.dynamic_manager_title),
|
||||||
|
tint = colorScheme.onBackground
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
showDynDialog.value = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
DynamicManagerDialog(
|
||||||
|
show = showDynDialog,
|
||||||
|
initialEnabled = isDynEnabled,
|
||||||
|
initialSize = dynSize,
|
||||||
|
initialHash = dynHash,
|
||||||
|
onConfirm = { enabled, size, hash ->
|
||||||
|
scope.launch(Dispatchers.IO) {
|
||||||
|
if (enabled) {
|
||||||
|
val newSize = try {
|
||||||
|
when {
|
||||||
|
size.startsWith("0x", true) ->
|
||||||
|
size.substring(2).toInt(16)
|
||||||
|
else -> size.toInt()
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
if (newSize <= 0 || hash.length != 64) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
android.widget.Toast.makeText(
|
||||||
|
context,
|
||||||
|
R.string.invalid_sign_config,
|
||||||
|
android.widget.Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
val ok = Natives.setDynamicManager(newSize, hash)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
if (ok) {
|
||||||
|
dynSize = size
|
||||||
|
dynHash = hash
|
||||||
|
isDynEnabled = true
|
||||||
|
prefs.edit().apply {
|
||||||
|
putBoolean("dm_enabled", true)
|
||||||
|
putString("dm_size", dynSize)
|
||||||
|
putString("dm_hash", dynHash)
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
android.widget.Toast.makeText(
|
||||||
|
context,
|
||||||
|
R.string.dynamic_manager_set_success,
|
||||||
|
android.widget.Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
} else {
|
||||||
|
android.widget.Toast.makeText(
|
||||||
|
context,
|
||||||
|
R.string.dynamic_manager_set_failed,
|
||||||
|
android.widget.Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val ok = Natives.clearDynamicManager()
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
if (ok) {
|
||||||
|
isDynEnabled = false
|
||||||
|
prefs.edit().apply {
|
||||||
|
putBoolean("dm_enabled", false)
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
android.widget.Toast.makeText(
|
||||||
|
context,
|
||||||
|
R.string.dynamic_manager_disabled_success,
|
||||||
|
android.widget.Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
} else {
|
||||||
|
android.widget.Toast.makeText(
|
||||||
|
context,
|
||||||
|
R.string.dynamic_manager_clear_failed,
|
||||||
|
android.widget.Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun DynamicManagerDialog(
|
||||||
|
show: MutableState<Boolean>,
|
||||||
|
initialEnabled: Boolean,
|
||||||
|
initialSize: String,
|
||||||
|
initialHash: String,
|
||||||
|
onConfirm: (enabled: Boolean, size: String, hash: String) -> Unit
|
||||||
|
) {
|
||||||
|
var tempDynEnabled by remember { mutableStateOf(initialEnabled) }
|
||||||
|
var tempDynSize by remember { mutableStateOf(initialSize) }
|
||||||
|
var tempDynHash by remember { mutableStateOf(initialHash) }
|
||||||
|
|
||||||
|
if (show.value) {
|
||||||
|
tempDynEnabled = initialEnabled
|
||||||
|
tempDynSize = initialSize
|
||||||
|
tempDynHash = initialHash
|
||||||
|
}
|
||||||
|
|
||||||
|
SuperDialog(
|
||||||
|
title = stringResource(R.string.dynamic_manager_title),
|
||||||
|
show = show,
|
||||||
|
onDismissRequest = {
|
||||||
|
show.value = false
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(bottom = 16.dp)
|
||||||
|
) {
|
||||||
|
SuperSwitch(
|
||||||
|
title = stringResource(R.string.enable_dynamic_manager),
|
||||||
|
checked = tempDynEnabled,
|
||||||
|
onCheckedChange = { tempDynEnabled = it }
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
|
||||||
|
TextField(
|
||||||
|
value = tempDynSize,
|
||||||
|
onValueChange = { value ->
|
||||||
|
// 只允许输入十六进制字符
|
||||||
|
if (value.all { it in "0123456789xXaAbBcCdDeEfF" }) {
|
||||||
|
tempDynSize = value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label = stringResource(R.string.signature_size),
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 8.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
TextField(
|
||||||
|
value = tempDynHash,
|
||||||
|
onValueChange = { value ->
|
||||||
|
// 只允许输入十六进制字符,最多64个
|
||||||
|
if (value.all { it in "0123456789aAbBcCdDeEfF" } && value.length <= 64) {
|
||||||
|
tempDynHash = value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label = stringResource(R.string.signature_hash),
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 8.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "${tempDynHash.length} / 64",
|
||||||
|
modifier = Modifier.padding(start = 12.dp, top = 4.dp),
|
||||||
|
color = colorScheme.onSurfaceVariantSummary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
TextButton(
|
||||||
|
text = stringResource(android.R.string.cancel),
|
||||||
|
onClick = {
|
||||||
|
show.value = false
|
||||||
|
},
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
Spacer(Modifier.width(20.dp))
|
||||||
|
TextButton(
|
||||||
|
text = stringResource(android.R.string.ok),
|
||||||
|
onClick = {
|
||||||
|
show.value = false
|
||||||
|
onConfirm(tempDynEnabled, tempDynSize.trim(), tempDynHash.trim())
|
||||||
|
},
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
colors = ButtonDefaults.textButtonColorsPrimary()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ package com.sukisu.ultra.ui.screen
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Process.myUid
|
|
||||||
import android.system.Os
|
import android.system.Os
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
@@ -649,7 +648,7 @@ private fun InfoCard() {
|
|||||||
val dynamicValid = remember { Natives.getDynamicManager()?.isValid() == true }
|
val dynamicValid = remember { Natives.getDynamicManager()?.isValid() == true }
|
||||||
if (dynamicValid && managersList != null) {
|
if (dynamicValid && managersList != null) {
|
||||||
val signatureMap = managersList.managers.groupBy { it.signatureIndex }
|
val signatureMap = managersList.managers.groupBy { it.signatureIndex }
|
||||||
val showDetailed = signatureMap.size > 1 || signatureMap.keys.firstOrNull() != 0
|
val showDetailed = signatureMap.isNotEmpty() || signatureMap.keys.firstOrNull() != 0
|
||||||
if (showDetailed) {
|
if (showDetailed) {
|
||||||
val managersText = buildString {
|
val managersText = buildString {
|
||||||
signatureMap.toSortedMap().forEach { (idx, list) ->
|
signatureMap.toSortedMap().forEach { (idx, list) ->
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.sukisu.ultra.ui.screen
|
package com.sukisu.ultra.ui.screen
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
@@ -11,6 +13,7 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.only
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.systemBars
|
import androidx.compose.foundation.layout.systemBars
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.rounded.Adb
|
import androidx.compose.material.icons.rounded.Adb
|
||||||
@@ -25,13 +28,16 @@ import androidx.compose.material.icons.rounded.FolderDelete
|
|||||||
import androidx.compose.material.icons.rounded.RemoveCircle
|
import androidx.compose.material.icons.rounded.RemoveCircle
|
||||||
import androidx.compose.material.icons.rounded.RemoveModerator
|
import androidx.compose.material.icons.rounded.RemoveModerator
|
||||||
import androidx.compose.material.icons.rounded.RestartAlt
|
import androidx.compose.material.icons.rounded.RestartAlt
|
||||||
|
import androidx.compose.material.icons.rounded.Security
|
||||||
import androidx.compose.material.icons.rounded.Update
|
import androidx.compose.material.icons.rounded.Update
|
||||||
import androidx.compose.material.icons.rounded.UploadFile
|
import androidx.compose.material.icons.rounded.UploadFile
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -56,18 +62,27 @@ import dev.chrisbanes.haze.hazeEffect
|
|||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import com.sukisu.ultra.Natives
|
import com.sukisu.ultra.Natives
|
||||||
import com.sukisu.ultra.R
|
import com.sukisu.ultra.R
|
||||||
|
import com.sukisu.ultra.ui.component.DynamicManagerCard
|
||||||
import com.sukisu.ultra.ui.component.KsuIsValid
|
import com.sukisu.ultra.ui.component.KsuIsValid
|
||||||
import com.sukisu.ultra.ui.component.SendLogDialog
|
import com.sukisu.ultra.ui.component.SendLogDialog
|
||||||
import com.sukisu.ultra.ui.component.SuperDropdown
|
import com.sukisu.ultra.ui.component.SuperDropdown
|
||||||
import com.sukisu.ultra.ui.component.UninstallDialog
|
import com.sukisu.ultra.ui.component.UninstallDialog
|
||||||
import com.sukisu.ultra.ui.component.rememberLoadingDialog
|
import com.sukisu.ultra.ui.component.rememberLoadingDialog
|
||||||
import com.sukisu.ultra.ui.util.execKsud
|
import com.sukisu.ultra.ui.util.execKsud
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import top.yukonga.miuix.kmp.basic.ButtonDefaults
|
||||||
import top.yukonga.miuix.kmp.basic.Card
|
import top.yukonga.miuix.kmp.basic.Card
|
||||||
import top.yukonga.miuix.kmp.basic.Icon
|
import top.yukonga.miuix.kmp.basic.Icon
|
||||||
import top.yukonga.miuix.kmp.basic.MiuixScrollBehavior
|
import top.yukonga.miuix.kmp.basic.MiuixScrollBehavior
|
||||||
import top.yukonga.miuix.kmp.basic.Scaffold
|
import top.yukonga.miuix.kmp.basic.Scaffold
|
||||||
|
import top.yukonga.miuix.kmp.basic.Text
|
||||||
|
import top.yukonga.miuix.kmp.basic.TextButton
|
||||||
|
import top.yukonga.miuix.kmp.basic.TextField
|
||||||
import top.yukonga.miuix.kmp.basic.TopAppBar
|
import top.yukonga.miuix.kmp.basic.TopAppBar
|
||||||
import top.yukonga.miuix.kmp.extra.SuperArrow
|
import top.yukonga.miuix.kmp.extra.SuperArrow
|
||||||
|
import top.yukonga.miuix.kmp.extra.SuperDialog
|
||||||
import top.yukonga.miuix.kmp.extra.SuperSwitch
|
import top.yukonga.miuix.kmp.extra.SuperSwitch
|
||||||
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
||||||
import top.yukonga.miuix.kmp.utils.getWindowSize
|
import top.yukonga.miuix.kmp.utils.getWindowSize
|
||||||
@@ -475,13 +490,17 @@ fun SettingPager(
|
|||||||
}
|
}
|
||||||
|
|
||||||
KsuIsValid {
|
KsuIsValid {
|
||||||
Card(
|
DynamicManagerCard()
|
||||||
modifier = Modifier
|
}
|
||||||
.padding(top = 12.dp)
|
|
||||||
.fillMaxWidth(),
|
KsuIsValid {
|
||||||
) {
|
val lkmMode = Natives.isLkmMode
|
||||||
val lkmMode = Natives.isLkmMode
|
if (lkmMode) {
|
||||||
if (lkmMode) {
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 12.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
) {
|
||||||
val uninstall = stringResource(id = R.string.settings_uninstall)
|
val uninstall = stringResource(id = R.string.settings_uninstall)
|
||||||
SuperArrow(
|
SuperArrow(
|
||||||
title = uninstall,
|
title = uninstall,
|
||||||
|
|||||||
@@ -193,4 +193,17 @@
|
|||||||
<string name="log_viewer_settings">设置</string>
|
<string name="log_viewer_settings">设置</string>
|
||||||
<string name="log_viewer_collapse">收起</string>
|
<string name="log_viewer_collapse">收起</string>
|
||||||
<string name="log_viewer_expand">展开</string>
|
<string name="log_viewer_expand">展开</string>
|
||||||
|
<!-- dynamic Manager -->
|
||||||
|
<string name="dynamic_manager_title">动态管理器配置</string>
|
||||||
|
<string name="dynamic_manager_enabled_summary">启用(大小:%s)</string>
|
||||||
|
<string name="dynamic_manager_disabled">已禁用</string>
|
||||||
|
<string name="enable_dynamic_manager">启用动态管理器</string>
|
||||||
|
<string name="signature_size">动态管理器签名大小</string>
|
||||||
|
<string name="signature_hash">动态管理器签名哈希</string>
|
||||||
|
<string name="hash_must_be_64_chars">哈希必须是 64 个 16 进制字符</string>
|
||||||
|
<string name="dynamic_manager_set_success">动态管理器配置设置成功</string>
|
||||||
|
<string name="dynamic_manager_set_failed">设置动态管理器配置失败</string>
|
||||||
|
<string name="invalid_sign_config">无效的管理器配置</string>
|
||||||
|
<string name="dynamic_manager_disabled_success">动态管理器已禁用</string>
|
||||||
|
<string name="dynamic_manager_clear_failed">清空动态管理器配置失败</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -195,4 +195,17 @@
|
|||||||
<string name="log_viewer_settings">Settings</string>
|
<string name="log_viewer_settings">Settings</string>
|
||||||
<string name="log_viewer_collapse">Collapse</string>
|
<string name="log_viewer_collapse">Collapse</string>
|
||||||
<string name="log_viewer_expand">Expand</string>
|
<string name="log_viewer_expand">Expand</string>
|
||||||
|
<!-- dynamic Manager -->
|
||||||
|
<string name="dynamic_manager_title">Dynamic Manager Configuration</string>
|
||||||
|
<string name="dynamic_manager_enabled_summary">Enabled (Size: %s)</string>
|
||||||
|
<string name="dynamic_manager_disabled">Disabled</string>
|
||||||
|
<string name="enable_dynamic_manager">Enable Dynamic Manager</string>
|
||||||
|
<string name="signature_size">Dynamic Manager Signature Size</string>
|
||||||
|
<string name="signature_hash">Dynamic Manager Signature Hash</string>
|
||||||
|
<string name="hash_must_be_64_chars">Hash must be 64 hexadecimal characters</string>
|
||||||
|
<string name="dynamic_manager_set_success">Dynamic Manager configuration set successfully</string>
|
||||||
|
<string name="dynamic_manager_set_failed">Failed to set dynamic Manager configuration</string>
|
||||||
|
<string name="invalid_sign_config">Invalid Manager configuration</string>
|
||||||
|
<string name="dynamic_manager_disabled_success">Dynamic Manager disabled</string>
|
||||||
|
<string name="dynamic_manager_clear_failed">Failed to clear dynamic Manager</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user