diff options
| author | Bora Gülerman <49169566+eratoriele@users.noreply.github.com> | 2026-02-19 13:26:10 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-19 21:26:10 +1100 |
| commit | 40a255283083301b9503e1cbb9f0ea7db83e069a (patch) | |
| tree | b98f42e7dd34fffb87fb6f81c82fc93b091163b5 /modules/controlcenter | |
| parent | [CI] chore: update flake (diff) | |
| download | caelestia-shell-40a255283083301b9503e1cbb9f0ea7db83e069a.tar.gz caelestia-shell-40a255283083301b9503e1cbb9f0ea7db83e069a.tar.bz2 caelestia-shell-40a255283083301b9503e1cbb9f0ea7db83e069a.zip | |
launcher: add favorite apps (#946)
* launcher: add favorite apps
Favorite apps always appear above non-favorite apps
Accepts regex, same logic as #920
Added the same regex logic to hidden apps
Added util file may need to be relocated
* addressed requested changes
* fix: Renamed newly added util singleton
Also added a null check to favorite icon loader in AppItem.qml
* controlCenter/launcherPane: added favorite apps
added icons to the app list to indicate if they are favorited/hidden
marking as favorite/hidden is desabled if the other is selected
* favouriteApps: renamed from favorite to favourite
Also disabled favorite/hidden switch for entries added as regex
* appDb: added notify and emit to favoriteApps
* controlCentre/Launcher: Fixed bug with favourite switch not enabling itself when no hiddenApps exist
Added a comment to explain the enabled state of the switches
icon loader is now a single loader rather than two, hidden icon has
priority
* spelling mistakes
* fixed warning
* formatting fixes
Diffstat (limited to 'modules/controlcenter')
| -rw-r--r-- | modules/controlcenter/launcher/LauncherPane.qml | 92 |
1 files changed, 78 insertions, 14 deletions
diff --git a/modules/controlcenter/launcher/LauncherPane.qml b/modules/controlcenter/launcher/LauncherPane.qml index 0dd464f..b236cf9 100644 --- a/modules/controlcenter/launcher/LauncherPane.qml +++ b/modules/controlcenter/launcher/LauncherPane.qml @@ -24,6 +24,7 @@ Item { property var selectedApp: root.session.launcher.active property bool hideFromLauncherChecked: false + property bool favouriteChecked: false anchors.fill: parent @@ -43,16 +44,14 @@ Item { function updateToggleState() { if (!root.selectedApp) { root.hideFromLauncherChecked = false; + root.favouriteChecked = false; return; } const appId = root.selectedApp.id || root.selectedApp.entry?.id; - if (Config.launcher.hiddenApps && Config.launcher.hiddenApps.length > 0) { - root.hideFromLauncherChecked = Config.launcher.hiddenApps.includes(appId); - } else { - root.hideFromLauncherChecked = false; - } + root.hideFromLauncherChecked = Config.launcher.hiddenApps && Config.launcher.hiddenApps.length > 0 && Strings.testRegexList(Config.launcher.hiddenApps, appId); + root.favouriteChecked = Config.launcher.favouriteApps && Config.launcher.favouriteApps.length > 0 && Strings.testRegexList(Config.launcher.favouriteApps, appId); } function saveHiddenApps(isHidden) { @@ -83,6 +82,7 @@ Item { id: allAppsDb path: `${Paths.state}/apps.sqlite` + favouriteApps: Config.launcher.favouriteApps entries: DesktopEntries.applications.values } @@ -286,6 +286,7 @@ Item { id: appsListLoader Layout.fillWidth: true Layout.fillHeight: true + asynchronous: true active: true sourceComponent: StyledListView { @@ -305,7 +306,8 @@ Item { delegate: StyledRect { required property var modelData - width: parent ? parent.width : 0 + width: parent ? parent.width : 0 + implicitHeight: 40 readonly property bool isSelected: root.selectedApp === modelData @@ -353,9 +355,34 @@ Item { text: modelData.name || modelData.entry?.name || qsTr("Unknown") font.pointSize: Appearance.font.size.normal } - } - implicitHeight: 40 + Loader { + Layout.alignment: Qt.AlignVCenter + readonly property bool isHidden: modelData ? Strings.testRegexList(Config.launcher.hiddenApps, modelData.id) : false + readonly property bool isFav: modelData ? Strings.testRegexList(Config.launcher.favouriteApps, modelData.id) : false + active: isHidden || isFav + + sourceComponent: isHidden ? hiddenIcon : (isFav ? favouriteIcon : null) + } + + Component { + id: hiddenIcon + MaterialIcon { + text: "visibility_off" + fill: 1 + color: Colours.palette.m3primary + } + } + + Component { + id: favouriteIcon + MaterialIcon { + text: "favorite" + fill: 1 + color: Colours.palette.m3primary + } + } + } } } } @@ -440,13 +467,11 @@ Item { onDisplayedAppChanged: { if (displayedApp) { const appId = displayedApp.id || displayedApp.entry?.id; - if (Config.launcher.hiddenApps && Config.launcher.hiddenApps.length > 0) { - root.hideFromLauncherChecked = Config.launcher.hiddenApps.includes(appId); - } else { - root.hideFromLauncherChecked = false; - } + root.hideFromLauncherChecked = Config.launcher.hiddenApps && Config.launcher.hiddenApps.length > 0 && Strings.testRegexList(Config.launcher.hiddenApps, appId); + root.favouriteChecked = Config.launcher.favouriteApps && Config.launcher.favouriteApps.length > 0 && Strings.testRegexList(Config.launcher.favouriteApps, appId); } else { root.hideFromLauncherChecked = false; + root.favouriteChecked = false; } } } @@ -562,9 +587,48 @@ Item { SwitchRow { Layout.topMargin: Appearance.spacing.normal visible: appDetailsLayout.displayedApp !== null + label: qsTr("Mark as favourite") + checked: root.favouriteChecked + // disabled if: + // * app is hidden + // * app isn't in favouriteApps array but marked as favourite anyway + // ^^^ This means that this app is favourited because of a regex check + // this button can not toggle regexed apps + enabled: appDetailsLayout.displayedApp !== null && !root.hideFromLauncherChecked && (Config.launcher.favouriteApps.indexOf(appDetailsLayout.displayedApp.id || appDetailsLayout.displayedApp.entry?.id) !== -1 || !root.favouriteChecked) + opacity: enabled ? 1 : 0.6 + onToggled: checked => { + root.favouriteChecked = checked; + const app = appDetailsLayout.displayedApp; + if (app) { + const appId = app.id || app.entry?.id; + const favouriteApps = Config.launcher.favouriteApps ? [...Config.launcher.favouriteApps] : []; + if (checked) { + if (!favouriteApps.includes(appId)) { + favouriteApps.push(appId); + } + } else { + const index = favouriteApps.indexOf(appId); + if (index !== -1) { + favouriteApps.splice(index, 1); + } + } + Config.launcher.favouriteApps = favouriteApps; + Config.save(); + } + } + } + SwitchRow { + Layout.topMargin: Appearance.spacing.normal + visible: appDetailsLayout.displayedApp !== null label: qsTr("Hide from launcher") checked: root.hideFromLauncherChecked - enabled: appDetailsLayout.displayedApp !== null + // disabled if: + // * app is favourited + // * app isn't in hiddenApps array but marked as hidden anyway + // ^^^ This means that this app is hidden because of a regex check + // this button can not toggle regexed apps + enabled: appDetailsLayout.displayedApp !== null && !root.favouriteChecked && (Config.launcher.hiddenApps.indexOf(appDetailsLayout.displayedApp.id || appDetailsLayout.displayedApp.entry?.id) !== -1 || !root.hideFromLauncherChecked) + opacity: enabled ? 1 : 0.6 onToggled: checked => { root.hideFromLauncherChecked = checked; const app = appDetailsLayout.displayedApp; |