Add temporary reload button to applauncher

This commit is contained in:
lysec 2025-07-25 13:19:21 +02:00
parent b6a0adac56
commit f2df117732

View file

@ -11,23 +11,6 @@ import "../../Helpers/Fuzzysort.js" as Fuzzysort
PanelWithOverlay {
id: appLauncherPanel
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
function isPinned(app) {
return app && app.execString && Settings.settings.pinnedExecs.indexOf(app.execString) !== -1;
}
function togglePin(app) {
if (!app || !app.execString) return;
var arr = Settings.settings.pinnedExecs ? Settings.settings.pinnedExecs.slice() : [];
var idx = arr.indexOf(app.execString);
if (idx === -1) {
arr.push(app.execString);
} else {
arr.splice(idx, 1);
}
Settings.settings.pinnedExecs = arr;
root.updateFilter();
}
function showAt() {
appLauncherPanelRect.showAt();
}
@ -143,22 +126,7 @@ PanelWithOverlay {
return r.obj;
}));
}
// Pinning logic: split into pinned and unpinned
var pinned = [];
var unpinned = [];
for (var i = 0; i < results.length; ++i) {
var app = results[i];
if (app.execString && Settings.settings.pinnedExecs.indexOf(app.execString) !== -1) {
pinned.push(app);
} else {
unpinned.push(app);
}
}
// Sort pinned alphabetically
pinned.sort(function(a, b) {
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
});
root.filteredApps = pinned.concat(unpinned);
root.filteredApps = results;
root.selectedIndex = 0;
}
function selectNext() {
@ -175,15 +143,12 @@ PanelWithOverlay {
return;
var modelData = filteredApps[selectedIndex];
const termEmu = Quickshell.env("TERMINAL") || Quickshell.env("TERM_PROGRAM") || "";
if (modelData.isCalculator) {
Qt.callLater(function () {
Quickshell.clipboardText = String(modelData.result);
Quickshell.execDetached(["notify-send", "Calculator Result", `${modelData.expr} = ${modelData.result} (copied to clipboard)`]);
});
} else if (modelData.runInTerminal && termEmu){
Quickshell.execDetached([termEmu, "-e", modelData.execString.trim()]);
} else if (modelData.execute) {
modelData.execute();
} else {
@ -208,69 +173,116 @@ PanelWithOverlay {
anchors.margins: 32
spacing: 18
// Search Bar
Rectangle {
id: searchBar
color: Theme.surfaceVariant
radius: 22
height: 48
// Search Bar Row
RowLayout {
spacing: 12
Layout.fillWidth: true
border.color: searchField.activeFocus ? Theme.accentPrimary : Theme.outline
border.width: searchField.activeFocus ? 2 : 1
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 14
anchors.rightMargin: 14
spacing: 10
// Search Bar
Rectangle {
id: searchBar
color: Theme.surfaceVariant
radius: 22
height: 48
Layout.fillWidth: true
Layout.preferredWidth: 320 // Made the search bar narrower
border.color: searchField.activeFocus ? Theme.accentPrimary : Theme.outline
border.width: searchField.activeFocus ? 2 : 1
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 14
anchors.rightMargin: 14
spacing: 10
Text {
text: "search"
font.family: "Material Symbols Outlined"
font.pixelSize: Theme.fontSizeHeader
color: searchField.activeFocus ? Theme.accentPrimary : Theme.textSecondary
verticalAlignment: Text.AlignVCenter
Layout.alignment: Qt.AlignVCenter
}
TextField {
id: searchField
placeholderText: "Search apps..."
color: Theme.textPrimary
placeholderTextColor: Theme.textSecondary
background: null
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeBody
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
onTextChanged: root.updateFilter()
selectedTextColor: Theme.onAccent
selectionColor: Theme.accentPrimary
padding: 0
verticalAlignment: TextInput.AlignVCenter
leftPadding: 0
rightPadding: 0
topPadding: 0
bottomPadding: 0
font.bold: true
Component.onCompleted: contentItem.cursorColor = Theme.textPrimary
onActiveFocusChanged: contentItem.cursorColor = Theme.textPrimary
Keys.onDownPressed: root.selectNext()
Keys.onUpPressed: root.selectPrev()
Keys.onEnterPressed: root.activateSelected()
Keys.onReturnPressed: root.activateSelected()
Keys.onEscapePressed: appLauncherPanel.hidePanel()
}
}
Behavior on border.color {
ColorAnimation {
duration: 120
}
}
Behavior on border.width {
NumberAnimation {
duration: 120
}
}
}
// Added rectangle with onClick
Rectangle {
id: actionButton
width: 48
height: 48
radius: 20
color: mouseArea.containsPress ? Theme.accentPrimary : Theme.surfaceVariant
border.color: mouseArea.containsMouse ? Theme.accentPrimary : Theme.outline
border.width: 2
Text {
text: "search"
text: "refresh"
font.family: "Material Symbols Outlined"
font.pixelSize: Theme.fontSizeHeader
color: searchField.activeFocus ? Theme.accentPrimary : Theme.textSecondary
verticalAlignment: Text.AlignVCenter
Layout.alignment: Qt.AlignVCenter
color: mouseArea.containsMouse ? Theme.accentPrimary : Theme.textPrimary
anchors.centerIn: parent
}
TextField {
id: searchField
placeholderText: "Search apps..."
color: Theme.textPrimary
placeholderTextColor: Theme.textSecondary
background: null
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeBody
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
onTextChanged: root.updateFilter()
selectedTextColor: Theme.onAccent
selectionColor: Theme.accentPrimary
padding: 0
verticalAlignment: TextInput.AlignVCenter
leftPadding: 0
rightPadding: 0
topPadding: 0
bottomPadding: 0
font.bold: true
Component.onCompleted: contentItem.cursorColor = Theme.textPrimary
onActiveFocusChanged: contentItem.cursorColor = Theme.textPrimary
Keys.onDownPressed: root.selectNext()
Keys.onUpPressed: root.selectPrev()
Keys.onEnterPressed: root.activateSelected()
Keys.onReturnPressed: root.activateSelected()
Keys.onEscapePressed: appLauncherPanel.hidePanel()
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
Quickshell.reload(true);
}
cursorShape: Qt.PointingHandCursor
}
}
Behavior on border.color {
ColorAnimation {
duration: 120
Behavior on color {
ColorAnimation {
duration: 120
}
}
}
Behavior on border.width {
NumberAnimation {
duration: 120
Behavior on border.color {
ColorAnimation {
duration: 120
}
}
}
}
@ -308,14 +320,10 @@ PanelWithOverlay {
Rectangle {
anchors.fill: parent
color: (hovered || isSelected)
? Theme.accentPrimary
: (appLauncherPanel.isPinned(modelData) ? Theme.surfaceVariant : "transparent")
color: hovered || isSelected ? Theme.accentPrimary : "transparent"
radius: 12
border.color: appLauncherPanel.isPinned(modelData)
? "transparent"
: (hovered || isSelected ? Theme.accentPrimary : "transparent")
border.width: appLauncherPanel.isPinned(modelData) ? 0 : (hovered || isSelected ? 2 : 0)
border.color: hovered || isSelected ? Theme.accentPrimary : "transparent"
border.width: hovered || isSelected ? 2 : 0
Behavior on color {
ColorAnimation {
duration: 120
@ -367,7 +375,7 @@ PanelWithOverlay {
spacing: 1
Text {
text: modelData.name
color: (hovered || isSelected) ? Theme.onAccent : (appLauncherPanel.isPinned(modelData) ? Theme.textPrimary : Theme.textPrimary)
color: hovered || isSelected ? Theme.onAccent : Theme.textPrimary
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.bold: hovered || isSelected
@ -377,7 +385,7 @@ PanelWithOverlay {
}
Text {
text: modelData.isCalculator ? (modelData.expr + " = " + modelData.result) : (modelData.comment || modelData.genericName || "No description available")
color: (hovered || isSelected) ? Theme.onAccent : (appLauncherPanel.isPinned(modelData) ? Theme.textSecondary : Theme.textSecondary)
color: hovered || isSelected ? Theme.onAccent : Theme.textSecondary
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeCaption
font.italic: !(modelData.comment || modelData.genericName)
@ -394,14 +402,9 @@ PanelWithOverlay {
text: modelData.isCalculator ? "content_copy" : "chevron_right"
font.family: "Material Symbols Outlined"
font.pixelSize: Theme.fontSizeBody
color: (hovered || isSelected)
? Theme.onAccent
: (appLauncherPanel.isPinned(modelData) ? Theme.textPrimary : Theme.textSecondary)
color: hovered || isSelected ? Theme.onAccent : Theme.textSecondary
verticalAlignment: Text.AlignVCenter
Layout.rightMargin: 8 // Add margin to separate from star
}
// Add a spacing item between chevron and star
Item { width: 8; height: 1 }
}
Rectangle {
@ -415,14 +418,7 @@ PanelWithOverlay {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
// Prevent app launch if click is inside pinArea
if (pinArea.containsMouse) return;
if (mouse.button === Qt.RightButton) {
appLauncherPanel.togglePin(modelData);
return;
}
ripple.opacity = 0.18;
rippleNumberAnimation.start();
root.selectedIndex = index;
@ -449,37 +445,6 @@ PanelWithOverlay {
color: Theme.outline
opacity: index === appList.count - 1 ? 0 : 0.10
}
// Pin/Unpin button (move to last child for stacking)
Item {
id: pinArea
width: 28; height: 28
z: 100 // Ensure above everything else
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
MouseArea {
anchors.fill: parent
preventStealing: true
z: 100
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
propagateComposedEvents: false
onClicked: {
appLauncherPanel.togglePin(modelData);
event.accepted = true;
}
}
Text {
anchors.centerIn: parent
text: "star"
font.family: "Material Symbols Outlined"
font.pixelSize: Theme.fontSizeSmall
color: (parent.MouseArea.containsMouse || hovered || isSelected)
? Theme.onAccent
: (appLauncherPanel.isPinned(modelData) ? Theme.textPrimary : Theme.textDisabled)
verticalAlignment: Text.AlignVCenter
}
}
}
}
}