Fix applauncher given 'ABSURDs' recommendations

This commit is contained in:
ly-sec 2025-07-11 23:40:07 +02:00
parent fdc3cb3745
commit 95b24a3fe1
10 changed files with 54 additions and 56 deletions

View file

@ -26,17 +26,22 @@ PanelWindow {
visible = true; visible = true;
shouldBeVisible = true; shouldBeVisible = true;
searchField.forceActiveFocus() searchField.forceActiveFocus()
root.selectedIndex = 0;
root.appModel = DesktopEntries.applications.values;
root.updateFilter();
} }
function hidePanel() { function hidePanel() {
shouldBeVisible = false; shouldBeVisible = false;
searchField.text = "";
root.selectedIndex = 0;
} }
Rectangle { Rectangle {
id: root id: root
width: 400 width: 400
height: 640 height: 640
x: (parent.width - width) / 2 // Horizontally centered x: (parent.width - width) / 2
color: Theme.backgroundPrimary color: Theme.backgroundPrimary
bottomLeftRadius: 28 bottomLeftRadius: 28
bottomRightRadius: 28 bottomRightRadius: 28
@ -44,8 +49,8 @@ PanelWindow {
property var appModel: DesktopEntries.applications.values property var appModel: DesktopEntries.applications.values
property var filteredApps: [] property var filteredApps: []
property int selectedIndex: 0 property int selectedIndex: 0
property int targetY: (parent.height - height) / 2 // Centered vertically property int targetY: (parent.height - height) / 2
y: appLauncherPanel.shouldBeVisible ? targetY : -height // Slide from above y: appLauncherPanel.shouldBeVisible ? targetY : -height
Behavior on y { Behavior on y {
NumberAnimation { duration: 300; easing.type: Easing.OutCubic } NumberAnimation { duration: 300; easing.type: Easing.OutCubic }
} }
@ -59,13 +64,10 @@ PanelWindow {
} }
} }
function isMathExpression(str) { function isMathExpression(str) {
// Allow numbers, operators, parentheses, decimal points, spaces
return /^[-+*/().0-9\s]+$/.test(str); return /^[-+*/().0-9\s]+$/.test(str);
} }
function safeEval(expr) { function safeEval(expr) {
// Only allow safe math expressions
try { try {
// eslint-disable-next-line no-eval
return Function('return (' + expr + ')')(); return Function('return (' + expr + ')')();
} catch (e) { } catch (e) {
return undefined; return undefined;
@ -99,7 +101,7 @@ PanelWindow {
results = results.concat(fuzzyResults.map(function(r) { return r.obj; })); results = results.concat(fuzzyResults.map(function(r) { return r.obj; }));
} }
root.filteredApps = results; root.filteredApps = results;
root.selectedIndex = 0; // reset selection root.selectedIndex = 0;
} }
function selectNext() { function selectNext() {
if (filteredApps.length > 0) if (filteredApps.length > 0)
@ -131,6 +133,7 @@ PanelWindow {
console.warn("Cannot launch app:", modelData.name, "missing execString or exec", modelData); console.warn("Cannot launch app:", modelData.name, "missing execString or exec", modelData);
} }
appLauncherPanel.hidePanel(); appLauncherPanel.hidePanel();
searchField.text = "";
} }
Component.onCompleted: updateFilter() Component.onCompleted: updateFilter()
ColumnLayout { ColumnLayout {
@ -192,6 +195,8 @@ PanelWindow {
leftPadding: 0 leftPadding: 0
rightPadding: 0 rightPadding: 0
font.bold: true font.bold: true
Component.onCompleted: contentItem.cursorColor = Theme.textPrimary
onActiveFocusChanged: contentItem.cursorColor = Theme.textPrimary
Keys.onDownPressed: root.selectNext() Keys.onDownPressed: root.selectNext()
Keys.onUpPressed: root.selectPrev() Keys.onUpPressed: root.selectPrev()
@ -220,7 +225,7 @@ PanelWindow {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: parent.innerPadding height: parent.innerPadding
visible: false // for layout only visible: false
} }
ListView { ListView {
id: appList id: appList

View file

@ -17,7 +17,7 @@ Rectangle {
property real currentPosition: 0 property real currentPosition: 0
property int selectedPlayerIndex: 0 property int selectedPlayerIndex: 0
// Get all available players // Returns available MPRIS players
function getAvailablePlayers() { function getAvailablePlayers() {
if (!Mpris.players || !Mpris.players.values) { if (!Mpris.players || !Mpris.players.values) {
return [] return []
@ -36,7 +36,7 @@ Rectangle {
return controllablePlayers return controllablePlayers
} }
// Find the active player // Returns active player or first available
function findActivePlayer() { function findActivePlayer() {
let availablePlayers = getAvailablePlayers() let availablePlayers = getAvailablePlayers()
if (availablePlayers.length === 0) { if (availablePlayers.length === 0) {
@ -52,7 +52,7 @@ Rectangle {
} }
} }
// Update current player // Updates currentPlayer and currentPosition
function updateCurrentPlayer() { function updateCurrentPlayer() {
let newPlayer = findActivePlayer() let newPlayer = findActivePlayer()
if (newPlayer !== currentPlayer) { if (newPlayer !== currentPlayer) {
@ -61,7 +61,7 @@ Rectangle {
} }
} }
// Timer to update progress bar position // Updates progress bar every second
Timer { Timer {
id: positionTimer id: positionTimer
interval: 1000 interval: 1000
@ -74,7 +74,7 @@ Rectangle {
} }
} }
// Monitor for player changes // Reacts to player list changes
Connections { Connections {
target: Mpris.players target: Mpris.players
function onValuesChanged() { function onValuesChanged() {
@ -92,7 +92,7 @@ Rectangle {
color: Theme.surface color: Theme.surface
radius: 18 radius: 18
// No music player available state // Show fallback UI if no player is available
Item { Item {
width: parent.width width: parent.width
height: parent.height height: parent.height
@ -120,25 +120,25 @@ Rectangle {
} }
} }
// Music player content // Main player UI
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: 18 anchors.margins: 18
spacing: 12 spacing: 12
visible: currentPlayer visible: currentPlayer
// Album artwork and track info row // Album art and spectrum
RowLayout { RowLayout {
spacing: 12 spacing: 12
Layout.fillWidth: true Layout.fillWidth: true
// Album artwork with circular spectrum visualizer, aligned left // Album art with spectrum
Item { Item {
id: albumArtContainer id: albumArtContainer
width: 96; height: 96 // enough for spectrum and art (will adjust if needed) width: 96; height: 96 // enough for spectrum and art (will adjust if needed)
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
// Circular spectrum visualizer behind album art // Spectrum visualizer
CircularSpectrum { CircularSpectrum {
id: spectrum id: spectrum
anchors.centerIn: parent anchors.centerIn: parent
@ -150,7 +150,7 @@ Rectangle {
z: 0 z: 0
} }
// Album art in the center // Album art image
Rectangle { Rectangle {
id: albumArtwork id: albumArtwork
width: 60; height: 60 width: 60; height: 60
@ -186,7 +186,7 @@ Rectangle {
} }
} }
// Fallback music icon // Fallback icon
Text { Text {
anchors.centerIn: parent anchors.centerIn: parent
text: "album" text: "album"
@ -198,7 +198,7 @@ Rectangle {
} }
} }
// Track info // Track metadata
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: 4 spacing: 4

View file

@ -30,8 +30,6 @@ PanelWindow {
slideAnim.from = width; slideAnim.from = width;
slideAnim.to = 0; slideAnim.to = 0;
slideAnim.running = true; slideAnim.running = true;
// Start system monitoring when sidebar becomes visible
if (systemMonitor) systemMonitor.startMonitoring(); if (systemMonitor) systemMonitor.startMonitoring();
if (weather) weather.startWeatherFetch(); if (weather) weather.startWeatherFetch();
if (systemWidget) systemWidget.panelVisible = true; if (systemWidget) systemWidget.panelVisible = true;
@ -57,8 +55,7 @@ PanelWindow {
onStopped: { onStopped: {
if (panelPopup.slideOffset === panelPopup.width) { if (panelPopup.slideOffset === panelPopup.width) {
panelPopup.visible = false; panelPopup.visible = false;
// Stop monitoring and background tasks when hidden
// Stop system monitoring when sidebar becomes hidden
if (systemMonitor) systemMonitor.stopMonitoring(); if (systemMonitor) systemMonitor.stopMonitoring();
if (weather) weather.stopWeatherFetch(); if (weather) weather.stopWeatherFetch();
if (systemWidget) systemWidget.panelVisible = false; if (systemWidget) systemWidget.panelVisible = false;

View file

@ -167,14 +167,13 @@ Rectangle {
// Timer to check if recording is active // Timer to check if recording is active
Timer { Timer {
interval: 2000 // Check every 2 seconds interval: 2000
repeat: true repeat: true
running: panelVisible running: panelVisible
onTriggered: checkRecordingStatus() onTriggered: checkRecordingStatus()
} }
function checkRecordingStatus() { function checkRecordingStatus() {
// Simple check - if we're recording but no process, reset state
if (isRecording) { if (isRecording) {
checkRecordingProcess.running = true checkRecordingProcess.running = true
} }
@ -186,8 +185,6 @@ Rectangle {
command: ["pgrep", "-f", "gpu-screen-recorder.*portal"] command: ["pgrep", "-f", "gpu-screen-recorder.*portal"]
onExited: function(exitCode, exitStatus) { onExited: function(exitCode, exitStatus) {
var isActuallyRecording = exitCode === 0 var isActuallyRecording = exitCode === 0
// If we think we're recording but process isn't running, reset state
if (isRecording && !isActuallyRecording) { if (isRecording && !isActuallyRecording) {
recordingStateMismatch(isActuallyRecording) recordingStateMismatch(isActuallyRecording)
} }

View file

@ -26,19 +26,19 @@ Rectangle {
anchors.margins: 18 anchors.margins: 18
spacing: 12 spacing: 12
// User Info Row // User info row
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: 12 spacing: 12
// Profile Image // Profile image
Rectangle { Rectangle {
width: 48 width: 48
height: 48 height: 48
radius: 24 radius: 24
color: Theme.accentPrimary color: Theme.accentPrimary
// Border overlay // Border
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: "transparent" color: "transparent"
@ -82,7 +82,7 @@ Rectangle {
} }
} }
// User Info // User info text
ColumnLayout { ColumnLayout {
spacing: 4 spacing: 4
Layout.fillWidth: true Layout.fillWidth: true
@ -101,12 +101,12 @@ Rectangle {
} }
} }
// Spacer to push button to the right // Spacer
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
} }
// System Menu Button - positioned all the way to the right // System menu button
Rectangle { Rectangle {
id: systemButton id: systemButton
width: 32 width: 32
@ -137,7 +137,7 @@ Rectangle {
} }
} }
// System Menu Popup - positioned below the button // System menu popup
Rectangle { Rectangle {
id: systemMenu id: systemMenu
width: 160 width: 160
@ -149,7 +149,7 @@ Rectangle {
visible: false visible: false
z: 9999 z: 9999
// Position relative to the system button using absolute positioning // Position below system button
x: systemButton.x + systemButton.width - width + 12 x: systemButton.x + systemButton.width - width + 12
y: systemButton.y + systemButton.height + 32 y: systemButton.y + systemButton.height + 32
@ -158,7 +158,7 @@ Rectangle {
anchors.margins: 8 anchors.margins: 8
spacing: 4 spacing: 4
// Lock Button // Lock button
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 36 Layout.preferredHeight: 36
@ -196,7 +196,7 @@ Rectangle {
} }
} }
// Reboot Button // Reboot button
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 36 Layout.preferredHeight: 36
@ -234,7 +234,7 @@ Rectangle {
} }
} }
// Logout Button // Logout button
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 36 Layout.preferredHeight: 36
@ -272,7 +272,7 @@ Rectangle {
} }
} }
// Shutdown Button // Shutdown button
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 36 Layout.preferredHeight: 36
@ -356,8 +356,6 @@ Rectangle {
} }
Component.onCompleted: { Component.onCompleted: {
// Don't update system info immediately - wait for panel to be visible
// updateSystemInfo() will be called when panelVisible becomes true
uptimeProcess.running = true uptimeProcess.running = true
} }

View file

@ -16,7 +16,6 @@ Rectangle {
property real diskUsage: 0 property real diskUsage: 0
property bool isVisible: false property bool isVisible: false
// Timers to control when processes run
Timer { Timer {
id: cpuTimer id: cpuTimer
interval: 2000 interval: 2000

View file

@ -24,7 +24,6 @@ PanelWindow {
command: ["ls", Settings.wallpaperFolder !== undefined ? Settings.wallpaperFolder : ""] command: ["ls", Settings.wallpaperFolder !== undefined ? Settings.wallpaperFolder : ""]
stdout: StdioCollector { stdout: StdioCollector {
onStreamFinished: { onStreamFinished: {
// Split by newlines and filter out empty lines
wallpaperPanelModal.wallpapers = this.text.split("\n").filter(function(x){return x.length > 0}) wallpaperPanelModal.wallpapers = this.text.split("\n").filter(function(x){return x.length > 0})
} }
} }

View file

@ -59,12 +59,12 @@ Rectangle {
spacing: 12 spacing: 12
Layout.fillWidth: true Layout.fillWidth: true
// Weather icon and basic info // Weather icon and basic info section
RowLayout { RowLayout {
spacing: 12 spacing: 12
Layout.preferredWidth: 140 Layout.preferredWidth: 140
// Material Symbol icon // Weather icon
Text { Text {
id: weatherIcon id: weatherIcon
text: weatherData && weatherData.current_weather ? materialSymbolForCode(weatherData.current_weather.weathercode) : "cloud" text: weatherData && weatherData.current_weather ? materialSymbolForCode(weatherData.current_weather.weathercode) : "cloud"
@ -116,7 +116,7 @@ Rectangle {
Layout.bottomMargin: 2 Layout.bottomMargin: 2
} }
// 5-day forecast row (smaller) // 5-day forecast row
RowLayout { RowLayout {
spacing: 12 spacing: 12
Layout.fillWidth: true Layout.fillWidth: true
@ -129,7 +129,7 @@ Rectangle {
spacing: 2 spacing: 2
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Text { Text {
// Day name (e.g., Mon) // Day of the week (e.g., Mon)
text: Qt.formatDateTime(new Date(weatherData.daily.time[index]), "ddd") text: Qt.formatDateTime(new Date(weatherData.daily.time[index]), "ddd")
font.pixelSize: 12 font.pixelSize: 12
color: Theme.textSecondary color: Theme.textSecondary
@ -157,7 +157,7 @@ Rectangle {
} }
} }
// Error message (if any) // Error message
Text { Text {
text: errorString text: errorString
color: Theme.error color: Theme.error
@ -169,9 +169,8 @@ Rectangle {
} }
} }
// Weather code to Material Symbol ligature // Weather code to Material Symbol ligature mapping
function materialSymbolForCode(code) { function materialSymbolForCode(code) {
// Open-Meteo WMO code mapping
if (code === 0) return "sunny"; // Clear if (code === 0) return "sunny"; // Clear
if (code === 1 || code === 2) return "partly_cloudy_day"; // Mainly clear/partly cloudy if (code === 1 || code === 2) return "partly_cloudy_day"; // Mainly clear/partly cloudy
if (code === 3) return "cloud"; // Overcast if (code === 3) return "cloud"; // Overcast

View file

@ -18,7 +18,7 @@ Item {
} }
function signalIcon(signal) { function signalIcon(signal) {
if (signal >= 80) return "network_wifi"; if (signal >= 80) return "network_wifi_4_bar";
if (signal >= 60) return "network_wifi_3_bar"; if (signal >= 60) return "network_wifi_3_bar";
if (signal >= 40) return "network_wifi_2_bar"; if (signal >= 40) return "network_wifi_2_bar";
if (signal >= 20) return "network_wifi_1_bar"; if (signal >= 20) return "network_wifi_1_bar";
@ -69,7 +69,7 @@ Item {
property string connectStatusSsid: "" property string connectStatusSsid: ""
property string connectError: "" property string connectError: ""
property string connectSecurity: "" property string connectSecurity: ""
property var pendingConnect: null // store connect params for after delete property var pendingConnect: null
property string detectedInterface: "" property string detectedInterface: ""
property var connectionsToDelete: [] property var connectionsToDelete: []
@ -112,7 +112,7 @@ Item {
} }
} }
// Disconnect, then delete the profile. This chain is triggered by clicking the row. // Disconnect, delete profile, refresh
Process { Process {
id: disconnectProfileProcess id: disconnectProfileProcess
property string connectionName: "" property string connectionName: ""
@ -120,7 +120,6 @@ Item {
command: ["nmcli", "connection", "down", "id", connectionName] command: ["nmcli", "connection", "down", "id", connectionName]
onRunningChanged: { onRunningChanged: {
if (!running) { if (!running) {
// After disconnect, delete the profile
deleteProfileProcess.connectionName = connectionName; deleteProfileProcess.connectionName = connectionName;
deleteProfileProcess.running = true; deleteProfileProcess.running = true;
} }
@ -164,6 +163,7 @@ Item {
} }
} }
// Handles connecting to a Wi-Fi network, with or without password
Process { Process {
id: connectProcess id: connectProcess
property string ssid: "" property string ssid: ""
@ -202,6 +202,7 @@ Item {
} }
} }
// Finds the correct Wi-Fi interface for connection
Process { Process {
id: getInterfaceProcess id: getInterfaceProcess
running: false running: false
@ -235,6 +236,7 @@ Item {
} }
} }
// Adds a new Wi-Fi connection profile
Process { Process {
id: addConnectionProcess id: addConnectionProcess
property string ifname: "" property string ifname: ""
@ -267,6 +269,7 @@ Item {
} }
} }
// Brings up the new connection profile and finalizes connection state
Process { Process {
id: upConnectionProcess id: upConnectionProcess
property string profileName: "" property string profileName: ""

View file

@ -32,6 +32,7 @@ Scope {
NotificationServer { NotificationServer {
id: notificationServer id: notificationServer
onNotification: function(notification) { onNotification: function(notification) {
console.log("Notification received:", notification.appName);
notification.tracked = true; notification.tracked = true;
notificationPopup.addNotification(notification); notificationPopup.addNotification(notification);
} }