| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- package eu.mjdev.desktop.provider
- import androidx.compose.runtime.*
- import androidx.compose.ui.platform.LocalInspectionMode
- import androidx.compose.ui.unit.DpSize
- import androidx.compose.ui.unit.dp
- import coil3.ImageLoader
- 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.internal.Palette
- import eu.mjdev.desktop.helpers.system.Shell
- import eu.mjdev.desktop.managers.apps.AppsManager
- import eu.mjdev.desktop.managers.artificialintelligence.AIManager
- import eu.mjdev.desktop.managers.artificialintelligence.AIManager.Companion.aiManager
- import eu.mjdev.desktop.managers.artificialintelligence.plugins.AiPluginGemini
- import eu.mjdev.desktop.managers.connectivity.ConnectivityManager
- import eu.mjdev.desktop.managers.kcef.kcefManager
- import eu.mjdev.desktop.managers.os.osManager
- import eu.mjdev.desktop.managers.processes.ProcessManager
- import eu.mjdev.desktop.managers.theme.themeManager
- import kotlinx.coroutines.CoroutineScope
- import kotlinx.coroutines.Dispatchers
- import java.awt.Desktop
- import java.awt.GraphicsDevice
- import java.awt.GraphicsEnvironment
- import java.awt.Toolkit
- import java.io.File
- import java.net.URI
- import kotlin.system.exitProcess
- @Suppress("unused", "MemberVisibilityCanBePrivate", "SameParameterValue")
- class DesktopProvider(
- val scope: CoroutineScope = CoroutineScope(Dispatchers.IO),
- val args: List<String> = emptyList(),
- val imageLoader: ImageLoader? = null,
- val isDebug: Boolean = true,
- val isFirstStart: Boolean = true, // todo
- val isInstalled: Boolean = false, // todo
- ) : AutoCloseable {
- val osManager by lazy { osManager(this) }
- val toolkit: Toolkit by lazy { Toolkit.getDefaultToolkit() }
- val kcefHelper by lazy { kcefManager(this) }
- val connectionManager by lazy { ConnectivityManager() }
- val ai: AIManager by lazy {
- aiManager(this).apply {
- // todo user can configure
- pluginAI = AiPluginGemini(scope)
- }
- }
- val appsManager by lazy { AppsManager(this) }
- val themeManager by lazy { themeManager(this) }
- val palette by lazy { Palette(this) }
- val desktopUtils: Desktop by lazy { Desktop.getDesktop() }
- val processManager by lazy { ProcessManager() }
- // val windowsManager by lazy { WindowsManager(this) }
- // val dbus: DBus by lazy { DBus() }
- val homeDir
- get() = currentUser.homeDir
- val allUsers
- get() = User.allUsers
- val currentLocale get() = appsManager.currentLocale
- val machineName
- get() = osManager.machineName
- // todo state
- val currentUser: User
- get() = allUsers.firstOrNull { u -> u.isLoggedIn } ?: User.Nobody
- 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 isLandscapeMode: Boolean
- get() = containerSize.let { it.width > it.height }
- val isAlwaysOnTopSupported
- get() = runCatching {
- toolkit.isAlwaysOnTopSupported
- }.getOrNull() ?: false
- val cursorSize
- get() = toolkit.getBestCursorSize(32, 32).let {
- DpSize(it.width.dp, it.height.dp)
- }
- 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 {
- // windowsManager.init()
- // }
- // runCatching {
- // mounts.init()
- // }
- // runCatching {
- // dbus.updateEnvironment()
- // }
- // }
- override fun close() {
- processManager.close()
- // runCatching {
- // mounts.dispose()
- // }
- // runCatching {
- // kcefHelper.dispose()
- // }
- // runCatching {
- // windowsManager.dispose()
- // }
- }
- fun openMail(emailAddress: String) = runCatching {
- desktopUtils.mail(URI.create("mailto:$emailAddress"))
- }
- fun openBrowser(url: String) = runCatching {
- desktopUtils.browse(URI.create(url))
- }
- fun openDirectoryForFile(path: String) = runCatching {
- desktopUtils.browseFileDirectory(File(path))
- }
- fun moveToTrash(file: File) = runCatching {
- desktopUtils.moveToTrash(file)
- }
- fun moveToTrash(filePath: String) = runCatching {
- moveToTrash(File(filePath))
- }
- // todo, may be need another function
- fun open(what: String) {
- Shell.executeAndRead("xdg-open", what)
- }
- fun openFileInAssociated(file: File) = runCatching {
- desktopUtils.open(file)
- }
- fun openFileInAssociated(filePath: String) = runCatching {
- openFileInAssociated(File(filePath))
- }
- // fun runScript(script: String): Any = runCatching {
- // scriptEngine.eval(script)
- // }
- // fun runScript(file: File): Any = runCatching {
- // scriptEngine.eval(FileReader(file))
- // }
- fun beep() = runCatching {
- toolkit.beep()
- }
- fun sync() = runCatching {
- toolkit.sync()
- }
- // 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: ImageBitmap, hotSpot: Point, name: String): Cursor? = runCatching {
- // toolkit.createCustomCursor(cursor.toAwtImage(), hotSpot, name)
- // }.getOrNull()
- // todo
- // fun createCustomCursor(cursor: ImageVector, hotSpot: Point, name: String) =
- // toolkit.createCustomCursor(cursor, hotSpot, name)
- @Suppress("UNUSED_PARAMETER")
- fun login(
- user: String,
- password: String
- ): Boolean {
- // todo
- return true
- }
- fun lock() {
- Shell.executeAndRead("/usr/bin/loginctl", "lock-sessions")
- }
- fun logOut() {
- exitProcess(0)
- }
- fun suspend() {
- Shell.executeAndRead("/usr/bin/systemctl", "suspend")
- }
- fun shutdown() {
- Shell.executeAndRead("/usr/sbin/halt", "--poweroff")
- }
- fun restart() {
- Shell.executeAndRead("/usr/sbin/halt", "--reboot")
- }
- companion object {
- private val CONTROL_CENTER_PAGES = listOf(
- MainSettingsPage(),
- WifiSettingsPage(),
- EthSettingsPage(),
- SoundSettingsPage(),
- BluetoothSettingsPage(),
- DisplaySettingsPage(),
- DevicesPage(),
- AIPage(),
- )
- val LocalDesktop = staticCompositionLocalOf {
- println("default empty desktop provider created")
- DesktopProvider()
- }
- @Composable
- fun rememberDesktopProvider(
- scope: CoroutineScope = rememberCoroutineScope(),
- imageLoader: ImageLoader = asyncImageLoader(),
- isDebug: Boolean = LocalInspectionMode.current,
- args: List<String> = emptyList(),
- ) = remember {
- println("default initialized desktop provider created")
- DesktopProvider(
- scope = scope,
- imageLoader = imageLoader,
- args = args,
- isDebug = isDebug || args.contains("-d")
- )
- }
- fun Desktop.startApp(app: App) {
- startApp(app.desktopFile)
- }
- fun Desktop.startApp(
- desktopFile: DesktopFile?
- ) {
- open(desktopFile?.file)
- }
- }
- }
|