@@ -26,6 +26,7 @@ import androidx.compose.foundation.shape.CircleShape
2626import androidx.compose.foundation.shape.RoundedCornerShape
2727import androidx.compose.material.icons.Icons
2828import androidx.compose.material.icons.automirrored.rounded.KeyboardArrowRight
29+ import androidx.compose.material.icons.filled.Close
2930import androidx.compose.material3.*
3031import androidx.compose.runtime.*
3132import androidx.compose.ui.Alignment
@@ -213,7 +214,9 @@ class PasswordOverlayActivity: FragmentActivity() {
213214 onAuthSuccess = {},
214215 lockedAppName = appName,
215216 triggeringPackageName = triggeringPackageNameFromIntent,
216- onPinAttempt = onPinAttemptCallback
217+ onPinAttempt = onPinAttemptCallback,
218+ showCloseButton = true ,
219+ onClose = { finish() }
217220 )
218221
219222 BackHandler { }
@@ -336,6 +339,8 @@ fun PasswordOverlayScreen(
336339 modifier : Modifier = Modifier ,
337340 showBiometricButton : Boolean = false,
338341 fromMainActivity : Boolean = false,
342+ showCloseButton : Boolean = false,
343+ onClose : () -> Unit = {},
339344 onBiometricAuth : () -> Unit = {},
340345 onAuthSuccess : () -> Unit ,
341346 lockedAppName : String? = null,
@@ -356,36 +361,125 @@ fun PasswordOverlayScreen(
356361 modifier = modifier.fillMaxSize(),
357362 color = MaterialTheme .colorScheme.surfaceContainer
358363 ) {
359- val passwordState = remember { mutableStateOf(" " ) }
360- var showError by remember { mutableStateOf(false ) }
361- val minLength = 4
364+ Box (modifier = Modifier .fillMaxSize()) {
365+ if (showCloseButton) {
366+ IconButton (
367+ onClick = onClose,
368+ modifier = Modifier
369+ .statusBarsPadding()
370+ .padding(start = 8 .dp, top = 8 .dp)
371+ .align(Alignment .TopStart )
372+ ) {
373+ Icon (
374+ imageVector = Icons .Default .Close ,
375+ contentDescription = " Close" ,
376+ tint = MaterialTheme .colorScheme.onSurface
377+ )
378+ }
379+ }
362380
363- if (isLandscape) {
364- Row (
365- modifier = Modifier
366- .fillMaxSize()
367- .padding(horizontal = 16 .dp, vertical = 16 .dp),
368- horizontalArrangement = Arrangement .SpaceEvenly ,
369- verticalAlignment = Alignment .CenterVertically
370- ) {
381+ val passwordState = remember { mutableStateOf(" " ) }
382+ var showError by remember { mutableStateOf(false ) }
383+ val minLength = 4
384+
385+ if (isLandscape) {
386+ Row (
387+ modifier = Modifier
388+ .fillMaxSize()
389+ .padding(horizontal = 16 .dp, vertical = 16 .dp),
390+ horizontalArrangement = Arrangement .SpaceEvenly ,
391+ verticalAlignment = Alignment .CenterVertically
392+ ) {
393+ Column (
394+ modifier = Modifier
395+ .weight(1f )
396+ .padding(end = 32 .dp),
397+ horizontalAlignment = Alignment .CenterHorizontally ,
398+ verticalArrangement = Arrangement .Center
399+ ) {
400+ Text (
401+ text = if (! fromMainActivity && ! lockedAppName.isNullOrEmpty())
402+ " Continue to $lockedAppName "
403+ else
404+ stringResource(R .string.enter_password_to_continue),
405+ style = MaterialTheme .typography.titleLarge,
406+ textAlign = TextAlign .Center
407+ )
408+
409+ // if (!fromMainActivity && !triggeringPackageName.isNullOrEmpty()) {
410+ // Spacer(modifier = Modifier.height(8.dp))
411+ // Text(
412+ // text = triggeringPackageName,
413+ // style = MaterialTheme.typography.labelSmall,
414+ // color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f),
415+ // textAlign = TextAlign.Center
416+ // )
417+ // }
418+
419+ Spacer (modifier = Modifier .height(16 .dp))
420+
421+ PasswordIndicators (
422+ passwordLength = passwordState.value.length,
423+ )
424+
425+ if (showError) {
426+ Spacer (modifier = Modifier .height(8 .dp))
427+ Text (
428+ text = stringResource(R .string.incorrect_pin_try_again),
429+ color = MaterialTheme .colorScheme.error,
430+ style = MaterialTheme .typography.bodyMedium,
431+ )
432+ }
433+ }
434+
435+ Column (
436+ horizontalAlignment = Alignment .CenterHorizontally ,
437+ verticalArrangement = Arrangement .Center
438+ ) {
439+ KeypadSection (
440+ passwordState = passwordState,
441+ minLength = minLength,
442+ showBiometricButton = showBiometricButton,
443+ fromMainActivity = fromMainActivity,
444+ onBiometricAuth = onBiometricAuth,
445+ onAuthSuccess = onAuthSuccess,
446+ onPinAttempt = onPinAttempt,
447+ onPasswordChange = {
448+ showError = false
449+
450+ if (appLockRepository.isAutoUnlockEnabled()) {
451+ onPinAttempt?.invoke(passwordState.value)
452+ }
453+ },
454+ onPinIncorrect = { showError = true }
455+ )
456+ }
457+ }
458+ } else {
371459 Column (
372460 modifier = Modifier
373- .weight( 1f )
374- .padding(end = 32 .dp),
461+ .fillMaxSize( )
462+ .padding(vertical = if (fromMainActivity) 24 .dp else 12 .dp),
375463 horizontalAlignment = Alignment .CenterHorizontally ,
376- verticalArrangement = Arrangement .Center
464+ verticalArrangement = Arrangement .spacedBy( 24 .dp)
377465 ) {
466+ // Dynamic spacer for small screens
467+ val topSpacerHeight = if (screenHeightDp < 600 .dp) 12 .dp else 48 .dp
468+ Spacer (modifier = Modifier .height(topSpacerHeight))
469+
378470 Text (
379471 text = if (! fromMainActivity && ! lockedAppName.isNullOrEmpty())
380472 " Continue to $lockedAppName "
381473 else
382474 stringResource(R .string.enter_password_to_continue),
383- style = MaterialTheme .typography.titleLarge,
475+ style = if (! fromMainActivity && ! lockedAppName.isNullOrEmpty())
476+ MaterialTheme .typography.titleLargeEmphasized
477+ else
478+ MaterialTheme .typography.headlineMediumEmphasized,
384479 textAlign = TextAlign .Center
385480 )
386481
387482// if (!fromMainActivity && !triggeringPackageName.isNullOrEmpty()) {
388- // Spacer(modifier = Modifier.height(8.dp))
389483// Text(
390484// text = triggeringPackageName,
391485// style = MaterialTheme.typography.labelSmall,
@@ -401,19 +495,16 @@ fun PasswordOverlayScreen(
401495 )
402496
403497 if (showError) {
404- Spacer (modifier = Modifier .height(8 .dp))
405498 Text (
406499 text = stringResource(R .string.incorrect_pin_try_again),
407500 color = MaterialTheme .colorScheme.error,
408501 style = MaterialTheme .typography.bodyMedium,
502+ modifier = Modifier .padding(top = 8 .dp)
409503 )
410504 }
411- }
412505
413- Column (
414- horizontalAlignment = Alignment .CenterHorizontally ,
415- verticalArrangement = Arrangement .Center
416- ) {
506+ Spacer (modifier = Modifier .weight(1f ))
507+
417508 KeypadSection (
418509 passwordState = passwordState,
419510 minLength = minLength,
@@ -433,74 +524,6 @@ fun PasswordOverlayScreen(
433524 )
434525 }
435526 }
436- } else {
437- Column (
438- modifier = Modifier
439- .fillMaxSize()
440- .padding(vertical = if (fromMainActivity) 24 .dp else 12 .dp),
441- horizontalAlignment = Alignment .CenterHorizontally ,
442- verticalArrangement = Arrangement .spacedBy(24 .dp)
443- ) {
444- // Dynamic spacer for small screens
445- val topSpacerHeight = if (screenHeightDp < 600 .dp) 12 .dp else 48 .dp
446- Spacer (modifier = Modifier .height(topSpacerHeight))
447-
448- Text (
449- text = if (! fromMainActivity && ! lockedAppName.isNullOrEmpty())
450- " Continue to $lockedAppName "
451- else
452- stringResource(R .string.enter_password_to_continue),
453- style = if (! fromMainActivity && ! lockedAppName.isNullOrEmpty())
454- MaterialTheme .typography.titleLargeEmphasized
455- else
456- MaterialTheme .typography.headlineMediumEmphasized,
457- textAlign = TextAlign .Center
458- )
459-
460- // if (!fromMainActivity && !triggeringPackageName.isNullOrEmpty()) {
461- // Text(
462- // text = triggeringPackageName,
463- // style = MaterialTheme.typography.labelSmall,
464- // color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f),
465- // textAlign = TextAlign.Center
466- // )
467- // }
468-
469- Spacer (modifier = Modifier .height(16 .dp))
470-
471- PasswordIndicators (
472- passwordLength = passwordState.value.length,
473- )
474-
475- if (showError) {
476- Text (
477- text = stringResource(R .string.incorrect_pin_try_again),
478- color = MaterialTheme .colorScheme.error,
479- style = MaterialTheme .typography.bodyMedium,
480- modifier = Modifier .padding(top = 8 .dp)
481- )
482- }
483-
484- Spacer (modifier = Modifier .weight(1f ))
485-
486- KeypadSection (
487- passwordState = passwordState,
488- minLength = minLength,
489- showBiometricButton = showBiometricButton,
490- fromMainActivity = fromMainActivity,
491- onBiometricAuth = onBiometricAuth,
492- onAuthSuccess = onAuthSuccess,
493- onPinAttempt = onPinAttempt,
494- onPasswordChange = {
495- showError = false
496-
497- if (appLockRepository.isAutoUnlockEnabled()) {
498- onPinAttempt?.invoke(passwordState.value)
499- }
500- },
501- onPinIncorrect = { showError = true }
502- )
503- }
504527 }
505528 }
506529}
@@ -516,6 +539,8 @@ fun PasswordIndicators(
516539 val screenWidth = windowInfo.containerSize.width
517540 val screenHeight = windowInfo.containerSize.height
518541 val screenWidthDp = configuration.screenWidthDp.dp
542+ val screenHeightDp = configuration.screenHeightDp.dp
543+
519544 val isLandscape = screenWidth > screenHeight
520545
521546 val indicatorSize = remember(screenWidthDp) {
0 commit comments