diff --git a/src/main/kotlin/QuickLaunchMain.kt b/src/main/kotlin/QuickLaunchMain.kt index 949193c..13fa7ce 100644 --- a/src/main/kotlin/QuickLaunchMain.kt +++ b/src/main/kotlin/QuickLaunchMain.kt @@ -1,13 +1,39 @@ -import androidx.compose.animation.* +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.Spring import androidx.compose.animation.core.spring +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideInHorizontally +import androidx.compose.animation.slideOutHorizontally +import androidx.compose.animation.togetherWith import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.material.icons.Icons -import androidx.compose.material3.* -import androidx.compose.runtime.* +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.BiasAlignment import androidx.compose.ui.Modifier @@ -15,13 +41,22 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.BitmapPainter -import androidx.compose.ui.input.key.* +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.KeyEventType +import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.key.onKeyEvent +import androidx.compose.ui.input.key.type import androidx.compose.ui.res.loadImageBitmap import androidx.compose.ui.res.useResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.* +import androidx.compose.ui.window.DialogWindow +import androidx.compose.ui.window.Window +import androidx.compose.ui.window.WindowPosition +import androidx.compose.ui.window.application +import androidx.compose.ui.window.rememberDialogState +import androidx.compose.ui.window.rememberWindowState import notifications.NotificationCenter import theme.Minimize import theme.QuickLaunchTheme @@ -155,20 +190,20 @@ fun main() { minimize = { windowState.isMinimized = true }, openShortcuts = { openHelpWindow.value = true } ) - if (openHelpWindow.value) { - DialogWindow( - title = "Edit shortcuts", - onCloseRequest = { - openHelpWindow.value = false - ShortCutHandler.persistToStorage() - }, - state = rememberDialogState( - size = DpSize(800.dp, 600.dp), - position = WindowPosition(Alignment.Center) - ) - ) { - ShortcutEditWindow() - } + DialogWindow( + transparent = false, + visible = openHelpWindow.value, + title = "Edit shortcuts", + onCloseRequest = { + openHelpWindow.value = false + ShortCutHandler.persistToStorage() + }, + state = rememberDialogState( + size = DpSize(800.dp, 600.dp), + position = WindowPosition(Alignment.Center) + ) + ) { + ShortcutEditWindow() } } } diff --git a/src/main/kotlin/viewModel/ShortCutHandler.kt b/src/main/kotlin/viewModel/ShortCutHandler.kt index 827a8fb..0a29bee 100644 --- a/src/main/kotlin/viewModel/ShortCutHandler.kt +++ b/src/main/kotlin/viewModel/ShortCutHandler.kt @@ -10,13 +10,13 @@ import java.io.* object ShortCutHandler { private val currentPath: File = File(System.getProperty("user.home"), ".QuickLaunch") - private val shortcutsFile = File(currentPath,"shortcuts.json") - private val _shortcuts = MutableStateFlow>(emptyMap()) + private val shortcutsFile = File(currentPath, "shortcuts.json") + private val _shortcuts = MutableStateFlow>(mutableMapOf()) val shortcuts: StateFlow> = _shortcuts init { - if (!currentPath.exists()){ //TODO this is for config somewhere else maybe + if (!currentPath.exists()) { //TODO this is for config somewhere else maybe currentPath.mkdir() } readFromStorage() @@ -34,30 +34,44 @@ object ShortCutHandler { fun addShortcut(short: String, path: String) { _shortcuts.value = buildMap { - putAll(shortcuts.value) + putAll(_shortcuts.value) put(short, path) + }.toMutableMap() + } + + fun renameShortcutQuietly(oldShort: String, newShort: String) { + if (_shortcuts.value.containsKey(oldShort)) { + _shortcuts.value.remove(oldShort)?.let { + _shortcuts.value.put(newShort, it) + } + } + } + + fun updateShortcutQuietly(short: String, path: String){ + if (_shortcuts.value.containsKey(short)){ + _shortcuts.value[short] = path } } fun removeShortcut(short: String) { _shortcuts.value = buildMap { - putAll(shortcuts.value.filterNot { entry -> entry.key == short }) - } + putAll(_shortcuts.value.filterNot { entry -> entry.key == short }) + }.toMutableMap() } fun executeShortcut(short: String) { - shortcuts.value[short]?.let { + _shortcuts.value[short]?.let { ProcessBuilder(it.split(";")).start() } } fun persistToStorage() { _shortcuts.value = buildMap { - putAll(shortcuts.value.filter { entry -> entry.key.isNotEmpty() }) - } + putAll(_shortcuts.value.filter { entry -> entry.key.isNotEmpty() }) + }.toMutableMap() BufferedWriter(FileWriter(shortcutsFile)).use { it.write( - Json.Default.encodeToString(shortcuts.value) + Json.Default.encodeToString(_shortcuts.value) ) } } @@ -71,7 +85,7 @@ object ShortCutHandler { BufferedReader(FileReader(shortcutsFile)).use { _shortcuts.value = Json.Default.decodeFromString(it.readText()) } - } catch (j : SerializationException){ + } catch (j: SerializationException) { println("Empty configuration") } } diff --git a/src/main/kotlin/windows/ShortcutEditDialogWindow.kt b/src/main/kotlin/windows/ShortcutEditDialogWindow.kt index 760aa43..cbf9d00 100644 --- a/src/main/kotlin/windows/ShortcutEditDialogWindow.kt +++ b/src/main/kotlin/windows/ShortcutEditDialogWindow.kt @@ -2,17 +2,32 @@ package windows import androidx.compose.animation.animateContentSize import androidx.compose.desktop.ui.tooling.preview.Preview -import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Delete -import androidx.compose.material3.* -import androidx.compose.runtime.* +import androidx.compose.material3.FloatingActionButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @@ -52,8 +67,8 @@ fun ShortcutRow(entry: Pair) { modifier = Modifier.fillMaxWidth(0.1f), value = shState.value, onValueChange = { - ShortCutHandler.removeShortcut(shState.value) - ShortCutHandler.addShortcut(it, cmdState.value) + ShortCutHandler.renameShortcutQuietly(shState.value, it) + shState.value = it } ) @@ -63,16 +78,17 @@ fun ShortcutRow(entry: Pair) { modifier = Modifier.fillMaxWidth(0.85f), value = cmdState.value, onValueChange = { - ShortCutHandler.addShortcut(shState.value, it) + ShortCutHandler.updateShortcutQuietly(shState.value, it) + cmdState.value = it }, ) Box( - modifier = Modifier.width(30.dp).height(30.dp).clickable ( - indication = null, - interactionSource = remember { MutableInteractionSource() } - ) { - ShortCutHandler.removeShortcut(shState.value) - } + modifier = Modifier.width(30.dp).height(30.dp).clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() } + ) { + ShortCutHandler.removeShortcut(shState.value) + } ) { Icon( Icons.Default.Delete, @@ -87,17 +103,21 @@ fun ShortcutRow(entry: Pair) { @Preview @Composable fun AddFab() { - Surface ( + Surface( shadowElevation = 6.dp, color = FloatingActionButtonDefaults.containerColor, shape = FloatingActionButtonDefaults.shape, modifier = Modifier.clickable( indication = null, interactionSource = remember { MutableInteractionSource() } - ){ + ) { ShortCutHandler.addShortcut("", "") } ) { - Icon(Icons.Default.Add, "add", modifier = Modifier.width(56.dp).height(56.dp).padding(12.dp)) + Icon( + Icons.Default.Add, + "add", + modifier = Modifier.width(56.dp).height(56.dp).padding(12.dp) + ) } } \ No newline at end of file