Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,15 @@ internal fun buildFileSaverSuggestedName(
else -> "$suggestedName.$normalizedExtension"
}
}

internal fun buildFileSaverAllowedFileTypes(
defaultExtension: String?,
allowedExtensions: Set<String>?,
): List<String>? {
val normalizedDefault = normalizeFileSaverExtension(defaultExtension)
val normalizedAllowed = normalizeFileSaverExtensions(allowedExtensions).orEmpty()
return buildList {
normalizedDefault?.let { add(it) }
normalizedAllowed.forEach { if (it != normalizedDefault) add(it) }
}.takeIf { it.isNotEmpty() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,28 @@ class FileSaverNameTest {
assertEquals("document.pdf", buildFileSaverSuggestedName("document", ".pdf"))
assertEquals("document.pdf", buildFileSaverSuggestedName("document", " .pdf "))
}

@Test
fun buildFileSaverAllowedFileTypes_whenNoExtensions_returnsNull() {
assertNull(buildFileSaverAllowedFileTypes(null, null))
assertNull(buildFileSaverAllowedFileTypes("", setOf("", ".")))
}

@Test
fun buildFileSaverAllowedFileTypes_whenOnlyDefaultExtension_returnsSingleNormalizedType() {
assertEquals(listOf("pdf"), buildFileSaverAllowedFileTypes(".pdf", null))
}

@Test
fun buildFileSaverAllowedFileTypes_whenNoDefault_returnsNormalizedAllowedExtensions() {
assertEquals(listOf("md", "txt"), buildFileSaverAllowedFileTypes(null, setOf("md", "txt")))
}

@Test
fun buildFileSaverAllowedFileTypes_putsDefaultExtensionFirstAndDeduplicates() {
assertEquals(
listOf("pdf", "md", "txt"),
buildFileSaverAllowedFileTypes("pdf", setOf("md", "pdf", "txt")),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package io.github.vinceglb.filekit.dialogs.platform.mac
import io.github.vinceglb.filekit.PlatformFile
import io.github.vinceglb.filekit.dialogs.FileKitDialogSettings
import io.github.vinceglb.filekit.dialogs.FileKitMacOSSettings
import io.github.vinceglb.filekit.dialogs.buildFileSaverSuggestedName
import io.github.vinceglb.filekit.dialogs.buildFileSaverAllowedFileTypes
import io.github.vinceglb.filekit.dialogs.platform.PlatformFilePicker
import io.github.vinceglb.filekit.dialogs.platform.mac.foundation.Foundation
import io.github.vinceglb.filekit.dialogs.platform.mac.foundation.ID
Expand Down Expand Up @@ -73,18 +73,15 @@ internal class MacOSFilePicker : PlatformFilePicker {
Foundation.invoke(savePanel, "setDirectoryURL:", Foundation.nsURL(it.path))
}

// Set the file name without extension, NSSavePanel appends it from allowedFileTypes
Foundation.invoke(
savePanel,
"setNameFieldStringValue:",
Foundation.nsString(
buildFileSaverSuggestedName(
suggestedName = suggestedName,
extension = defaultExtension,
),
),
Foundation.nsString(suggestedName),
)

val fileTypes = allowedExtensions ?: defaultExtension?.let { setOf(it) }
// Default extension first so it is the one appended
val fileTypes = buildFileSaverAllowedFileTypes(defaultExtension, allowedExtensions)
savePanel.setAllowedFileTypes(fileTypes)

Foundation.invoke(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,16 @@ internal actual suspend fun FileKit.platformOpenFileSaver(
): PlatformFile? {
// Create an NSSavePanel
val nsSavePanel = NSSavePanel()
val normalizedDefaultExtension = normalizeFileSaverExtension(defaultExtension)
val normalizedAllowedExtensions = normalizeFileSaverExtensions(allowedExtensions)

// Set the initial directory
directory?.let { nsSavePanel.directoryURL = NSURL.fileURLWithPath(it.path) }

// Set the file name
nsSavePanel.nameFieldStringValue = buildFileSaverSuggestedName(
suggestedName = suggestedName,
extension = normalizedDefaultExtension,
)
// Set the file name without extension, NSSavePanel appends it from allowedFileTypes
nsSavePanel.nameFieldStringValue = suggestedName

// Set the file extension filters
val fileTypes = normalizedAllowedExtensions ?: normalizedDefaultExtension?.let { setOf(it) }
fileTypes?.let { nsSavePanel.allowedFileTypes = it.toList() }
// Set the file extension filters, default extension first so it is the one appended
buildFileSaverAllowedFileTypes(defaultExtension, allowedExtensions)
?.let { nsSavePanel.allowedFileTypes = it }

// Accept the creation of directories
nsSavePanel.canCreateDirectories = dialogSettings.canCreateDirectories
Expand Down