修正下一个口令时间窗口错误及高度挤压问题
This commit is contained in:
@@ -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 = {
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user