refactor(platform): remove Apple targets from KMP

This commit is contained in:
2026-07-21 17:09:59 +02:00
parent d8eaf78997
commit 9e8564e013
75 changed files with 118 additions and 2930 deletions

View File

@@ -128,44 +128,11 @@ private fun File.systemIconPng(): ByteArray? = runCatching {
}
}.getOrNull()
private fun pickDirectory(title: String): File? =
if (isMacOs()) {
val dialog = withMacDirectoryDialog {
nativeFileDialog(title).apply { isVisible = true }
}
try {
val directory = dialog.directory ?: return null
dialog.file
?.let { File(directory, it) }
?: File(directory)
} finally {
dialog.dispose()
}
} else {
val chooser = JFileChooser().apply {
dialogTitle = title
fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
isAcceptAllFileFilterUsed = false
}
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) chooser.selectedFile else null
}
private fun <T> withMacDirectoryDialog(block: () -> T): T {
if (!isMacOs()) return block()
val key = "apple.awt.fileDialogForDirectories"
val previous = System.getProperty(key)
System.setProperty(key, "true")
return try {
block()
} finally {
if (previous == null) {
System.clearProperty(key)
} else {
System.setProperty(key, previous)
}
private fun pickDirectory(title: String): File? {
val chooser = JFileChooser().apply {
dialogTitle = title
fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
isAcceptAllFileFilterUsed = false
}
return if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) chooser.selectedFile else null
}
private fun isMacOs(): Boolean =
System.getProperty("os.name").startsWith("Mac", ignoreCase = true)

View File

@@ -11,7 +11,7 @@ import java.io.File
@Composable
actual fun rememberTransferShareActions(): TransferShareActions = remember {
object : TransferShareActions {
override val canUseNativeShare = DesktopShareBridge.shareFile != null
override val canUseNativeShare = false
override val nfcAvailability = NfcShareAvailability.Hidden
override fun exportInvitation(ticket: String, transferName: String, onResult: (Result<Unit>) -> Unit) {
@@ -31,18 +31,7 @@ actual fun rememberTransferShareActions(): TransferShareActions = remember {
}
override fun shareInvitation(ticket: String, transferName: String, onResult: (Result<Unit>) -> Unit) {
EventQueue.invokeLater {
val share = DesktopShareBridge.shareFile
if (share == null) {
onResult(Result.failure(UnsupportedOperationException("System sharing is unavailable on this desktop")))
return@invokeLater
}
onResult(runCatching {
val directory = File(System.getProperty("java.io.tmpdir"), "vnidrop-share").apply { mkdirs() }
val file = File(directory, invitationFileName(transferName)).apply { writeText(ticket) }
share(file).getOrThrow()
})
}
onResult(Result.failure(UnsupportedOperationException("System sharing is unavailable on this desktop")))
}
override fun writeInvitationToNfc(ticket: String, onResult: (Result<Unit>) -> Unit) {
@@ -55,8 +44,3 @@ actual fun rememberTransferShareActions(): TransferShareActions = remember {
private fun activeFrame(): Frame? =
(KeyboardFocusManager.getCurrentKeyboardFocusManager().activeWindow as? Frame)
?: Frame.getFrames().firstOrNull { it.isActive || it.isFocused }
object DesktopShareBridge {
@Volatile
var shareFile: ((File) -> Result<Unit>)? = null
}

View File

@@ -1,83 +1,14 @@
package com.vnidrop.app.platform
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import java.awt.Color
import java.awt.EventQueue
import java.awt.Frame
import java.awt.Window
import javax.swing.JFrame
import javax.swing.JRootPane
@Composable
actual fun PlatformSystemAppearance(isDarkTheme: Boolean) {
SideEffect {
DesktopSystemAppearance.apply(isDarkTheme)
}
}
internal object DesktopSystemAppearance {
private const val MAC_APPEARANCE_PROPERTY = "apple.awt.application.appearance"
private const val FULL_WINDOW_CONTENT_PROPERTY = "apple.awt.fullWindowContent"
private const val TRANSPARENT_TITLE_BAR_PROPERTY = "apple.awt.transparentTitleBar"
private const val WINDOW_TITLE_VISIBLE_PROPERTY = "apple.awt.windowTitleVisible"
fun apply(isDarkTheme: Boolean) {
if (!DesktopAppearanceBridge.isMacOs()) return
System.setProperty(MAC_APPEARANCE_PROPERTY, macOsAppearanceName(isDarkTheme))
EventQueue.invokeLater {
DesktopAppearanceBridge.applyNativeAppearance?.invoke(isDarkTheme)
Window.getWindows().forEach { window ->
applyWindowChrome(window, isDarkTheme)
}
}
}
internal fun macOsAppearanceName(isDarkTheme: Boolean): String =
if (isDarkTheme) "NSAppearanceNameDarkAqua" else "NSAppearanceNameAqua"
internal fun usesTransparentTitlebar(): Boolean = true
internal fun usesFullWindowContent(): Boolean = true
internal fun showsNativeWindowTitle(): Boolean = false
internal fun titlebarBackground(isDarkTheme: Boolean): Color =
if (isDarkTheme) Color(0x21, 0x21, 0x21) else Color(0xF3, 0xF3, 0xF3)
private fun applyWindowChrome(window: Window, isDarkTheme: Boolean) {
val background = titlebarBackground(isDarkTheme)
window.background = background
(window as? JFrame)?.rootPane?.let { rootPane -> applyRootPaneChrome(rootPane, background) }
}
internal fun applyRootPaneChrome(rootPane: JRootPane, background: Color) {
// Extending the Compose surface beneath the native titlebar lets the
// window chrome and sidebar share one uninterrupted background.
rootPane.putClientProperty(FULL_WINDOW_CONTENT_PROPERTY, usesFullWindowContent())
rootPane.putClientProperty(TRANSPARENT_TITLE_BAR_PROPERTY, usesTransparentTitlebar())
rootPane.putClientProperty(WINDOW_TITLE_VISIBLE_PROPERTY, showsNativeWindowTitle())
rootPane.background = background
rootPane.contentPane.background = background
}
}
actual fun PlatformSystemAppearance(isDarkTheme: Boolean) = Unit
object DesktopAppearanceBridge {
@Volatile
var applyNativeAppearance: ((Boolean) -> Unit)? = null
fun isMacOs(): Boolean = isMacOs(System.getProperty("os.name"))
fun isLinux(): Boolean = isLinux(System.getProperty("os.name"))
fun toggleMaximized(window: Window) {
if (!isMacOs()) return
val frame = window as? Frame ?: return
EventQueue.invokeLater {
frame.extendedState = toggledWindowState(frame.extendedState)
}
}
internal fun isMacOs(osName: String): Boolean =
osName.startsWith("Mac", ignoreCase = true)
internal fun isLinux(osName: String): Boolean =
osName.startsWith("Linux", ignoreCase = true)