Build native UI shell foundation

This commit is contained in:
2026-07-04 10:41:51 +02:00
parent 89a99582a5
commit 6bcfc534a0
34 changed files with 1998 additions and 794 deletions

View File

@@ -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 =
AndroidPlatformLogStore(appDataDir, policy)
actual fun platformNowMillis(): Long = System.currentTimeMillis()
private class AndroidPlatformLogStore(
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"))
}
}
}

View File

@@ -0,0 +1,40 @@
package com.vnidrop.app.platform
import android.app.Activity
import android.os.Build
import android.view.View
import android.view.WindowInsetsController
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalView
@Composable
actual fun PlatformSystemAppearance(isDarkTheme: Boolean) {
val view = LocalView.current
if (view.isInEditMode) return
SideEffect {
val window = (view.context as? Activity)?.window ?: return@SideEffect
window.statusBarColor = Color.Transparent.toArgb()
window.navigationBarColor = Color.Transparent.toArgb()
val useDarkIcons = systemBarIconModeForTheme(isDarkTheme) == SystemBarIconMode.DarkIcons
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val lightBars = WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS or
WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
window.insetsController?.setSystemBarsAppearance(if (useDarkIcons) lightBars else 0, lightBars)
} else {
var flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
if (useDarkIcons) {
flags = flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
flags = flags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
}
}
window.decorView.systemUiVisibility = flags
}
}
}