ソースを参照

power menu api

milan jurkulák 2 年 前
親
コミット
9f4bffc883

+ 27 - 14
src/main/kotlin/eu/mjdev/desktop/components/appsmenu/AppsBottomBar.kt

@@ -3,17 +3,15 @@ package eu.mjdev.desktop.components.appsmenu
 import androidx.compose.desktop.ui.tooling.preview.Preview
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.automirrored.filled.ArrowBack
-import androidx.compose.material.icons.automirrored.filled.Logout
-import androidx.compose.material.icons.filled.PowerOff
-import androidx.compose.material.icons.filled.RestartAlt
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
 import eu.mjdev.desktop.components.icon.ShapedIcon
+import eu.mjdev.desktop.components.input.SearchField
+import eu.mjdev.desktop.icons.Icons
 import eu.mjdev.desktop.provider.DesktopScope.Companion.withDesktopScope
 
 @Suppress("FunctionName")
@@ -22,6 +20,7 @@ fun AppsBottomBar(
     modifier: Modifier = Modifier,
     backButtonVisible: Boolean = false,
     onContextMenuClick: () -> Unit = {},
+    onHideMenu: () -> Unit = {},
     onBackClick: () -> Unit = {}
 ) = withDesktopScope {
     Box(
@@ -32,7 +31,7 @@ fun AppsBottomBar(
         ) {
             if (backButtonVisible) {
                 ShapedIcon(
-                    imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+                    imageVector = Icons.BackArrow,
                     iconColor = borderColor,
                     iconBackgroundColor = iconsTintColor,
                     onRightClick = onContextMenuClick,
@@ -43,31 +42,45 @@ fun AppsBottomBar(
         Row(
             modifier = Modifier.align(Alignment.BottomCenter)
         ) {
-            // todo : center content if needed
+            SearchField(
+                modifier = Modifier.fillMaxWidth()
+            )
         }
         Row(
             modifier = Modifier.align(Alignment.BottomEnd)
         ) {
             ShapedIcon(
-                imageVector = Icons.Filled.RestartAlt,
+                imageVector = Icons.RestartComputer,
                 iconColor = borderColor,
                 iconBackgroundColor = iconsTintColor,
                 onRightClick = onContextMenuClick,
-                onClick = { api.restart() }
+                onClick = {
+                    onHideMenu()
+                    // todo : dialog
+                    api.restart()
+                }
             )
             ShapedIcon(
-                imageVector = Icons.AutoMirrored.Filled.Logout,
+                imageVector = Icons.PowerOffComputer,
                 iconColor = borderColor,
                 iconBackgroundColor = iconsTintColor,
                 onRightClick = onContextMenuClick,
-                onClick = { api.logOut() }
+                onClick = {
+                    onHideMenu()
+                    // todo : dialog
+                    api.suspend()
+                }
             )
             ShapedIcon(
-                imageVector = Icons.Filled.PowerOff,
+                imageVector = Icons.LogOutUser,
                 iconColor = borderColor,
                 iconBackgroundColor = iconsTintColor,
                 onRightClick = onContextMenuClick,
-                onClick = { api.shutdown() }
+                onClick = {
+                    onHideMenu()
+                    // todo : dialog
+                    api.logOut()
+                }
             )
         }
     }
@@ -75,4 +88,4 @@ fun AppsBottomBar(
 
 @Preview
 @Composable
-fun AppsBottomBarPreview() = AppsBottomBar()
+fun AppsBottomBarPreview() = AppsBottomBar()

+ 3 - 0
src/main/kotlin/eu/mjdev/desktop/components/appsmenu/AppsMenu.kt

@@ -192,6 +192,9 @@ fun AppsMenu(
                             .wrapContentHeight()
                             .background(backgroundColor),
                         backButtonVisible = items.firstOrNull() is App,
+                        onHideMenu = {
+                            menuState.hide()
+                        },
                         onBackClick = {
                             items = appCategories
                         },

+ 1 - 2
src/main/kotlin/eu/mjdev/desktop/components/controlcenter/pages/MainSettingsPage.kt

@@ -90,10 +90,9 @@ fun MainSettingsPage() = ControlCenterPage(
                     backgroundColor = backgroundColor,
                     shadowColor = borderColor.alpha(0.3f),
                     iconTintColor = iconsTintColor,
-//                    textColor = textColor,
                     onPowerButtonClick = {
                         // todo : dialog
-                        api.shutdown()
+                        api.logOut()
                     }
                 )
             }

+ 18 - 0
src/main/kotlin/eu/mjdev/desktop/components/input/SearchField.kt

@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package eu.mjdev.desktop.components.input
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+
+@Composable
+fun SearchField(
+    modifier: Modifier = Modifier
+) {
+}

+ 2 - 3
src/main/kotlin/eu/mjdev/desktop/data/App.kt

@@ -6,7 +6,6 @@ import eu.mjdev.desktop.extensions.Custom.command
 import eu.mjdev.desktop.extensions.Custom.commandLine
 import eu.mjdev.desktop.helpers.exception.EmptyException.Companion.EmptyException
 import eu.mjdev.desktop.helpers.system.Shell
-import eu.mjdev.desktop.provider.DesktopProvider
 import java.io.File
 
 @Suppress("unused", "MemberVisibilityCanBePrivate")
@@ -139,8 +138,8 @@ class App(
         }
     }
 
-    fun hasWindow(api: DesktopProvider): Boolean =
-        api.windowsManager.hasWindow(this)
+//    fun hasWindow(api: DesktopProvider): Boolean =
+//        api.windowsManager.hasWindow(this)
 
     override fun hashCode(): Int {
         var result = file?.hashCode() ?: 0

+ 2 - 3
src/main/kotlin/eu/mjdev/desktop/data/DesktopFile.kt

@@ -47,8 +47,8 @@ class DesktopFile(
     init {
         if (isApp && !isCorrect) {
             runCatching {
-                println("Correcting file: file:///$absolutePath")
-                println("Corrected file: file:///${correctedFile.absolutePath}")
+//                println("Correcting file: file:///$absolutePath")
+//                println("Corrected file: file:///${correctedFile.absolutePath}")
                 correctedFile.let { f ->
                     desktopSection?.StartupWMClass = fullAppName
                     desktopSection?.OnlyShowIn = mutableListOf()
@@ -198,7 +198,6 @@ class DesktopFile(
         var StartupWMClass: String
             get() = ParsedString(section[Prop_StartupWMClass]).trim()
             set(value) {
-                println("setting [$Prop_StartupWMClass] = $StartupWMClass")
                 section[Prop_StartupWMClass] = value
             }
     }

+ 6 - 3
src/main/kotlin/eu/mjdev/desktop/icons/Icons.kt

@@ -1,13 +1,12 @@
 package eu.mjdev.desktop.icons
 
 import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.automirrored.filled.Chat
-import androidx.compose.material.icons.automirrored.filled.Send
-import androidx.compose.material.icons.automirrored.filled.TextSnippet
+import androidx.compose.material.icons.automirrored.filled.*
 import androidx.compose.material.icons.filled.*
 
 @Suppress("unused")
 object Icons {
+    val BackArrow = Icons.AutoMirrored.Filled.ArrowBack
     val SendIcon = Icons.AutoMirrored.Filled.Send
     val TextFieldVisiblePassword = Icons.Filled.Visibility
     val TextFieldInVisiblePassword = Icons.Filled.VisibilityOff
@@ -16,4 +15,8 @@ object Icons {
     val Campaign = Icons.Filled.Campaign
     val Chat = Icons.AutoMirrored.Filled.Chat
     val User = Icons.Filled.AccountCircle
+    val LogOutUser = Icons.AutoMirrored.Filled.Logout
+    val PowerOffComputer = Icons.Filled.PowerOff
+    val RestartComputer = Icons.Filled.RestartAlt
+//    val SuspendComputer = Icons.Filled.Sleep
 }

+ 88 - 88
src/main/kotlin/eu/mjdev/desktop/provider/DesktopProvider.kt

@@ -1,36 +1,26 @@
 package eu.mjdev.desktop.provider
 
 import androidx.compose.runtime.*
-import androidx.compose.ui.graphics.ImageBitmap
-import androidx.compose.ui.graphics.toAwtImage
 import androidx.compose.ui.platform.*
 import androidx.compose.ui.unit.DpSize
 import androidx.compose.ui.unit.dp
 import coil3.ImageLoader
-import eu.mjdev.desktop.components.controlcenter.base.ControlCenterPage
 import eu.mjdev.desktop.components.controlcenter.pages.*
 import eu.mjdev.desktop.data.App
 import eu.mjdev.desktop.data.DesktopFile
 import eu.mjdev.desktop.data.User
 import eu.mjdev.desktop.extensions.Compose.asyncImageLoader
-import eu.mjdev.desktop.helpers.adb.AdbDiscover.Companion.adbDevicesHandler
-import eu.mjdev.desktop.helpers.bitmap.Bitmap
 import eu.mjdev.desktop.helpers.internal.Palette
 import eu.mjdev.desktop.managers.*
-import eu.mjdev.desktop.helpers.system.DBus
 import eu.mjdev.desktop.helpers.system.OsRelease
 import eu.mjdev.desktop.helpers.system.Shell
-import eu.mjdev.desktop.managers.WindowsManager
 import eu.mjdev.desktop.provider.AIProvider.AiPluginGemini
 import eu.mjdev.desktop.theme.gtk.GtkThemeHelper
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import java.awt.*
 import java.io.File
-import java.io.FileReader
 import java.net.URI
-import javax.script.ScriptEngine
-import javax.script.ScriptEngineManager
 import kotlin.system.exitProcess
 
 @Suppress("unused", "MemberVisibilityCanBePrivate", "SameParameterValue")
@@ -42,106 +32,111 @@ class DesktopProvider(
     val isFirstStart: Boolean = true, // todo
     val isInstalled: Boolean = false, // todo
 ) : AutoCloseable {
-    val scriptManager: ScriptEngineManager by lazy { ScriptEngineManager() }
-    val scriptEngine: ScriptEngine by lazy {
-        scriptManager.getEngineByName("JavaScript").apply {
-            // todo
-        }
-    }
+    //    val scriptManager: ScriptEngineManager by lazy { ScriptEngineManager() }
+//    val scriptEngine: ScriptEngine by lazy {
+//        scriptManager.getEngineByName("JavaScript").apply {
+//            // todo
+//        }
+//    }
     val osDetails by lazy { OsRelease() }
     val toolkit: Toolkit by lazy { Toolkit.getDefaultToolkit() }
-    val kcefHelper: KCEFHelper by lazy { KCEFHelper(this) }
-    val gnome: GnomeManager by lazy { GnomeManager() }
-    val connectionManager: ConnectivityManager by lazy { ConnectivityManager() }
-    val windowsManager: WindowsManager by lazy { WindowsManager(this) }
-    val dbus: DBus by lazy { DBus() }
+    val kcefHelper by lazy { KCEFHelper(this) }
+    val gnome by lazy { GnomeManager() }
+    val connectionManager by lazy { ConnectivityManager() }
+
+    //    val windowsManager by lazy { WindowsManager(this) }
+//    val dbus: DBus by lazy { DBus() }
     val ai: AIProvider by lazy {
         // todo user can configure
         AIProvider(scope, AiPluginGemini(scope))
     }
     val appsProvider by lazy { AppsProvider(this) }
-    val mounts by lazy {
-        FileSystemWatcher(scope) {
-            println("Mounted: ${this.targetDirectory}")
-        }
+
+    //    val mounts by lazy {
+//        FileSystemWatcher(scope) {
+//            println("Mounted: ${this.targetDirectory}")
+//        }
+//    }
+    val gtkTheme by lazy { GtkThemeHelper(this) }
+    val palette by lazy { Palette(this) }
+    val desktopUtils: Desktop by lazy {
+        Desktop.getDesktop()
     }
-    val gtkTheme: GtkThemeHelper by lazy { GtkThemeHelper(this) }
-    val palette: Palette by lazy { Palette(this) }
-    val homeDir: File
+
+    val homeDir
         get() = currentUser.homeDir
-    val allUsers: List<User>
+    val allUsers
         get() = User.allUsers
-    val machineName: String
+    val machineName
         get() = Shell.executeAndRead("hostname").trim()
 
     // todo state
     val currentUser: User
         get() = allUsers.firstOrNull { u -> u.isLoggedIn } ?: User.Nobody
-    val controlCenterPagesState: MutableState<List<ControlCenterPage>> = mutableStateOf(CONTROL_CENTER_PAGES)
-    var lastTheme: String = ""
-    val adbHandler = adbDevicesHandler(
-        coroutineScope = scope,
-        onAdded = { device ->
-            println("Device discovered : $device")
-            // when device connected
-        },
-        onRemoved = { device ->
-            println("Device removed : $device")
-            // when device removed
-        }
-    )
+
+    val controlCenterPagesState = mutableStateOf(CONTROL_CENTER_PAGES)
+
+//    val adbHandler = adbDevicesHandler(
+//        coroutineScope = scope,
+//        onAdded = { device ->
+//            println("Device discovered : $device")
+//            // when device connected
+//        },
+//        onRemoved = { device ->
+//            println("Device removed : $device")
+//            // when device removed
+//        }
+//    )
+
     val containerSize: DpSize
         get() = runCatching {
             toolkit.screenSize.let { screen -> DpSize(screen.width.dp, screen.height.dp) }
         }.getOrNull() ?: DpSize.Zero
+
     val isAlwaysOnTopSupported
         get() = runCatching {
             toolkit.isAlwaysOnTopSupported
         }.getOrNull() ?: false
+
     val cursorSize
         get() = toolkit.getBestCursorSize(32, 32).let {
             DpSize(it.width.dp, it.height.dp)
         }
-    val desktopUtils: Desktop by lazy {
-        Desktop.getDesktop()
-    }
+
     val controlCenterPages
         get() = controlCenterPagesState.value
+
     val graphicsEnvironment: GraphicsEnvironment
         get() = GraphicsEnvironment.getLocalGraphicsEnvironment()
+
     val graphicsDevice: GraphicsDevice
         get() = graphicsEnvironment.defaultScreenDevice
+
     val isTransparencySupported
         get() = graphicsDevice.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.TRANSLUCENT)
 
-    init {
-        runCatching {
-            mounts.init()
-        }
-        runCatching {
-            dbus.updateEnvironment()
-        }
-        runCatching {
-            lastTheme = gnome.getGTKTheme()
-        }
+//    init {
 //        runCatching {
-//            gnome.setGTKTheme(THEME_MJDEV)
+//            windowsManager.init()
 //        }
-    }
+//        runCatching {
+//            mounts.init()
+//        }
+//        runCatching {
+//            dbus.updateEnvironment()
+//        }
+//    }
 
     override fun close() {
 //        runCatching {
-//            gnome.setGTKTheme(lastTheme)
+//            mounts.dispose()
+//        }
+//        runCatching {
+//            kcefHelper.dispose()
+//        }
+//        runCatching {
+//            windowsManager.dispose()
 //        }
-        runCatching {
-            mounts.dispose()
-        }
-        runCatching {
-            kcefHelper.dispose()
-        }
-        runCatching {
-            windowsManager.dispose()
-        }
     }
 
     fun openMail(emailAddress: String) = runCatching {
@@ -172,13 +167,13 @@ class DesktopProvider(
         openFileInAssociated(File(filePath))
     }
 
-    fun runScript(script: String): Any = runCatching {
-        scriptEngine.eval(script)
-    }
+//    fun runScript(script: String): Any = runCatching {
+//        scriptEngine.eval(script)
+//    }
 
-    fun runScript(file: File): Any = runCatching {
-        scriptEngine.eval(FileReader(file))
-    }
+//    fun runScript(file: File): Any = runCatching {
+//        scriptEngine.eval(FileReader(file))
+//    }
 
     fun beep() = runCatching {
         toolkit.beep()
@@ -188,17 +183,17 @@ class DesktopProvider(
         toolkit.sync()
     }
 
-    fun createCustomCursor(cursor: Image, hotSpot: Point, name: String): Cursor? = runCatching {
-        toolkit.createCustomCursor(cursor, hotSpot, name)
-    }.getOrNull()
+//    fun createCustomCursor(cursor: Image, hotSpot: Point, name: String): Cursor? = runCatching {
+//        toolkit.createCustomCursor(cursor, hotSpot, name)
+//    }.getOrNull()
 
-    fun createCustomCursor(cursor: Bitmap, hotSpot: Point, name: String): Cursor? = runCatching {
-        toolkit.createCustomCursor(cursor.image, hotSpot, name)
-    }.getOrNull()
+//    fun createCustomCursor(cursor: Bitmap, hotSpot: Point, name: String): Cursor? = runCatching {
+//        toolkit.createCustomCursor(cursor.image, hotSpot, name)
+//    }.getOrNull()
 
-    fun createCustomCursor(cursor: ImageBitmap, hotSpot: Point, name: String): Cursor? = runCatching {
-        toolkit.createCustomCursor(cursor.toAwtImage(), hotSpot, name)
-    }.getOrNull()
+//    fun createCustomCursor(cursor: ImageBitmap, hotSpot: Point, name: String): Cursor? = runCatching {
+//        toolkit.createCustomCursor(cursor.toAwtImage(), hotSpot, name)
+//    }.getOrNull()
 
     // todo
 //    fun createCustomCursor(cursor: ImageVector, hotSpot: Point, name: String) =
@@ -213,19 +208,24 @@ class DesktopProvider(
         return true
     }
 
+    fun lock() {
+        Shell.executeAndRead("/usr/bin/loginctl", "lock-sessions")
+    }
+
     fun logOut() {
-        // todo
         exitProcess(0)
     }
 
+    fun suspend() {
+        Shell.executeAndRead("/usr/bin/systemctl", "suspend")
+    }
+
     fun shutdown() {
-        // todo
-        exitProcess(0)
+        Shell.executeAndRead("/usr/sbin/halt", "--poweroff")
     }
 
     fun restart() {
-        // todo
-        exitProcess(0)
+        Shell.executeAndRead("/usr/sbin/halt", "--reboot")
     }
 
     companion object {

+ 10 - 10
src/main/kotlin/eu/mjdev/desktop/provider/DesktopScope.kt

@@ -48,26 +48,26 @@ open class DesktopScope(
     val ai
         get() = api.ai
 
-    val adb
-        get() = api.adbHandler
+//    val adb
+//        get() = api.adbHandler
 
     val imageLoader
         get() = api.imageLoader
 
-    val scriptManager
-        get() = api.scriptManager
+//    val scriptManager
+//        get() = api.scriptManager
 
-    val scriptEngine
-        get() = api.scriptEngine
+//    val scriptEngine
+//        get() = api.scriptEngine
 
     val connectionManager
         get() = api.connectionManager
 
-    val windowsManager
-        get() = api.windowsManager
+//    val windowsManager
+//        get() = api.windowsManager
 
-    val dbus
-        get() = api.dbus
+//    val dbus
+//        get() = api.dbus
 
     val gnome
         get() = api.gnome