mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 10:29:58 +02:00
Build native UI shell foundation
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
package com.vnidrop.app.logging
|
||||
|
||||
import java.io.File
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
actual fun createPlatformLogStore(appDataDir: String, policy: LogRotationPolicy): PlatformLogStore =
|
||||
JvmPlatformLogStore(appDataDir, policy)
|
||||
|
||||
actual fun platformNowMillis(): Long = System.currentTimeMillis()
|
||||
|
||||
private class JvmPlatformLogStore(
|
||||
appDataDir: String,
|
||||
private val policy: LogRotationPolicy,
|
||||
) : PlatformLogStore {
|
||||
private val directory = File(appDataDir, "logs")
|
||||
private val activeFile = File(directory, "app.log")
|
||||
|
||||
override val logDirectory: String = directory.absolutePath
|
||||
|
||||
@Synchronized
|
||||
override fun append(line: String) {
|
||||
directory.mkdirs()
|
||||
val bytes = line.toByteArray(StandardCharsets.UTF_8)
|
||||
if (policy.shouldRotate(activeFile.length(), bytes.size.toLong())) {
|
||||
rotate()
|
||||
}
|
||||
activeFile.appendBytes(bytes)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun listLogFiles(): List<LogFileInfo> {
|
||||
directory.mkdirs()
|
||||
return directory
|
||||
.listFiles { file -> file.isFile && file.name.startsWith("app") && file.name.endsWith(".log") }
|
||||
.orEmpty()
|
||||
.sortedByDescending { it.lastModified() }
|
||||
.map { file -> LogFileInfo(file.name, file.absolutePath, file.length(), file.lastModified()) }
|
||||
}
|
||||
|
||||
private fun rotate() {
|
||||
if (policy.maxFiles == 0) {
|
||||
activeFile.delete()
|
||||
return
|
||||
}
|
||||
File(directory, "app.${policy.maxFiles}.log").delete()
|
||||
for (index in policy.maxFiles - 1 downTo 1) {
|
||||
val source = File(directory, "app.$index.log")
|
||||
if (source.exists()) {
|
||||
source.renameTo(File(directory, "app.${index + 1}.log"))
|
||||
}
|
||||
}
|
||||
if (activeFile.exists()) {
|
||||
activeFile.renameTo(File(directory, "app.1.log"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
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.Window
|
||||
import javax.swing.JFrame
|
||||
|
||||
@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 TRANSPARENT_TITLE_BAR_PROPERTY = "apple.awt.transparentTitleBar"
|
||||
|
||||
fun apply(isDarkTheme: Boolean) {
|
||||
if (!isMacOs()) return
|
||||
System.setProperty(MAC_APPEARANCE_PROPERTY, macOsAppearanceName(isDarkTheme))
|
||||
EventQueue.invokeLater {
|
||||
Window.getWindows().forEach { window ->
|
||||
applyWindowChrome(window, isDarkTheme)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun macOsAppearanceName(isDarkTheme: Boolean): String =
|
||||
if (isDarkTheme) "NSAppearanceNameDarkAqua" else "NSAppearanceNameAqua"
|
||||
|
||||
internal fun titlebarBackground(isDarkTheme: Boolean): Color =
|
||||
if (isDarkTheme) Color(0x12, 0x12, 0x12) else Color(0xF8, 0xF8, 0xF8)
|
||||
|
||||
private fun applyWindowChrome(window: Window, isDarkTheme: Boolean) {
|
||||
val background = titlebarBackground(isDarkTheme)
|
||||
window.background = background
|
||||
(window as? JFrame)?.rootPane?.let { rootPane ->
|
||||
// Keep the native macOS controls and drag behavior, but let the
|
||||
// decorated titlebar blend with the app's resolved light/dark surface.
|
||||
rootPane.putClientProperty(TRANSPARENT_TITLE_BAR_PROPERTY, true)
|
||||
rootPane.background = background
|
||||
rootPane.contentPane.background = background
|
||||
}
|
||||
}
|
||||
|
||||
private fun isMacOs(): Boolean =
|
||||
System.getProperty("os.name").startsWith("Mac", ignoreCase = true)
|
||||
}
|
||||
Reference in New Issue
Block a user