| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- 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.helpers.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.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")
- class DesktopProvider(
- val scope: CoroutineScope = CoroutineScope(Dispatchers.IO),
- val imageLoader: ImageLoader? = null,
- val isDebug: Boolean = true
- ) : AutoCloseable {
- 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 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 gtkTheme: GtkThemeHelper by lazy { GtkThemeHelper(this) }
- val palette: Palette by lazy { Palette(this) }
- val homeDir: File
- get() = currentUser.homeDir
- val allUsers: List<User>
- get() = User.allUsers
- val machineName: String
- 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 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 {
- windowsManager.init()
- }
- runCatching {
- currentUser.theme.controlCenterExpandedWidth = containerSize.width.div(4)
- }
- runCatching {
- mounts.init()
- }
- runCatching {
- dbus.updateEnvironment()
- }
- runCatching {
- lastTheme = gnome.getGTKTheme()
- }
- // runCatching {
- // gnome.setGTKTheme(THEME_MJDEV)
- // }
- }
- override fun close() {
- // runCatching {
- // gnome.setGTKTheme(lastTheme)
- // }
- 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))
- }
- 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 logOut() {
- // todo
- exitProcess(0)
- }
- fun shutdown() {
- // todo
- exitProcess(0)
- }
- fun restart() {
- // todo
- exitProcess(0)
- }
- companion object {
- private val CONTROL_CENTER_PAGES = listOf(
- MainSettingsPage(),
- EthSettingsPage(),
- WifiSettingsPage(),
- BluetoothSettingsPage(),
- DisplaySettingsPage(),
- SoundSettingsPage(),
- AIPage(),
- DevicesPage()
- )
- val LocalDesktop = staticCompositionLocalOf {
- println("default empty desktop provider created")
- DesktopProvider()
- }
- @Composable
- fun rememberDesktopProvider(
- scope: CoroutineScope = rememberCoroutineScope(),
- imageLoader: ImageLoader = asyncImageLoader(),
- isDebug: Boolean = LocalInspectionMode.current,
- ) = remember {
- println("default initialized desktop provider created")
- DesktopProvider(
- scope,
- imageLoader,
- isDebug
- )
- }
- fun Desktop.startApp(app: App) {
- startApp(app.desktopFile)
- }
- fun Desktop.startApp(
- desktopFile: DesktopFile?
- ) {
- open(desktopFile?.file)
- }
- }
- }
|