refactor(ui): 統一介面風格並優化佈局
- Home:重新整理資訊卡,將 StringBuilder 替換為 Composables;修正填充和 HtmlText 參數錯誤。 - Manager:為 TabRow 添加動畫指示器並統一頁面間距。 - Settings:為 KeyStore 對話框添加垂直滾動功能,以防止在小螢幕上出現裁剪。 - Repo:改善「即將推出」的 UI,增添圖標。
This commit is contained in:
parent
f215471400
commit
f14f65d078
2
core
2
core
|
|
@ -1 +1 @@
|
|||
Subproject commit f8c4b6c5a52e6fe07d288d96f3765fd18aaa928c
|
||||
Subproject commit 34f12244c931941420d011fbffb1858c8c045c1f
|
||||
|
|
@ -15,9 +15,9 @@ enum class BottomBarDestination(
|
|||
val iconSelected: ImageVector,
|
||||
val iconNotSelected: ImageVector
|
||||
) {
|
||||
Repo(RepoScreenDestination, R.string.screen_repo, Icons.Filled.GetApp, Icons.Outlined.GetApp),
|
||||
Home(HomeScreenDestination, R.string.screen_home, Icons.Filled.Home, Icons.Outlined.Home),
|
||||
Manage(ManageScreenDestination, R.string.screen_manage, Icons.Filled.Dashboard, Icons.Outlined.Dashboard),
|
||||
Home(HomeScreenDestination, R.string.app_name, Icons.Filled.Home, Icons.Outlined.Home),
|
||||
Repo(RepoScreenDestination, R.string.screen_repo, Icons.Filled.GetApp, Icons.Outlined.GetApp),
|
||||
Logs(LogsScreenDestination, R.string.screen_logs, Icons.Filled.Assignment, Icons.Outlined.Assignment),
|
||||
Settings(SettingsScreenDestination, R.string.screen_settings, Icons.Filled.Settings, Icons.Outlined.Settings);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,23 +13,19 @@ import androidx.compose.foundation.rememberScrollState
|
|||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.CheckCircle
|
||||
import androidx.compose.material.icons.outlined.ContentCopy
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.material.icons.outlined.Warning
|
||||
import androidx.compose.material3.*
|
||||
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.rememberCoroutineScope
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.annotation.RootNavGraph
|
||||
|
|
@ -50,7 +46,6 @@ import rikka.shizuku.Shizuku
|
|||
@Destination
|
||||
@Composable
|
||||
fun HomeScreen(navigator: DestinationsNavigator) {
|
||||
// Install from intent
|
||||
var isIntentLaunched by rememberSaveable { mutableStateOf(false) }
|
||||
val activity = LocalContext.current as Activity
|
||||
val intent = activity.intent
|
||||
|
|
@ -76,14 +71,15 @@ fun HomeScreen(navigator: DestinationsNavigator) {
|
|||
Column(
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.padding(horizontal = 16.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
ShizukuCard()
|
||||
InfoCard()
|
||||
SupportCard()
|
||||
Spacer(Modifier)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -92,7 +88,6 @@ private val listener: (Int, Int) -> Unit = { _, grantResult ->
|
|||
ShizukuApi.isPermissionGranted = grantResult == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun ShizukuCard() {
|
||||
LaunchedEffect(Unit) {
|
||||
|
|
@ -104,11 +99,21 @@ private fun ShizukuCard() {
|
|||
}
|
||||
}
|
||||
|
||||
ElevatedCard(
|
||||
colors = CardDefaults.elevatedCardColors(containerColor = run {
|
||||
if (ShizukuApi.isPermissionGranted) MaterialTheme.colorScheme.secondaryContainer
|
||||
else MaterialTheme.colorScheme.errorContainer
|
||||
})
|
||||
val containerColor = if (ShizukuApi.isPermissionGranted) {
|
||||
MaterialTheme.colorScheme.secondaryContainer
|
||||
} else {
|
||||
MaterialTheme.colorScheme.errorContainer
|
||||
}
|
||||
|
||||
val contentColor = if (ShizukuApi.isPermissionGranted) {
|
||||
MaterialTheme.colorScheme.onSecondaryContainer
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onErrorContainer
|
||||
}
|
||||
|
||||
Card(
|
||||
colors = CardDefaults.cardColors(containerColor = containerColor),
|
||||
modifier = Modifier.clip(CardDefaults.shape)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
|
|
@ -118,126 +123,148 @@ private fun ShizukuCard() {
|
|||
Shizuku.requestPermission(114514)
|
||||
}
|
||||
}
|
||||
.padding(24.dp),
|
||||
.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
if (ShizukuApi.isPermissionGranted) {
|
||||
Icon(Icons.Outlined.CheckCircle, stringResource(R.string.shizuku_available))
|
||||
Column(Modifier.padding(start = 20.dp)) {
|
||||
Text(
|
||||
text = stringResource(R.string.shizuku_available),
|
||||
fontFamily = FontFamily.Serif,
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
Icon(
|
||||
imageVector = if (ShizukuApi.isPermissionGranted) Icons.Outlined.CheckCircle else Icons.Outlined.Warning,
|
||||
contentDescription = null,
|
||||
tint = contentColor,
|
||||
modifier = Modifier.size(40.dp)
|
||||
)
|
||||
Spacer(Modifier.height(4.dp))
|
||||
Spacer(modifier = Modifier.width(16.dp))
|
||||
Column {
|
||||
Text(
|
||||
text = "API " + Shizuku.getVersion(),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
text = stringResource(if (ShizukuApi.isPermissionGranted) R.string.shizuku_available else R.string.shizuku_unavailable),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = contentColor
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Icon(Icons.Outlined.Warning, stringResource(R.string.shizuku_unavailable))
|
||||
Column(Modifier.padding(start = 20.dp)) {
|
||||
Text(
|
||||
text = stringResource(R.string.shizuku_unavailable),
|
||||
fontFamily = FontFamily.Serif,
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
text = if (ShizukuApi.isPermissionGranted) "API ${Shizuku.getVersion()}" else stringResource(R.string.home_shizuku_warning),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = contentColor.copy(alpha = 0.8f)
|
||||
)
|
||||
Spacer(Modifier.height(4.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.home_shizuku_warning),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val apiVersion = if (Build.VERSION.PREVIEW_SDK_INT != 0) {
|
||||
"${Build.VERSION.CODENAME} Preview (API ${Build.VERSION.PREVIEW_SDK_INT})"
|
||||
} else {
|
||||
"${Build.VERSION.RELEASE} (API ${Build.VERSION.SDK_INT})"
|
||||
}
|
||||
|
||||
private val device = buildString {
|
||||
append(Build.MANUFACTURER[0].uppercaseChar().toString() + Build.MANUFACTURER.substring(1))
|
||||
if (Build.BRAND != Build.MANUFACTURER) {
|
||||
append(" " + Build.BRAND[0].uppercaseChar() + Build.BRAND.substring(1))
|
||||
}
|
||||
append(" " + Build.MODEL + " ")
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun InfoCard() {
|
||||
val context = LocalContext.current
|
||||
val snackbarHost = LocalSnackbarHost.current
|
||||
val scope = rememberCoroutineScope()
|
||||
ElevatedCard {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 24.dp, top = 24.dp, end = 24.dp, bottom = 16.dp)
|
||||
) {
|
||||
val contents = StringBuilder()
|
||||
val infoCardContent: @Composable (Pair<String, String>) -> Unit = { texts ->
|
||||
contents.appendLine(texts.first).appendLine(texts.second).appendLine()
|
||||
Text(text = texts.first, style = MaterialTheme.typography.bodyLarge)
|
||||
Text(text = texts.second, style = MaterialTheme.typography.bodyMedium)
|
||||
|
||||
val apiVersion = if (Build.VERSION.PREVIEW_SDK_INT != 0) {
|
||||
"${Build.VERSION.CODENAME} Preview (API ${Build.VERSION.PREVIEW_SDK_INT})"
|
||||
} else {
|
||||
"${Build.VERSION.RELEASE} (API ${Build.VERSION.SDK_INT})"
|
||||
}
|
||||
|
||||
infoCardContent(stringResource(R.string.home_api_version) to "${LSPConfig.instance.API_CODE}")
|
||||
val deviceName = buildString {
|
||||
append(Build.MANUFACTURER.replaceFirstChar { it.uppercase() })
|
||||
if (Build.BRAND != Build.MANUFACTURER) {
|
||||
append(" " + Build.BRAND.replaceFirstChar { it.uppercase() })
|
||||
}
|
||||
append(" " + Build.MODEL)
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(24.dp))
|
||||
infoCardContent(stringResource(R.string.home_npatch_version) to LSPConfig.instance.VERSION_NAME + " (${LSPConfig.instance.VERSION_CODE})")
|
||||
|
||||
Spacer(Modifier.height(24.dp))
|
||||
infoCardContent(stringResource(R.string.home_framework_version) to LSPConfig.instance.CORE_VERSION_NAME + " (${LSPConfig.instance.CORE_VERSION_CODE})")
|
||||
|
||||
Spacer(Modifier.height(24.dp))
|
||||
infoCardContent(stringResource(R.string.home_system_version) to apiVersion)
|
||||
|
||||
Spacer(Modifier.height(24.dp))
|
||||
infoCardContent(stringResource(R.string.home_device) to device)
|
||||
|
||||
Spacer(Modifier.height(24.dp))
|
||||
infoCardContent(stringResource(R.string.home_system_abi) to Build.SUPPORTED_ABIS[0])
|
||||
|
||||
val copiedMessage = stringResource(R.string.home_info_copied)
|
||||
TextButton(
|
||||
modifier = Modifier.align(Alignment.End),
|
||||
onClick = {
|
||||
val cm = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
cm.setPrimaryClip(ClipData.newPlainText("NPatch", contents.toString()))
|
||||
scope.launch { snackbarHost.showSnackbar(copiedMessage) }
|
||||
},
|
||||
content = { Text(stringResource(android.R.string.copy)) }
|
||||
val infoList = listOf(
|
||||
stringResource(R.string.home_api_version) to "${LSPConfig.instance.API_CODE}",
|
||||
stringResource(R.string.home_npatch_version) to "${LSPConfig.instance.VERSION_NAME} (${LSPConfig.instance.VERSION_CODE})",
|
||||
stringResource(R.string.home_framework_version) to "${LSPConfig.instance.CORE_VERSION_NAME} (${LSPConfig.instance.CORE_VERSION_CODE})",
|
||||
stringResource(R.string.home_system_version) to apiVersion,
|
||||
stringResource(R.string.home_device) to deviceName,
|
||||
stringResource(R.string.home_system_abi) to Build.SUPPORTED_ABIS[0]
|
||||
)
|
||||
|
||||
val copySuccessMessage = stringResource(R.string.home_info_copied)
|
||||
|
||||
ElevatedCard {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||
.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.home_device_info),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
IconButton(onClick = {
|
||||
val contentString = infoList.joinToString("\n") { "${it.first}: ${it.second}" }
|
||||
val cm = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
cm.setPrimaryClip(ClipData.newPlainText("NPatch Info", contentString))
|
||||
scope.launch { snackbarHost.showSnackbar(copySuccessMessage) }
|
||||
}) {
|
||||
Icon(Icons.Outlined.ContentCopy, contentDescription = "Copy")
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f))
|
||||
|
||||
Column(modifier = Modifier.padding(vertical = 8.dp)) {
|
||||
infoList.forEach { (label, value) ->
|
||||
InfoRow(label, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Preview
|
||||
@Composable
|
||||
private fun InfoRow(label: String, value: String) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 6.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Text(
|
||||
text = value,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SupportCard() {
|
||||
ElevatedCard {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(24.dp)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(Icons.Outlined.Info, contentDescription = null, tint = MaterialTheme.colorScheme.primary)
|
||||
Spacer(Modifier.width(8.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.home_support),
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.SemiBold
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Text(
|
||||
modifier = Modifier.padding(vertical = 8.dp),
|
||||
text = stringResource(R.string.home_description),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Spacer(Modifier.height(12.dp))
|
||||
HtmlText(
|
||||
stringResource(
|
||||
R.string.home_view_source_code,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
package org.lsposed.npatch.ui.page
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||
import com.google.accompanist.pager.HorizontalPager
|
||||
|
|
@ -32,37 +34,51 @@ fun ManageScreen(
|
|||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val pagerState = rememberPagerState()
|
||||
val tabTitles = listOf(stringResource(R.string.apps), stringResource(R.string.modules))
|
||||
|
||||
Scaffold(
|
||||
topBar = { CenterTopBar(stringResource(BottomBarDestination.Manage.label)) },
|
||||
floatingActionButton = { if (pagerState.currentPage == 0) AppManageFab(navigator) }
|
||||
floatingActionButton = {
|
||||
if (pagerState.currentPage == 0) AppManageFab(navigator)
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box(Modifier.padding(innerPadding)) {
|
||||
Column {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
TabRow(
|
||||
contentColor = MaterialTheme.colorScheme.secondary,
|
||||
selectedTabIndex = pagerState.currentPage
|
||||
) {
|
||||
Tab(
|
||||
selected = pagerState.currentPage == 0,
|
||||
onClick = { scope.launch { pagerState.animateScrollToPage(0) } }
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(vertical = 16.dp),
|
||||
text = stringResource(R.string.apps)
|
||||
selectedTabIndex = pagerState.currentPage,
|
||||
containerColor = MaterialTheme.colorScheme.surface,
|
||||
contentColor = MaterialTheme.colorScheme.primary,
|
||||
indicator = { tabPositions ->
|
||||
TabRowDefaults.Indicator(
|
||||
Modifier.tabIndicatorOffset(tabPositions[pagerState.currentPage])
|
||||
)
|
||||
}
|
||||
Tab(
|
||||
selected = pagerState.currentPage == 1,
|
||||
onClick = { scope.launch { pagerState.animateScrollToPage(1) } }
|
||||
) {
|
||||
tabTitles.forEachIndexed { index, title ->
|
||||
val selected = pagerState.currentPage == index
|
||||
Tab(
|
||||
selected = selected,
|
||||
onClick = { scope.launch { pagerState.animateScrollToPage(index) } },
|
||||
text = {
|
||||
Text(
|
||||
modifier = Modifier.padding(vertical = 16.dp),
|
||||
text = stringResource(R.string.modules)
|
||||
text = title,
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
fontWeight = if (selected) FontWeight.Bold else FontWeight.Normal,
|
||||
modifier = Modifier.padding(vertical = 12.dp)
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalPager(count = 2, state = pagerState) { page ->
|
||||
HorizontalPager(
|
||||
count = tabTitles.size,
|
||||
state = pagerState,
|
||||
modifier = Modifier.weight(1f)
|
||||
) { page ->
|
||||
when (page) {
|
||||
0 -> AppManageBody(navigator, resultRecipient)
|
||||
1 -> ModuleManageBody()
|
||||
|
|
@ -70,5 +86,4 @@ fun ManageScreen(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
package org.lsposed.npatch.ui.page
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Construction
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import org.lsposed.npatch.R
|
||||
import org.lsposed.npatch.ui.component.CenterTopBar
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
|
|
@ -19,12 +21,34 @@ fun RepoScreen() {
|
|||
Scaffold(
|
||||
topBar = { CenterTopBar(stringResource(BottomBarDestination.Repo.label)) }
|
||||
) { innerPadding ->
|
||||
Text(
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.fillMaxSize(),
|
||||
.fillMaxSize()
|
||||
.padding(32.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Construction,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(72.dp),
|
||||
tint = MaterialTheme.colorScheme.primary.copy(alpha = 0.6f)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.coming_soon),
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
text = "This page is not yet implemented",
|
||||
textAlign = TextAlign.Center
|
||||
textAlign = TextAlign.Center,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,9 +8,7 @@ import androidx.activity.result.contract.ActivityResultContracts
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.PressInteraction
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
|
|
@ -52,7 +50,9 @@ fun SettingsScreen() {
|
|||
Column(
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(vertical = 16.dp)
|
||||
) {
|
||||
KeyStore()
|
||||
DetailPatchLogs()
|
||||
|
|
@ -122,7 +122,6 @@ private fun KeyStore() {
|
|||
onDismissRequest = { expanded = false; showDialog = false },
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
content = { Text(stringResource(android.R.string.ok)) },
|
||||
onClick = {
|
||||
wrongKeystore = false
|
||||
wrongPassword = false
|
||||
|
|
@ -159,25 +158,31 @@ private fun KeyStore() {
|
|||
scope.launch { MyKeyStore.setCustom(password, alias, aliasPassword) }
|
||||
expanded = false
|
||||
showDialog = false
|
||||
})
|
||||
}
|
||||
) {
|
||||
Text(stringResource(android.R.string.ok))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(
|
||||
content = { Text(stringResource(android.R.string.cancel)) },
|
||||
onClick = { expanded = false; showDialog = false }
|
||||
)
|
||||
TextButton(onClick = { expanded = false; showDialog = false }) {
|
||||
Text(stringResource(android.R.string.cancel))
|
||||
}
|
||||
},
|
||||
title = {
|
||||
Text(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = stringResource(R.string.settings_keystore_dialog_title),
|
||||
textAlign = TextAlign.Center
|
||||
textAlign = TextAlign.Center,
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState()),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
LaunchedEffect(interactionSource) {
|
||||
|
|
@ -188,6 +193,7 @@ private fun KeyStore() {
|
|||
}
|
||||
}
|
||||
|
||||
// Error Message Handling
|
||||
val wrongText = when {
|
||||
wrongAliasPassword -> stringResource(R.string.settings_keystore_wrong_alias_password)
|
||||
wrongAliasName -> stringResource(R.string.settings_keystore_wrong_alias)
|
||||
|
|
@ -195,10 +201,13 @@ private fun KeyStore() {
|
|||
wrongKeystore -> stringResource(R.string.settings_keystore_wrong_keystore)
|
||||
else -> null
|
||||
}
|
||||
|
||||
Text(
|
||||
modifier = Modifier.padding(bottom = 8.dp),
|
||||
text = wrongText ?: stringResource(R.string.settings_keystore_desc),
|
||||
color = if (wrongText != null) MaterialTheme.colorScheme.error else Color.Unspecified
|
||||
color = if (wrongText != null) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
|
|
@ -209,28 +218,32 @@ private fun KeyStore() {
|
|||
placeholder = { Text(stringResource(R.string.settings_keystore_file)) },
|
||||
singleLine = true,
|
||||
isError = wrongKeystore,
|
||||
interactionSource = interactionSource
|
||||
interactionSource = interactionSource,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = password,
|
||||
onValueChange = { password = it },
|
||||
label = { Text(stringResource(R.string.settings_keystore_password)) },
|
||||
singleLine = true,
|
||||
isError = wrongPassword
|
||||
isError = wrongPassword,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = alias,
|
||||
onValueChange = { alias = it },
|
||||
label = { Text(stringResource(R.string.settings_keystore_alias)) },
|
||||
singleLine = true,
|
||||
isError = wrongAliasName
|
||||
isError = wrongAliasName,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = aliasPassword,
|
||||
onValueChange = { aliasPassword = it },
|
||||
label = { Text(stringResource(R.string.settings_keystore_alias_password)) },
|
||||
singleLine = true,
|
||||
isError = wrongAliasPassword
|
||||
isError = wrongAliasPassword,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
<string name="modules">模块</string>
|
||||
<string name="shizuku_available">Shizuku 服务可用</string>
|
||||
<string name="shizuku_unavailable">Shizuku 服务未连接</string>
|
||||
<string name="screen_home">主页</string>
|
||||
<string name="screen_repo">仓库</string>
|
||||
<string name="screen_logs">日志</string>
|
||||
<string name="off">关闭</string>
|
||||
|
|
@ -21,6 +22,8 @@
|
|||
<string name="home_framework_version">框架版本</string>
|
||||
<string name="home_system_version">系统版本</string>
|
||||
<string name="home_device">设备</string>
|
||||
<string name="home_device_info">设备信息</string>
|
||||
<string name="coming_soon">敬请期待</string>
|
||||
<string name="home_system_abi">系统架构</string>
|
||||
<string name="home_info_copied">已复制到剪贴板</string>
|
||||
<string name="home_support">支持</string>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
<string name="modules">模組</string>
|
||||
<string name="shizuku_available">Shizuku 服務可用</string>
|
||||
<string name="shizuku_unavailable">Shizuku 服務未連線</string>
|
||||
<string name="screen_home">首頁</string>
|
||||
<string name="screen_repo">倉庫</string>
|
||||
<string name="screen_logs">日誌</string>
|
||||
<string name="off">關閉</string>
|
||||
|
|
@ -21,6 +22,8 @@
|
|||
<string name="home_framework_version">框架版本</string>
|
||||
<string name="home_system_version">系統版本</string>
|
||||
<string name="home_device">裝置</string>
|
||||
<string name="home_device_info">設備資訊</string>
|
||||
<string name="coming_soon">敬請期待</string>
|
||||
<string name="home_system_abi">系統架構</string>
|
||||
<string name="home_info_copied">已複製到剪貼簿</string>
|
||||
<string name="home_support">支援</string>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
<string name="modules">Modules</string>
|
||||
<string name="shizuku_available">Shizuku service available</string>
|
||||
<string name="shizuku_unavailable">Shizuku service not connected</string>
|
||||
<string name="screen_home">Home</string>
|
||||
<string name="screen_repo">Repo</string>
|
||||
<string name="screen_logs">Logs</string>
|
||||
<string name="off">Off</string>
|
||||
|
|
@ -21,6 +22,8 @@
|
|||
<string name="home_framework_version">Framework Version</string>
|
||||
<string name="home_system_version">System Version</string>
|
||||
<string name="home_device">Device</string>
|
||||
<string name="home_device_info">Equipment Information</string>
|
||||
<string name="coming_soon">Stay tuned</string>
|
||||
<string name="home_system_abi">System ABI</string>
|
||||
<string name="home_info_copied">Copied to clipboard</string>
|
||||
<string name="home_support">Support</string>
|
||||
|
|
|
|||
Loading…
Reference in New Issue