Skip to content

Commit 07b31ca

Browse files
authored
Merge pull request #51 from Paulanerus/dev
Dev
2 parents a498f99 + f8bd9ed commit 07b31ca

9 files changed

Lines changed: 453 additions & 17 deletions

File tree

build.gradle.kts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ compose.desktop {
4242
}
4343

4444
jvmArgs += listOf(
45-
"--add-modules", "java.sql",
4645
"--add-modules", "jdk.incubator.vector",
4746
"-Dapi.version=${property("api.version")}",
4847
"-Dcore.version=${property("core.version")}",
@@ -56,7 +55,7 @@ compose.desktop {
5655

5756
licenseFile.set(project.file("LICENSE.md"))
5857

59-
modules += listOf("java.sql", "jdk.incubator.vector")
58+
modules += listOf("java.sql", "jdk.incubator.vector", "java.net.http")
6059

6160
linux {
6261
iconFile.set(project.file("ui/src/main/resources/icon.png"))

core/src/main/kotlin/dev/paulee/core/data/provider/EmbeddingProvider.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ internal object EmbeddingProvider {
235235
}
236236
}
237237
} catch (_: CancellationException) {
238-
runCatching { modelPath.deleteIfExists() }
238+
runCatching { if (modelPath.exists()) modelPath.deleteRecursively() }
239239
.onFailure { logger.error("Failed to delete model dir $modelPath", it) }
240240

241241
logger.info("Download cancelled.")

gradle.properties

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ duckdb.version=1.4.1.0
1515
caffeine.version=3.2.2
1616

1717
api.version=1.14.1
18-
core.version=1.17.6
19-
ui.version=1.17.4
20-
app.version=1.6.1
18+
core.version=1.17.8
19+
ui.version=1.17.7
20+
app.version=1.6.3

ui/src/main/kotlin/dev/paulee/ui/Config.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ object Config {
2222

2323
var exactHighlighting by mutableStateOf(true)
2424

25+
var useLegacyFileDialog by mutableStateOf(false)
26+
2527
var selectedPool by mutableStateOf("")
2628

2729
var windowState by mutableStateOf("Floating")

ui/src/main/kotlin/dev/paulee/ui/components/Dialog.kt

Lines changed: 126 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@ package dev.paulee.ui.components
22

33
import androidx.compose.foundation.layout.*
44
import androidx.compose.material.*
5-
import androidx.compose.runtime.Composable
5+
import androidx.compose.runtime.*
66
import androidx.compose.ui.Modifier
7+
import androidx.compose.ui.awt.SwingPanel
78
import androidx.compose.ui.unit.dp
89
import androidx.compose.ui.window.AwtWindow
910
import androidx.compose.ui.window.Dialog
1011
import androidx.compose.ui.window.DialogProperties
12+
import dev.paulee.ui.Config
1113
import dev.paulee.ui.LocalI18n
1214
import dev.paulee.ui.SimpleTextField
1315
import java.awt.FileDialog
1416
import java.awt.Frame
17+
import java.io.File
1518
import java.io.FilenameFilter
1619
import java.nio.file.Path
20+
import javax.swing.JFileChooser
21+
import javax.swing.filechooser.FileNameExtensionFilter
1722

1823
enum class DialogType {
1924
LOAD, SAVE
@@ -25,13 +30,28 @@ fun FileDialog(
2530
dialogType: DialogType = DialogType.LOAD,
2631
extension: String? = null,
2732
onCloseRequest: (result: List<Path>) -> Unit,
33+
) {
34+
if (Config.useLegacyFileDialog) LegacyFileDialog(dialogType, extension, onCloseRequest)
35+
else SystemFileDialog(parent, dialogType, extension, onCloseRequest)
36+
}
37+
38+
@Composable
39+
fun SystemFileDialog(
40+
parent: Frame? = null,
41+
dialogType: DialogType = DialogType.LOAD,
42+
extension: String? = null,
43+
onCloseRequest: (result: List<Path>) -> Unit,
2844
) {
2945
val locale = LocalI18n.current
3046

3147
AwtWindow(
3248
create = {
3349
object :
34-
FileDialog(parent, if (dialogType == DialogType.SAVE) locale["dialog.save"] else locale["dialog.open"], dialogType.ordinal) {
50+
FileDialog(
51+
parent,
52+
if (dialogType == DialogType.SAVE) locale["dialog.save"] else locale["dialog.open"],
53+
dialogType.ordinal
54+
) {
3555

3656
init {
3757
isMultipleMode = dialogType == DialogType.LOAD
@@ -69,6 +89,110 @@ fun FileDialog(
6989
)
7090
}
7191

92+
@Composable
93+
fun LegacyFileDialog(
94+
type: DialogType = DialogType.LOAD,
95+
extension: String? = null,
96+
onCloseRequest: (result: List<Path>) -> Unit,
97+
) {
98+
val locale = LocalI18n.current
99+
100+
val title = if (type == DialogType.SAVE) locale["dialog.save"] else locale["dialog.open"]
101+
var closeResult by remember { mutableStateOf<List<Path>?>(null) }
102+
103+
closeResult?.let {
104+
LaunchedEffect(closeResult) { onCloseRequest(it) }
105+
return
106+
}
107+
108+
val normalizedExtension = extension?.trim()?.lowercase()?.takeIf { it.isNotBlank() }
109+
110+
fun JFileChooser.configure(initial: Boolean = true) {
111+
dialogTitle = title
112+
dialogType = if (type == DialogType.SAVE) JFileChooser.SAVE_DIALOG else JFileChooser.OPEN_DIALOG
113+
isMultiSelectionEnabled = type == DialogType.LOAD
114+
fileSelectionMode = JFileChooser.FILES_ONLY
115+
116+
normalizedExtension?.let { ext ->
117+
val extensionFilter = FileNameExtensionFilter("*.$ext", ext)
118+
119+
if (initial) {
120+
fileFilter = extensionFilter
121+
isAcceptAllFileFilterUsed = true
122+
123+
} else {
124+
val filter = fileFilter
125+
126+
if (filter !is FileNameExtensionFilter || filter.extensions.any { it.equals(ext, true) }) {
127+
resetChoosableFileFilters()
128+
129+
fileFilter = extensionFilter
130+
isAcceptAllFileFilterUsed = true
131+
}
132+
}
133+
}
134+
}
135+
136+
Dialog(
137+
onDismissRequest = { closeResult = emptyList() },
138+
properties = DialogProperties(
139+
usePlatformDefaultWidth = false,
140+
dismissOnBackPress = true,
141+
dismissOnClickOutside = true
142+
)
143+
) {
144+
Surface(
145+
modifier = Modifier.padding(16.dp),
146+
shape = MaterialTheme.shapes.medium,
147+
elevation = 8.dp
148+
) {
149+
SwingPanel(
150+
modifier = Modifier.sizeIn(minWidth = 520.dp, minHeight = 420.dp),
151+
factory = {
152+
JFileChooser().apply {
153+
configure()
154+
155+
if (type == DialogType.SAVE && selectedFile == null) {
156+
val baseName = buildString {
157+
append("untitled")
158+
normalizedExtension?.let { append('.').append(it) }
159+
}
160+
161+
selectedFile = File(currentDirectory, baseName)
162+
}
163+
164+
addActionListener { event ->
165+
val approved = event.actionCommand == JFileChooser.APPROVE_SELECTION
166+
167+
if (!approved) {
168+
closeResult = emptyList()
169+
return@addActionListener
170+
}
171+
172+
val files =
173+
if (isMultiSelectionEnabled) selectedFiles
174+
else selectedFile?.let { arrayOf(it) }.orEmpty()
175+
176+
closeResult = files.mapNotNull { file ->
177+
if (file == null) return@mapNotNull null
178+
179+
if (type == DialogType.SAVE && normalizedExtension != null) {
180+
181+
val withExt = if (file.extension == normalizedExtension) file
182+
else File(file.parentFile ?: currentDirectory, "${file.name}.$normalizedExtension")
183+
184+
withExt.toPath()
185+
} else file.toPath()
186+
}
187+
}
188+
}
189+
},
190+
update = { it.configure(false) }
191+
)
192+
}
193+
}
194+
}
195+
72196
@Composable
73197
fun CustomInputDialog(
74198
title: String,

0 commit comments

Comments
 (0)