ソースを参照

mose press & drag fix

Milan Jurkulak 1 年間 前
親
コミット
a2d82f1444
18 ファイル変更、209 行追加、56 行削除
  1. 1 1
      build.gradle.kts
  2. 14 5
      composeApp/composeApp.gradle.kts
  3. 4 0
      composeApp/src/androidMain/kotlin/org/mjdev/desktop/app/App.kt
  4. 2 3
      composeApp/src/androidMain/kotlin/org/mjdev/desktop/extensions/ComponentActivity.kt
  5. 3 1
      composeApp/src/androidMain/kotlin/org/mjdev/desktop/managers/processes/ProcessManager.kt
  6. 25 6
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/appsmenu/components/AppsList.kt
  7. 2 1
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/appsmenu/components/AppsMenuCategory.kt
  8. 0 1
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/desktoppanel/applets/DesktopPanelDateTime.kt
  9. 1 0
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/desktoppanel/applets/DesktopPanelIcon.kt
  10. 6 3
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/context/DesktopContextScope.kt
  11. 6 3
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/context/IDesktopContext.kt
  12. 57 2
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/extensions/Modifier.kt
  13. 7 4
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/extensions/PathExt.kt
  14. 47 19
      composeApp/src/commonMain/kotlin/org/mjdev/desktop/log/Log.kt
  15. 2 0
      composeApp/src/desktopMain/kotlin/org/mjdev/desktop/helpers/application/Application.kt
  16. 7 1
      composeApp/src/desktopMain/kotlin/org/mjdev/desktop/main/Main.kt
  17. 13 1
      composeApp/src/desktopMain/kotlin/org/mjdev/desktop/managers/processes/ProcessManager.kt
  18. 12 5
      gradle/libs.versions.toml

+ 1 - 1
build.gradle.kts

@@ -1,5 +1,5 @@
 plugins {
-    alias(libs.plugins.devtools.ksp) apply false
+//    alias(libs.plugins.devtools.ksp) apply false
     alias(libs.plugins.android.application) apply false
     alias(libs.plugins.android.library) apply false
     alias(libs.plugins.compose) apply false

+ 14 - 5
composeApp/composeApp.gradle.kts

@@ -12,13 +12,10 @@ import org.jetbrains.compose.ComposeExtension
 import org.jetbrains.compose.desktop.DesktopExtension
 import org.jetbrains.compose.desktop.application.dsl.TargetFormat
 import org.jetbrains.compose.resources.ResourcesExtension
-import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
 import org.jetbrains.kotlin.gradle.dsl.JvmTarget
 import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
 import org.jetbrains.kotlin.gradle.dsl.KotlinTargetContainerWithPresetFunctions
-import org.jetbrains.kotlin.gradle.dsl.KotlinTargetContainerWithWasmPresetFunctions
 import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
-import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWasmJsTargetDsl
 import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
 
 //</editor-fold>------------------------------------------------------------------------------------
@@ -31,7 +28,7 @@ plugins {
     alias(libs.plugins.compose)
     alias(libs.plugins.compose.compiler)
     alias(libs.plugins.vlc.setup)
-    alias(libs.plugins.devtools.ksp)
+//    alias(libs.plugins.devtools.ksp)
 }
 
 //</editor-fold>------------------------------------------------------------------------------------
@@ -140,6 +137,11 @@ kotlin {
                 // lifecycles
                 implementation(libs.androidx.lifecycle.viewmodel)
                 implementation(libs.androidx.lifecycle.runtime.compose)
+                // log
+                implementation(libs.napier)
+                // crypto
+                implementation(libs.cryptography.core)
+                implementation(libs.cryptography.provider.optimal)
                 // date time
                 implementation(libs.kotlinx.datetime)
                 // images
@@ -291,12 +293,19 @@ android {
     }
     packaging {
         resources {
-            excludes += "/META-INF/{AL2.0,LGPL2.1}"
+            excludes += "META-INF/{AL2.0,LGPL2.1}"
+            excludes += "META-INF/INDEX.LIST"
+            excludes += "META-INF/DEPENDENCIES"
         }
     }
     buildTypes {
         getByName("release") {
+            isDebuggable = true
+            isJniDebuggable = true
             isMinifyEnabled = false
+            isShrinkResources = false
+//            isRenderscriptDebuggable = true
+            isPseudoLocalesEnabled = true
         }
     }
     compileOptions {

+ 4 - 0
composeApp/src/androidMain/kotlin/org/mjdev/desktop/app/App.kt

@@ -1,11 +1,15 @@
 package org.mjdev.desktop.app
 
 import android.app.Application
+import io.github.aakira.napier.DebugAntilog
+import io.github.aakira.napier.Napier
 import org.mjdev.desktop.helpers.crash.CrashHandler
+import org.mjdev.desktop.log.Log
 
 class App : Application() {
     override fun onCreate() {
         super.onCreate()
         CrashHandler.register(this, 200L)
+        Log.init()
     }
 }

+ 2 - 3
composeApp/src/androidMain/kotlin/org/mjdev/desktop/extensions/ComponentActivity.kt

@@ -1,6 +1,5 @@
 package org.mjdev.desktop.extensions
 
-import android.util.Log
 import android.view.WindowManager
 import androidx.activity.compose.BackHandler
 import androidx.compose.runtime.Composable
@@ -11,9 +10,9 @@ import androidx.core.view.WindowCompat
 import androidx.core.view.WindowInsetsCompat
 import androidx.core.view.WindowInsetsControllerCompat
 import org.mjdev.desktop.BuildConfig
-import org.mjdev.desktop.activity.MainActivity.Companion.TAG
 import org.mjdev.desktop.helpers.WakeLockHelper
 import androidx.core.graphics.drawable.toDrawable
+import org.mjdev.desktop.log.Log
 
 @Suppress("unused", "MemberVisibilityCanBePrivate")
 object ComponentActivityExt {
@@ -71,7 +70,7 @@ object ComponentActivityExt {
     fun OnBackPress(
         enabled: Boolean = !BuildConfig.DEBUG,
         action: () -> Unit = {
-            Log.d(TAG, "OnBackPressed")
+            Log.d("OnBackPressed")
         }
     ) = BackHandler(enabled, action)
 }

+ 3 - 1
composeApp/src/androidMain/kotlin/org/mjdev/desktop/managers/processes/ProcessManager.kt

@@ -8,12 +8,13 @@
 
 package org.mjdev.desktop.managers.processes
 
-import org.mjdev.desktop.interfaces.IApp
 import org.mjdev.desktop.context.IDesktopContext
+import org.mjdev.desktop.interfaces.IApp
 import org.mjdev.desktop.interfaces.IProcessListener
 import org.mjdev.desktop.managers.process.IProcessManager
 
 // todo dbus
+// todo strange error :  index (71) is out of bound of [0, 0)
 @Suppress("unused")
 class ProcessManager(
     private val context: IDesktopContext,
@@ -32,6 +33,7 @@ class ProcessManager(
     }
 
     override fun dispose() {
+        listeners.clear()
     }
 
     // todo

+ 25 - 6
composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/appsmenu/components/AppsList.kt

@@ -9,6 +9,10 @@
 package org.mjdev.desktop.components.appsmenu.components
 
 import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.draggable
+import androidx.compose.foundation.gestures.rememberDraggableState
+import androidx.compose.foundation.gestures.scrollBy
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.LazyListState
@@ -16,9 +20,13 @@ import androidx.compose.foundation.lazy.itemsIndexed
 import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.unit.dp
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 import org.mjdev.desktop.data.Category
 import org.mjdev.desktop.extensions.Colors.SuperDarkGray
 import org.mjdev.desktop.extensions.Colors.alpha
@@ -33,17 +41,28 @@ import org.jetbrains.compose.ui.tooling.preview.Preview
 fun AppsList(
     modifier: Modifier = Modifier,
     category: Category? = null,
+    items: List<Any> = listOf(),
     listState: LazyListState = rememberForeverLazyListState("AppsMenu"),
     onCategoryClick: DesktopContextScope.(Category) -> Unit = {},
     onCategoryContextMenuClick: DesktopContextScope.(Category) -> Unit = {},
     onAppClick: DesktopContextScope.(IApp) -> Unit = { app -> runAsync { app.start() } },
     onAppContextMenuClick: DesktopContextScope.(IApp) -> Unit = {},
-    items: List<Any> = listOf(),
-    onTooltip: (item: Any?) -> Unit = {}
+    onTooltip: (item: Any?) -> Unit = {},
 ) = withDesktopContext {
+    val state = if (category == null) listState else rememberLazyListState()
+    var clickEnabled = remember { true }
     LazyColumn(
-        modifier = modifier,
-        state = if (category == null) listState else rememberLazyListState(),
+        modifier = modifier.draggable(
+            orientation = Orientation.Horizontal,
+            state = rememberDraggableState { delta ->
+                runAsync {
+                    state.scrollBy(delta * 8) // todo remove magic number
+                }
+            },
+            onDragStarted = { clickEnabled = false },
+            onDragStopped = { clickEnabled = true },
+        ),
+        state = state,
     ) {
         when (items.firstOrNull()) {
             is Category -> {
@@ -52,8 +71,8 @@ fun AppsList(
                         category = item as Category,
                         showDivider = (items.size - 1) > idx,
                         dividerColor = textColor.alpha(0.3f),
-                        onClick = { onCategoryClick(item) },
-                        onContextMenuClick = { onCategoryContextMenuClick(item) },
+                        onClick = { if (clickEnabled) onCategoryClick(item) },
+                        onContextMenuClick = { if (clickEnabled) onCategoryContextMenuClick(item) },
                         onTooltip = onTooltip
                     )
                 }

+ 2 - 1
composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/appsmenu/components/AppsMenuCategory.kt

@@ -50,7 +50,8 @@ fun AppsMenuCategory(
     val categoryName = remember(category) { category.name }
     val materialIcon = remember(categoryName) { iconSet.iconForName(categoryName) ?: 0 }
     Column(
-        modifier = modifier.padding(vertical = 2.dp)
+        modifier = modifier
+            .padding(vertical = 2.dp)
             .onMousePress {
                 onLeftClick { onClick(category) }
                 onRightClick { onContextMenuClick(category) }

+ 0 - 1
composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/desktoppanel/applets/DesktopPanelDateTime.kt

@@ -23,7 +23,6 @@ import org.mjdev.desktop.extensions.Modifier.onMouseLeave
 import org.mjdev.desktop.extensions.MutableStateExt.rememberState
 import org.mjdev.desktop.context.DesktopContextScope.Companion.withDesktopContext
 import org.jetbrains.compose.ui.tooling.preview.Preview
-import org.mjdev.desktop.extensions.Modifier.onMousePress
 
 @Composable
 fun DesktopPanelDateTime(

+ 1 - 0
composeApp/src/commonMain/kotlin/org/mjdev/desktop/components/desktoppanel/applets/DesktopPanelIcon.kt

@@ -35,6 +35,7 @@ import org.mjdev.desktop.interfaces.IApp
 import org.jetbrains.compose.ui.tooling.preview.Preview
 import org.mjdev.desktop.extensions.PaddingValues.size
 
+// todo paddings
 @Composable
 fun DesktopPanelIcon(
     app: IApp? = null,

+ 6 - 3
composeApp/src/commonMain/kotlin/org/mjdev/desktop/context/DesktopContextScope.kt

@@ -7,6 +7,7 @@ import androidx.compose.ui.unit.DpSize
 import androidx.compose.ui.unit.dp
 import coil3.ImageLoader
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.Dispatchers
 import org.mjdev.desktop.data.Category
 import org.mjdev.desktop.interfaces.IApp
@@ -17,6 +18,7 @@ import org.mjdev.desktop.managers.process.IProcessManager
 import org.mjdev.desktop.interfaces.ITheme
 import org.mjdev.desktop.interfaces.IUser
 import kotlin.coroutines.CoroutineContext
+import kotlin.coroutines.EmptyCoroutineContext
 
 // todo theme user support
 @Suppress("unused", "MemberVisibilityCanBePrivate")
@@ -155,9 +157,10 @@ open class DesktopContextScope(
     fun dispose() = context.dispose()
 
     fun runAsync(
-        coroutineContext: CoroutineContext = Dispatchers.Default,
-        block: suspend () -> Unit
-    ) = context.runAsync(coroutineContext, block)
+        coroutineContext: CoroutineContext = EmptyCoroutineContext,
+        start: CoroutineStart = CoroutineStart.DEFAULT,
+        block: suspend CoroutineScope.() -> Unit
+    ) = context.runAsync(coroutineContext, start, block)
 
     companion object {
         @Suppress("ComposableNaming")

+ 6 - 3
composeApp/src/commonMain/kotlin/org/mjdev/desktop/context/IDesktopContext.kt

@@ -4,6 +4,7 @@ import androidx.compose.ui.unit.DpSize
 import coil3.ImageLoader
 import coil3.PlatformContext
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import org.mjdev.desktop.components.controlcenter.pages.about.AboutPage
@@ -37,6 +38,7 @@ import org.mjdev.desktop.managers.base.ManagerCache
 import org.mjdev.desktop.managers.keys.IKeyManager
 import org.mjdev.desktop.managers.palette.IPalette
 import kotlin.coroutines.CoroutineContext
+import kotlin.coroutines.EmptyCoroutineContext
 import kotlin.reflect.KClass
 import kotlin.reflect.KProperty
 
@@ -101,9 +103,10 @@ abstract class IDesktopContext : IDisposable {
     abstract fun createManager(cls: KClass<*>): IDelegate?
 
     fun runAsync(
-        context: CoroutineContext = Dispatchers.Default,
-        block: suspend () -> Unit
-    ) = scope.launch(context) { block() }
+        context: CoroutineContext = EmptyCoroutineContext,
+        start: CoroutineStart = CoroutineStart.DEFAULT,
+        block: suspend CoroutineScope.() -> Unit
+    ) = scope.launch(context, start, block)
 
     fun notify(
         message: String = "This is a test message",

+ 57 - 2
composeApp/src/commonMain/kotlin/org/mjdev/desktop/extensions/Modifier.kt

@@ -11,6 +11,7 @@ import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.composed
 import androidx.compose.ui.draw.clip
@@ -30,14 +31,16 @@ import androidx.compose.ui.input.pointer.AwaitPointerEventScope
 import androidx.compose.ui.input.pointer.PointerEvent
 import androidx.compose.ui.input.pointer.PointerEventPass
 import androidx.compose.ui.input.pointer.PointerEventType
+import androidx.compose.ui.input.pointer.isPrimaryPressed
 import androidx.compose.ui.input.pointer.isSecondaryPressed
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 
+@Suppress("unused")
+@OptIn(ExperimentalComposeUiApi::class)
 object Modifier {
-    @Stable
     @Composable
     fun Modifier.conditional(
         condition: Boolean,
@@ -157,7 +160,7 @@ object Modifier {
         pass: PointerEventPass = PointerEventPass.Main,
         onEvent: AwaitPointerEventScope.(event: PointerEvent) -> Unit
     ): Modifier = onPointerEvent(
-        eventType = PointerEventType.Press,
+        eventType = PointerEventType.Release,
         pass = pass,
         onEvent = onEvent
     )
@@ -193,6 +196,58 @@ object Modifier {
         if (isSecondary) block()
     }
 
+//    val PointerEvent.isConsumed
+//        get() = changes.firstOrNull()?.isConsumed ?: false
+
+//    val PointerEvent.isNotConsumed
+//        get() = isConsumed.not()
+
+//    val PointerEvent.isRelease
+//        get() = type == PointerEventType.Release
+
+//    val PointerEvent.isPress
+//        get() = type == PointerEventType.Press
+
+//    val PointerEvent.isPressed
+//        get() = changes.firstOrNull()?.pressed ?: false
+
+//    @OptIn(ExperimentalComposeUiApi::class)
+//    val PointerEvent.isLeftButton
+//        get() = buttons.isPrimaryPressed
+
+
+//    val PointerEvent.isRightButton
+//        get() = buttons.isSecondaryPressed
+
+//    val PointerEvent.isNotPressed
+//        get() = isPressed.not()
+
+//    fun Modifier.onLeftClick(
+//        onClick: () -> Unit
+//    ): Modifier = pointerInput(Unit) {
+//        awaitPointerEventScope {
+//            while (true) {
+//                val event = awaitPointerEvent(PointerEventPass.Main)
+//                if (event.isPressed && event.isNotConsumed && event.isLeftButton) {
+//                    onClick()
+//                }
+//            }
+//        }
+//    }
+
+//    fun Modifier.onRightClick(
+//        onClick: () -> Unit
+//    ): Modifier = pointerInput(Unit) {
+//        awaitPointerEventScope {
+//            while (true) {
+//                val event = awaitPointerEvent(PointerEventPass.Main)
+//                if (event.isPressed && event.isNotConsumed && event.isRightButton) {
+//                    onClick()
+//                }
+//            }
+//        }
+//    }
+
     @Stable
     @Composable
     fun Modifier.clipCircle() = clip(CircleShape)

+ 7 - 4
composeApp/src/commonMain/kotlin/org/mjdev/desktop/extensions/PathExt.kt

@@ -1,6 +1,7 @@
 package org.mjdev.desktop.extensions
 
 import okio.Path
+import org.mjdev.desktop.log.Log
 import org.mjdev.desktop.system.Filesystem
 
 @Suppress("unused", "MemberVisibilityCanBePrivate")
@@ -26,7 +27,7 @@ object PathExt {
         get() = Filesystem.isSymbolicLink(this)
 
     val Path.exists: Boolean
-        get() = Filesystem.fileExists(this)
+        get() = isFile || isDirectory
 
     val Path.parentFile: Path
         get() = this.parent ?: cwd
@@ -83,10 +84,12 @@ object PathExt {
         Filesystem.writeText(this, text)
 
     fun Path.mkdirs() =
-        Filesystem.createDir(this)
+        Filesystem.createDirectories(this)
 
-    fun Path.delete() = if (isDirectory) Filesystem.deleteDir(this)
-    else Filesystem.delete(this)
+    fun Path.delete() = if (isDirectory)
+        Filesystem.deleteDir(this)
+    else
+        Filesystem.delete(this)
 
     fun Path.createNewFile() =
         Filesystem.createNewFile(this)

+ 47 - 19
composeApp/src/commonMain/kotlin/org/mjdev/desktop/log/Log.kt

@@ -8,12 +8,15 @@
 
 package org.mjdev.desktop.log
 
+import io.github.aakira.napier.DebugAntilog
+import io.github.aakira.napier.Napier
 import okio.Path.Companion.toPath
 import org.mjdev.desktop.extensions.System.currentTimeMillis
 
-// todo colors
 object Log {
+    private var isInitialized = false
     private val creationDate = currentTimeMillis.toString()
+    // todo
     private val logFile = "/var/tmp/mjdev-desktop/log/$creationDate.log".toPath()
 //    private val logWriter = PrintWriter(logFile.apply {
 //        runCatching {
@@ -22,70 +25,95 @@ object Log {
 //        }
 //    })
 
+    fun init() {
+        if (!isInitialized) {
+            isInitialized = true
+            Napier.base(DebugAntilog())
+        }
+    }
+
     fun i(message: String) {
-        println(message)
+        init()
+        Napier.i(message)
+//        println(message)
 //        runCatching {
 //            logWriter.println(message)
 //        }
     }
 
     fun i(e: Throwable) {
-        e.stackTraceToString().also { message ->
-            println(message)
+        init()
+        Napier.i(e.message ?: "", e)
+//        e.stackTraceToString().also { message ->
+//            println(message)
 //            runCatching {
 //                logWriter.println(message)
 //            }
-        }
+//        }
     }
 
     fun d(message: String) {
-        println(message)
+        init()
+        Napier.d(message)
+//        println(message)
 //        runCatching {
 //            logWriter.println(message)
 //        }
     }
 
     fun d(e: Throwable) {
-        e.stackTraceToString().also { message ->
-            println(message)
+        init()
+        Napier.d(e.message ?: "", e)
+//        e.stackTraceToString().also { message ->
+//            println(message)
 //            runCatching {
 //                logWriter.println(message)
 //            }
-        }
+//        }
     }
 
     fun w(message: String) {
-        println(message)
+        init()
+        Napier.w(message)
+//        println(message)
 //        runCatching {
 //            logWriter.println(message)
 //        }
     }
 
     fun w(e: Throwable) {
-        e.stackTraceToString().also { message ->
-            println(message)
+        init()
+        Napier.w(e.message ?: "", e)
+//        e.stackTraceToString().also { message ->
+//            println(message)
 //            runCatching {
 //                logWriter.println(message)
 //            }
-        }
+//        }
     }
 
     fun e(message: String) {
-        RuntimeException(message).also { e -> e(e) }
+        init()
+        Napier.e(message)
+//        RuntimeException(message).also { e -> e(e) }
     }
 
     fun e(e: Throwable) {
-        e.stackTraceToString().also { message ->
-            println(message)
+        init()
+        Napier.e(e.message ?: "", e)
+//        e.stackTraceToString().also { message ->
+//            println(message)
 //            runCatching {
 //                logWriter.println(message)
 //            }
-        }
+//        }
     }
 
     fun e(message: String, e: Throwable) {
-        e(message)
-        e(e)
+        init()
+        Napier.e(message, e)
+//        e(message)
+//        e(e)
     }
 
 }

+ 2 - 0
composeApp/src/desktopMain/kotlin/org/mjdev/desktop/helpers/application/Application.kt

@@ -42,11 +42,13 @@ fun application(
     args: List<String> = emptyList(),
     exitProcessOnExit: Boolean = true,
     onExit: () -> Unit = {},
+    onStart: () -> Unit = {},
     content: @Composable ApplicationScope.() -> Unit
 ) {
     if (System.getProperty("compose.application.configure.swing.globals") == "true") {
         configureSwingGlobalsForCompose()
     }
+    onStart()
     runBlocking {
         awaitApplication(
             args,

+ 7 - 1
composeApp/src/desktopMain/kotlin/org/mjdev/desktop/main/Main.kt

@@ -2,12 +2,18 @@ package org.mjdev.desktop.main
 
 import org.mjdev.desktop.components.main.MainWindow
 import org.mjdev.desktop.helpers.application.application
+import org.mjdev.desktop.log.Log
 
 fun main(
     args: Array<String>
 ) = application(
     args = args.toList(),
-    exitProcessOnExit = true
+    exitProcessOnExit = true,
+    onStart = {
+        Log.init()
+    },
+    onExit = {
+    }
 ) {
     MainWindow()
 //    Notify(

+ 13 - 1
composeApp/src/desktopMain/kotlin/org/mjdev/desktop/managers/processes/ProcessManager.kt

@@ -18,6 +18,7 @@ import org.mjdev.desktop.extensions.Compose.orElse
 import org.mjdev.desktop.interfaces.IApp
 import org.mjdev.desktop.context.IDesktopContext
 import org.mjdev.desktop.interfaces.IProcessListener
+import org.mjdev.desktop.log.Log
 import org.mjdev.desktop.managers.process.IProcessManager
 import kotlin.jvm.optionals.getOrNull
 
@@ -27,9 +28,18 @@ class ProcessManager(
     context: IDesktopContext,
     private val checkDelay: Long = 1000L
 ) : IProcessManager {
-    override val size: Int get() = processes.size
+
     private val listeners = mutableListOf<IProcessListener>()
+
+    override val size: Int
+        get() = runCatching {
+            processes.size
+        }.onFailure { e ->
+            Log.e(e)
+        }.getOrElse { 0 }
+
     private var job: Job? = null
+
     private val processes = mutableStateListOf<ProcessWrapper>()
 
     init {
@@ -93,6 +103,8 @@ class ProcessManager(
                     (appFullName != null && pw.commandLine.contains(appFullName))
 
         }
+    }.onFailure { e ->
+        Log.e(e)
     }.getOrNull() ?: false
 
     companion object {

+ 12 - 5
gradle/libs.versions.toml

@@ -35,12 +35,12 @@ human-readable = "1.11.0"
 #i18n4k-core = "0.9.0"
 ini4j = "0.5.4"
 jetlime = "3.0.1"
-kotlin = "2.1.21"
+kotlin = "2.2.0"
 kotlinx-coroutines = "1.10.2"
 kotlinx-date-time = "0.6.2"
 #logback = "1.5.7"
 okhttp3 = "4.12.0"
-okio = "3.12.0"
+okio = "3.13.0"
 qrose = "1.0.1"
 tts = "3.0.0"
 ychat = "1.4.1"
@@ -60,17 +60,19 @@ junitVersion = "1.2.1"
 espressoCore = "3.6.1"
 appcompat = "1.7.1"
 material = "1.12.0"
-devtools-ksp = "2.1.21-2.0.1"
+#devtools-ksp = "2.1.21-2.0.1"
 vlc-setup = "0.1.0"
 vlcj = "4.11.0"
 jna = "5.17.0"
 image-comparison = "4.4.0"
 haze = "1.6.4"
 kotlinx-serialization-json = "1.8.1"
-ktor = "3.2.0"
+ktor = "3.1.0"
 flock = "0.1.0"
 markwon = "4.6.2"
 html2text = "-SNAPSHOT"
+napier = "2.7.1"
+cryptography = "0.5.0"
 ### libs ###########################################################################################
 [libraries]
 ####################################################################################################
@@ -166,6 +168,11 @@ flock-aigentic-openapi = { module = "community.flock.aigentic:openapi", version.
 markwon = { module = "io.noties.markwon:core", version.ref = "markwon" }
 # html 2 text
 html2text = { module = "com.github.BartoszJarocki:android-boilerpipe", version.ref = "html2text" }
+# logs
+napier = { module = "io.github.aakira:napier", version.ref = "napier" }
+# cryptography
+cryptography-core = { module = "dev.whyoleg.cryptography:cryptography-core", version.ref = "cryptography" }
+cryptography-provider-optimal = { module = "dev.whyoleg.cryptography:cryptography-provider-optimal", version.ref = "cryptography" }
 ### plugins ########################################################################################
 [plugins]
 ####################################################################################################
@@ -184,6 +191,6 @@ gradle-ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "gradle-kt
 #foojay-resolver-convention = { id ="org.gradle.toolchains.foojay-resolver-convention", version.ref = "foojay-resolver-convention" }
 manes-versions = { id = "com.github.ben-manes.versions", version.ref = "manes-versions" }
 kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
-devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "devtools-ksp" }
+#devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "devtools-ksp" }
 vlc-setup = { id = "ir.mahozad.vlc-setup", version.ref = "vlc-setup" }
 ####################################################################################################