diff --git a/src/main/kotlin/com/bolenpad/photophetch/ui/SettingsScreen.kt b/src/main/kotlin/com/bolenpad/photophetch/ui/SettingsScreen.kt index 65b895c..d74c572 100644 --- a/src/main/kotlin/com/bolenpad/photophetch/ui/SettingsScreen.kt +++ b/src/main/kotlin/com/bolenpad/photophetch/ui/SettingsScreen.kt @@ -3,12 +3,16 @@ package com.bolenpad.photophetch.ui import androidx.compose.foundation.layout.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.FolderOpen import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import java.awt.FileDialog +import java.awt.Frame +import java.io.File @Composable fun SettingsScreen(state: AppState) { @@ -33,14 +37,30 @@ fun SettingsScreen(state: AppState) { // Staging directory Text("Staging Directory", style = MaterialTheme.typography.titleSmall, fontWeight = FontWeight.SemiBold) - OutlinedTextField( - value = stagingRoot, - onValueChange = { stagingRoot = it }, - label = { Text("Path to _staging/ directory") }, - placeholder = { Text("/Volumes/delphi/_staging") }, - modifier = Modifier.fillMaxWidth(), - singleLine = true, - ) + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + OutlinedTextField( + value = stagingRoot, + onValueChange = { stagingRoot = it }, + label = { Text("Path to _staging/ directory") }, + placeholder = { Text("/Volumes/delphi/_staging") }, + modifier = Modifier.weight(1f), + singleLine = true, + ) + OutlinedIconButton( + onClick = { + val chosen = pickFolder( + title = "Select _staging directory", + initialDir = stagingRoot.ifBlank { "/Volumes" }, + ) + if (chosen != null) stagingRoot = chosen + }, + ) { + Icon(Icons.Default.FolderOpen, contentDescription = "Browse…") + } + } Text( "This should be the _staging directory on your NAS (must be mounted).", style = MaterialTheme.typography.bodySmall, @@ -78,7 +98,6 @@ fun SettingsScreen(state: AppState) { Button( onClick = { state.updateStagingRoot(stagingRoot) - // Also save template update state.saveConfig() }, modifier = Modifier.fillMaxWidth().height(52.dp), @@ -87,3 +106,24 @@ fun SettingsScreen(state: AppState) { } } } + +/** + * Opens the native macOS folder picker (System.setProperty trick to make + * AWT FileDialog show directories instead of files). + * Returns the chosen absolute path, or null if cancelled. + */ +private fun pickFolder(title: String, initialDir: String): String? { + // On macOS, this system property switches FileDialog to directory-selection mode + System.setProperty("apple.awt.fileDialogForDirectories", "true") + return try { + val dialog = FileDialog(null as Frame?, title, FileDialog.LOAD).apply { + directory = initialDir + isVisible = true + } + val dir = dialog.directory + val file = dialog.file + if (file != null) File(dir, file).absolutePath else null + } finally { + System.setProperty("apple.awt.fileDialogForDirectories", "false") + } +}