修正下一个口令时间窗口错误及高度挤压问题

This commit is contained in:
2026-06-17 00:17:06 +08:00
parent 2d45b717a4
commit fce997c3d6
2 changed files with 61 additions and 23 deletions
@@ -40,6 +40,8 @@ fun TokenDetailSheet(
var nextCode by remember { mutableStateOf("") }
var progress by remember { mutableStateOf(1f) }
var remainingSeconds by remember { mutableStateOf(0) }
val showNextPreview = remainingSeconds in 0..5 &&
(token.tokenType == TokenType.TOTP || token.tokenType == TokenType.STEAM)
val secretBytes = remember(token.secret.value) {
try {
@@ -64,7 +66,7 @@ fun TokenDetailSheet(
secretBytes, time, token.period, token.digits, token.algorithm.ordinal
)
nextCode = NativeLib.generateTOTP(
secretBytes, time + 1, token.period, token.digits, token.algorithm.ordinal
secretBytes, time + token.period, token.period, token.digits, token.algorithm.ordinal
)
val remaining = periodMs - (now % periodMs)
progress = remaining.toFloat() / periodMs.toFloat()
@@ -73,7 +75,7 @@ fun TokenDetailSheet(
TokenType.STEAM -> {
val time = now / 1000L
currentCode = NativeLib.generateSteam(secretBytes, time)
nextCode = NativeLib.generateSteam(secretBytes, time + 1)
nextCode = NativeLib.generateSteam(secretBytes, time + 30)
val periodMs = 30000L
val remaining = periodMs - (now % periodMs)
progress = remaining.toFloat() / periodMs.toFloat()
@@ -133,12 +135,17 @@ fun TokenDetailSheet(
color = MaterialTheme.colorScheme.primary,
fontWeight = FontWeight.Bold
)
if (remainingSeconds <= 5 && (token.tokenType == TokenType.TOTP || token.tokenType == TokenType.STEAM)) {
Text(
text = formatCode(nextCode),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f)
)
Box(
modifier = Modifier.height(20.dp),
contentAlignment = Alignment.Center
) {
if (showNextPreview) {
Text(
text = formatCode(nextCode),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f)
)
}
}
}
@@ -150,7 +157,7 @@ fun TokenDetailSheet(
CircularProgressIndicator(
progress = { progress },
modifier = Modifier.fillMaxSize(),
color = if (remainingSeconds <= 5) warningColor else MaterialTheme.colorScheme.primary,
color = if (showNextPreview) warningColor else MaterialTheme.colorScheme.primary,
trackColor = MaterialTheme.colorScheme.surfaceVariant,
strokeWidth = 3.dp,
)
@@ -158,7 +165,7 @@ fun TokenDetailSheet(
text = "$remainingSeconds",
style = MaterialTheme.typography.labelMedium,
fontWeight = FontWeight.Bold,
color = if (remainingSeconds <= 5) warningColor else MaterialTheme.colorScheme.onSurface
color = if (showNextPreview) warningColor else MaterialTheme.colorScheme.onSurface
)
}
}
@@ -25,7 +25,11 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
@@ -48,6 +52,15 @@ fun TokensScreen(
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
var showAddBottomSheet by remember { mutableStateOf(false) }
var isSearchExpanded by remember { mutableStateOf(false) }
var searchFieldHasFocus by remember { mutableStateOf(false) }
val searchFocusRequester = remember { FocusRequester() }
val focusManager = LocalFocusManager.current
LaunchedEffect(isSearchExpanded) {
if (isSearchExpanded) {
searchFocusRequester.requestFocus()
}
}
Scaffold(
topBar = {
@@ -62,7 +75,9 @@ fun TokensScreen(
}
AnimatedVisibility(
visible = isSearchExpanded,
modifier = Modifier.weight(1f)
modifier = Modifier
.weight(1f)
.padding(end = 16.dp)
) {
Surface(
shape = MaterialTheme.shapes.large,
@@ -72,12 +87,21 @@ fun TokensScreen(
TextField(
value = uiState.searchQuery,
onValueChange = { viewModel.updateSearchQuery(it) },
modifier = Modifier.fillMaxWidth(),
modifier = Modifier
.fillMaxWidth()
.focusRequester(searchFocusRequester)
.onFocusChanged { focusState ->
if (searchFieldHasFocus && !focusState.isFocused) {
isSearchExpanded = false
}
searchFieldHasFocus = focusState.isFocused
},
placeholder = { Text(stringResource(R.string.search_tokens)) },
leadingIcon = { Icon(Icons.Default.Search, contentDescription = stringResource(R.string.search)) },
trailingIcon = {
IconButton(onClick = {
IconButton(onClick = {
viewModel.updateSearchQuery("")
focusManager.clearFocus(force = true)
isSearchExpanded = false
}) {
Icon(Icons.Default.Close, contentDescription = "Clear search")
@@ -211,6 +235,8 @@ fun TokenCard(
var remainingSeconds by remember { mutableStateOf(0) }
var showDetailSheet by remember { mutableStateOf(false) }
val context = LocalContext.current
val showNextPreview = remainingSeconds in 0..5 &&
(token.tokenType == TokenType.TOTP || token.tokenType == TokenType.STEAM)
val secretBytes = remember(token.secret.value) {
try {
@@ -240,7 +266,7 @@ fun TokenCard(
)
nextCode = NativeLib.generateTOTP(
secretBytes,
time + 1,
time + token.period,
token.period,
token.digits,
token.algorithm.ordinal
@@ -257,7 +283,7 @@ fun TokenCard(
)
nextCode = NativeLib.generateSteam(
secretBytes,
time + 1
time + 30
)
val periodMs = 30000L
val remaining = periodMs - (now % periodMs)
@@ -318,12 +344,17 @@ fun TokenCard(
color = MaterialTheme.colorScheme.primary,
fontWeight = FontWeight.Bold
)
if (remainingSeconds <= 5 && (token.tokenType == TokenType.TOTP || token.tokenType == TokenType.STEAM)) {
Text(
text = formatCode(nextCode),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f)
)
Box(
modifier = Modifier.height(20.dp),
contentAlignment = Alignment.CenterStart
) {
if (showNextPreview) {
Text(
text = formatCode(nextCode),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f)
)
}
}
}
@@ -339,7 +370,7 @@ fun TokenCard(
CircularProgressIndicator(
progress = { progress },
modifier = Modifier.fillMaxSize(),
color = if (remainingSeconds <= 5) warningColor else MaterialTheme.colorScheme.primary,
color = if (showNextPreview) warningColor else MaterialTheme.colorScheme.primary,
trackColor = MaterialTheme.colorScheme.surfaceVariant,
strokeWidth = 3.dp,
)
@@ -347,7 +378,7 @@ fun TokenCard(
text = "$remainingSeconds",
style = MaterialTheme.typography.labelMedium,
fontWeight = FontWeight.Bold,
color = if (remainingSeconds <= 5) warningColor else MaterialTheme.colorScheme.onSurface
color = if (showNextPreview) warningColor else MaterialTheme.colorScheme.onSurface
)
}
}