diff --git a/app/src/main/kotlin/com/syncflow/ui/addpair/AddPairScreen.kt b/app/src/main/kotlin/com/syncflow/ui/addpair/AddPairScreen.kt index aaae6d6..b3a00f4 100644 --- a/app/src/main/kotlin/com/syncflow/ui/addpair/AddPairScreen.kt +++ b/app/src/main/kotlin/com/syncflow/ui/addpair/AddPairScreen.kt @@ -1,6 +1,7 @@ package com.syncflow.ui.addpair import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardOptions @@ -105,18 +106,17 @@ fun AddPairScreen(onDone: () -> Unit, vm: AddPairViewModel = hiltViewModel()) { Spacer(Modifier.height(4.dp)) // Local folder - OutlinedTextField( - value = uriToDisplay(s.localPath), onValueChange = {}, - label = { Text("Local folder") }, - leadingIcon = { Icon(Icons.Default.PhoneAndroid, null) }, - trailingIcon = { - IconButton(onClick = { showLocalBrowser = true }) { - Icon(Icons.Default.FolderOpen, "Browse") - } - }, - readOnly = true, singleLine = true, modifier = Modifier.fillMaxWidth(), - placeholder = { Text("Tap to choose folder…") }, - ) + Box(modifier = Modifier.fillMaxWidth()) { + OutlinedTextField( + value = uriToDisplay(s.localPath), onValueChange = {}, + label = { Text("Local folder") }, + leadingIcon = { Icon(Icons.Default.PhoneAndroid, null) }, + trailingIcon = { Icon(Icons.Default.FolderOpen, null) }, + readOnly = true, singleLine = true, modifier = Modifier.fillMaxWidth(), + placeholder = { Text("Tap to choose folder…") }, + ) + Box(modifier = Modifier.matchParentSize().clickable { showLocalBrowser = true }) + } // Remote folder OutlinedTextField( diff --git a/app/src/main/kotlin/com/syncflow/ui/browser/LocalBrowserDialog.kt b/app/src/main/kotlin/com/syncflow/ui/browser/LocalBrowserDialog.kt index 1606db0..25d28b9 100644 --- a/app/src/main/kotlin/com/syncflow/ui/browser/LocalBrowserDialog.kt +++ b/app/src/main/kotlin/com/syncflow/ui/browser/LocalBrowserDialog.kt @@ -26,9 +26,14 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalView +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -131,8 +136,25 @@ fun LocalBrowserDialog( onDismissRequest = onDismiss, properties = DialogProperties(usePlatformDefaultWidth = false, decorFitsSystemWindows = false), ) { + val view = LocalView.current + val density = LocalDensity.current + var topInset by remember { mutableStateOf(0.dp) } + var bottomInset by remember { mutableStateOf(56.dp) } + DisposableEffect(view) { + ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets -> + val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + with(density) { + topInset = bars.top.toDp() + bottomInset = maxOf(bars.bottom.toDp(), 56.dp) + } + insets + } + ViewCompat.requestApplyInsets(view) + onDispose { ViewCompat.setOnApplyWindowInsetsListener(view, null) } + } + Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.surface) { - Column(modifier = Modifier.fillMaxSize().statusBarsPadding()) { + Column(modifier = Modifier.fillMaxSize().padding(top = topInset)) { // ── Top bar ────────────────────────────────────────────────── TopAppBar( @@ -242,20 +264,21 @@ fun LocalBrowserDialog( // ── Select button ──────────────────────────────────────────── Surface(tonalElevation = 4.dp, modifier = Modifier.fillMaxWidth()) { - Column(modifier = Modifier.navigationBarsPadding()) { - Button( - onClick = { onSelect(currentPath.absolutePath) }, - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp, top = 12.dp, end = 16.dp, bottom = 12.dp) - .height(52.dp), - shape = RoundedCornerShape(14.dp), - ) { - Icon(Icons.Default.CheckCircle, null, Modifier.size(20.dp)) - Spacer(Modifier.width(8.dp)) - Text("Select \"$currentFolderName\"", - style = MaterialTheme.typography.titleSmall, fontWeight = FontWeight.SemiBold) - } + Column { + Button( + onClick = { onSelect(currentPath.absolutePath) }, + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, top = 12.dp, end = 16.dp, bottom = 12.dp) + .height(52.dp), + shape = RoundedCornerShape(14.dp), + ) { + Icon(Icons.Default.CheckCircle, null, Modifier.size(20.dp)) + Spacer(Modifier.width(8.dp)) + Text("Select \"$currentFolderName\"", + style = MaterialTheme.typography.titleSmall, fontWeight = FontWeight.SemiBold) + } + Spacer(Modifier.height(bottomInset)) } } } diff --git a/app/src/main/kotlin/com/syncflow/ui/browser/RemoteBrowserDialog.kt b/app/src/main/kotlin/com/syncflow/ui/browser/RemoteBrowserDialog.kt index b25ce1f..e6ef4fd 100644 --- a/app/src/main/kotlin/com/syncflow/ui/browser/RemoteBrowserDialog.kt +++ b/app/src/main/kotlin/com/syncflow/ui/browser/RemoteBrowserDialog.kt @@ -25,9 +25,13 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalView import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat import androidx.hilt.navigation.compose.hiltViewModel import com.syncflow.domain.model.RemoteFile import kotlinx.coroutines.launch @@ -77,8 +81,25 @@ fun RemoteBrowserDialog( onDismissRequest = onDismiss, properties = DialogProperties(usePlatformDefaultWidth = false, decorFitsSystemWindows = false), ) { + val view = LocalView.current + val density = LocalDensity.current + var topInset by remember { mutableStateOf(0.dp) } + var bottomInset by remember { mutableStateOf(56.dp) } + DisposableEffect(view) { + ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets -> + val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + with(density) { + topInset = bars.top.toDp() + bottomInset = maxOf(bars.bottom.toDp(), 56.dp) + } + insets + } + ViewCompat.requestApplyInsets(view) + onDispose { ViewCompat.setOnApplyWindowInsetsListener(view, null) } + } + Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.surface) { - Column(modifier = Modifier.fillMaxSize().statusBarsPadding()) { + Column(modifier = Modifier.fillMaxSize().padding(top = topInset)) { // ── Top bar ────────────────────────────────────────────────── TopAppBar( @@ -208,7 +229,7 @@ fun RemoteBrowserDialog( // ── Select button ──────────────────────────────────────────── Surface(tonalElevation = 4.dp, modifier = Modifier.fillMaxWidth()) { - Column(modifier = Modifier.navigationBarsPadding()) { + Column { Button( onClick = { onSelect(state.currentPath) }, modifier = Modifier @@ -225,6 +246,7 @@ fun RemoteBrowserDialog( fontWeight = FontWeight.SemiBold, ) } + Spacer(Modifier.height(bottomInset)) } } } diff --git a/version.properties b/version.properties index fcbf9f7..22acddf 100644 --- a/version.properties +++ b/version.properties @@ -1,2 +1,2 @@ -VERSION_NAME=1.0.47 -VERSION_CODE=48 +VERSION_NAME=1.0.52 +VERSION_CODE=53