quickshell: CacheServise

This commit is contained in:
2025-10-13 21:35:34 +02:00
parent 20821ef078
commit ba6c735850
13 changed files with 102 additions and 59 deletions

View File

@@ -303,8 +303,8 @@ binds {
Mod+L { spawn-sh "loginctl lock-session"; } Mod+L { spawn-sh "loginctl lock-session"; }
// Media // Media
XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ && wp-vol"; } XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"; }
XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%- && wp-vol"; } XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%-"; }
XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; } XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; }
XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; } XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; }
XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; } XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; }

View File

@@ -303,8 +303,8 @@ binds {
Mod+L { spawn-sh "loginctl lock-session"; } Mod+L { spawn-sh "loginctl lock-session"; }
// Media // Media
XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ && wp-vol"; } XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"; }
XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%- && wp-vol"; } XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%-"; }
XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; } XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; }
XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; } XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; }
XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; } XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; }

View File

@@ -1,5 +1,2 @@
# some sensitive files # some sensitive files
Location.json
GeoInfoToken.txt GeoInfoToken.txt
IpCache.json
Notifications.json

View File

@@ -1,7 +1,8 @@
{ {
"location": "Munich",
"notifications": { "notifications": {
"doNotDisturb": false, "doNotDisturb": false,
"lastSeenTs": 1760375164000 "lastSeenTs": 1760383655000
}, },
"primaryColor": "#89b4fa", "primaryColor": "#89b4fa",
"showLyricsBar": false "showLyricsBar": false

View File

@@ -5,6 +5,7 @@ import Quickshell
import Quickshell.Widgets import Quickshell.Widgets
import qs.Constants import qs.Constants
import qs.Services import qs.Services
import qs.Utils
Item { Item {
id: root id: root
@@ -12,24 +13,22 @@ Item {
property real maxWidth: 250 property real maxWidth: 250
property string fallbackIcon: "application-x-executable" property string fallbackIcon: "application-x-executable"
function getAppIcon() { function getAppIcon(appId) {
try { try {
const focusedWindow = Niri.getFocusedWindow(); if (appId) {
if (focusedWindow && focusedWindow.appId) {
try { try {
const idValue = focusedWindow.appId; const normalizedId = (typeof appId === 'string') ? appId : String(appId);
const normalizedId = (typeof idValue === 'string') ? idValue : String(idValue);
const iconResult = ThemeIcons.iconForAppId(normalizedId.toLowerCase()); const iconResult = ThemeIcons.iconForAppId(normalizedId.toLowerCase());
if (iconResult && iconResult !== "") if (iconResult && iconResult !== "")
return iconResult; return iconResult;
} catch (iconError) { } catch (iconError) {
console.warn("Error getting icon from CompositorService:", iconError); Logger.warn("FocusedWindow", "Error getting icon from CompositorService: " + iconError);
} }
} }
return ThemeIcons.iconFromName(root.fallbackIcon); return ThemeIcons.iconFromName(root.fallbackIcon);
} catch (e) { } catch (e) {
console.warn("Error in getAppIcon:", e); Logger.warn("FocusedWindow", "Error in getAppIcon:", e);
return ThemeIcons.iconFromName(root.fallbackIcon); return ThemeIcons.iconFromName(root.fallbackIcon);
} }
} }
@@ -55,7 +54,7 @@ Item {
id: windowIcon id: windowIcon
anchors.fill: parent anchors.fill: parent
source: getAppIcon() source: getAppIcon(Niri.focusedWindowAppId)
asynchronous: true asynchronous: true
smooth: true smooth: true
visible: source !== "" visible: source !== ""

View File

@@ -0,0 +1,31 @@
import QtQuick
import Quickshell
import Quickshell.Io
import qs.Utils
pragma Singleton
Singleton {
id: root
property string cacheDir: Quickshell.env("HOME") + "/.cache/quickshell/"
property var cacheFiles: ["Location.json", "Ip.json", "Notifications.json", "LyricsOffset.txt"]
property bool loaded: false
property string locationCacheFile: cacheDir + "Location.json"
property string ipCacheFile: cacheDir + "Ip.json"
property string notificationsCacheFile: cacheDir + "Notifications.json"
property string lyricsOffsetCacheFile: cacheDir + "LyricsOffset.txt"
Process {
id: process
running: true
command: ["sh", "-c", `mkdir -p ${cacheDir} && touch ${cacheDir + cacheFiles.join(` && touch ${cacheDir}`)}`]
onExited: (code, status) => {
if (code === 0)
root.loaded = true;
else
Logger.error("CacheService", `Failed to create cache files: ${command.join(" ")}`);
}
}
}

View File

@@ -7,6 +7,7 @@ pragma Singleton
Singleton { Singleton {
property alias ip: cacheFileAdapter.ip property alias ip: cacheFileAdapter.ip
property string cacheFilePath: CacheService.ipCacheFile
property string countryCode: "N/A" property string countryCode: "N/A"
property real fetchInterval: 120 // in s property real fetchInterval: 120 // in s
property real fetchTimeout: 10 // in s property real fetchTimeout: 10 // in s
@@ -150,7 +151,7 @@ Singleton {
FileView { FileView {
id: cacheFile id: cacheFile
path: Qt.resolvedUrl("../Assets/Config/IpCache.json") path: cacheFilePath
watchChanges: false watchChanges: false
onLoaded: { onLoaded: {
Logger.log("IpService", "Loaded IP from cache file: " + cacheFileAdapter.ip); Logger.log("IpService", "Loaded IP from cache file: " + cacheFileAdapter.ip);

View File

@@ -12,8 +12,8 @@ Singleton {
id: root id: root
property string locationName: "Munich" property string locationName: SettingsService.location
property string locationFile: Qt.resolvedUrl("../Assets/Config/Location.json") property string locationFile: CacheService.locationCacheFile
property int weatherUpdateFrequency: 30 * 60 // 30 minutes expressed in seconds property int weatherUpdateFrequency: 30 * 60 // 30 minutes expressed in seconds
property bool isFetchingWeather: false property bool isFetchingWeather: false
readonly property alias data: adapter // Used to access via LocationService.data.xxx from outside, best to use "adapter" inside the service. readonly property alias data: adapter // Used to access via LocationService.data.xxx from outside, best to use "adapter" inside the service.

View File

@@ -9,7 +9,7 @@ Singleton {
property int linesCount: 3 property int linesCount: 3
property int linesAhead: linesCount / 2 property int linesAhead: linesCount / 2
property int currentIndex: linesCount - linesAhead - 1 property int currentIndex: linesCount - linesAhead - 1
property string offsetFile: Qt.resolvedUrl("../Assets/Config/LyricsOffset.txt") property string offsetFile: CacheService.lyricsOffsetCacheFile
property int offset: 0 // in ms property int offset: 0 // in ms
property int offsetStep: 500 // in ms property int offsetStep: 500 // in ms
property int referenceCount: 0 property int referenceCount: 0
@@ -26,7 +26,7 @@ Singleton {
Logger.log("LyricsService", "Starting lyrics syncing"); Logger.log("LyricsService", "Starting lyrics syncing");
// fill lyrics with empty lines // fill lyrics with empty lines
lyrics = Array(linesCount).fill(" "); lyrics = Array(linesCount).fill(" ");
listenProcess.exec(["sh", "-c", `sl-wrap listen -l ${linesCount} -a ${linesAhead} -f ${offsetFile.slice(7)}`]); listenProcess.exec(["sh", "-c", `sl-wrap listen -l ${linesCount} -a ${linesAhead} -f ${offsetFile}`]);
} }
} }
@@ -127,17 +127,14 @@ Singleton {
writeOffset(); writeOffset();
} }
} catch (e) { } catch (e) {
Logger.log("LyricsService", "Error reading offset file:", e); Logger.error("LyricsService", "Error reading offset file:", e);
} }
} }
onLoadFailed: { onLoadFailed: {
Logger.log("LyricsService", "Error loading offset file:", errorString); Logger.error("LyricsService", "Error loading offset file:", errorString);
} }
onSaveFailed: { onSaveFailed: {
Logger.log("LyricsService", "Error saving offset file:", errorString); Logger.error("LyricsService", "Error saving offset file:", errorString);
}
onSaved: {
Logger.log("LyricsService", "Offset file saved.");
} }
} }

View File

@@ -14,15 +14,15 @@ Singleton {
property bool noFocus: focusedWindowId === -1 property bool noFocus: focusedWindowId === -1
property bool inOverview: false property bool inOverview: false
property string focusedWindowTitle: "" property string focusedWindowTitle: ""
// property string focusedWindowAppId: "" property string focusedWindowAppId: ""
function updateFocusedWindowTitle() { function updateFocusedWindowTitle() {
if (windows && windows[focusedWindowId]) { if (windows && windows[focusedWindowId]) {
focusedWindowTitle = windows[focusedWindowId].title || ""; focusedWindowTitle = windows[focusedWindowId].title || "";
// focusedWindowAppId = windows[focusedWindowId].appId || ""; focusedWindowAppId = windows[focusedWindowId].appId || "";
} else { } else {
focusedWindowTitle = ""; focusedWindowTitle = "";
// focusedWindowAppId = ""; focusedWindowAppId = "";
} }
} }
@@ -30,8 +30,6 @@ Singleton {
return (windows && windows[focusedWindowId]) || null; return (windows && windows[focusedWindowId]) || null;
} }
onWindowsChanged: updateFocusedWindowTitle()
onFocusedWindowIdChanged: updateFocusedWindowTitle()
Component.onCompleted: { Component.onCompleted: {
eventStream.running = true; eventStream.running = true;
} }
@@ -102,6 +100,7 @@ Singleton {
}; };
} }
root.windows = windowsMap; root.windows = windowsMap;
root.updateFocusedWindowTitle();
} catch (e) { } catch (e) {
Logger.error("Niri", "Error parsing windows event:", e); Logger.error("Niri", "Error parsing windows event:", e);
} }
@@ -120,6 +119,7 @@ Singleton {
} else { } else {
root.focusedWindowId = -1; root.focusedWindowId = -1;
} }
root.updateFocusedWindowTitle();
} catch (e) { } catch (e) {
Logger.error("Niri", "Error parsing window focus event:", e); Logger.error("Niri", "Error parsing window focus event:", e);
} }
@@ -155,9 +155,10 @@ Singleton {
root.windows[id] = targetWin; root.windows[id] = targetWin;
} }
if (isFocused) { if (isFocused) {
root.focusedWindowId = id; if (root.focusedWindowId !== id || needUpdateTitle){
if (needUpdateTitle) root.focusedWindowId = id;
root.updateFocusedWindowTitle(); root.updateFocusedWindowTitle();
}
} }
} }
@@ -169,6 +170,10 @@ Singleton {
const closedId = event.windowClosed.id; const closedId = event.windowClosed.id;
if (closedId && (root.windows && root.windows[closedId])) { if (closedId && (root.windows && root.windows[closedId])) {
delete root.windows[closedId]; delete root.windows[closedId];
if (root.focusedWindowId === closedId) {
root.focusedWindowId = -1;
root.updateFocusedWindowTitle();
}
} }
} catch (e) { } catch (e) {
Logger.error("Niri", "Error parsing window closed event:", e); Logger.error("Niri", "Error parsing window closed event:", e);

View File

@@ -16,7 +16,7 @@ Singleton {
// Configuration // Configuration
property int maxVisible: 5 property int maxVisible: 5
property int maxHistory: 100 property int maxHistory: 100
property string historyFile: Qt.resolvedUrl("../Assets/Config/Notifications.json") property string historyFile: CacheService.notificationsCacheFile
property string cacheDirImagesNotifications: Quickshell.env("HOME") + "/.cache/quickshell/notifications/" property string cacheDirImagesNotifications: Quickshell.env("HOME") + "/.cache/quickshell/notifications/"
property real lowUrgencyDuration: 3 property real lowUrgencyDuration: 3
property real normalUrgencyDuration: 8 property real normalUrgencyDuration: 8

View File

@@ -9,6 +9,7 @@ Singleton {
property alias primaryColor: adapter.primaryColor property alias primaryColor: adapter.primaryColor
property alias showLyricsBar: adapter.showLyricsBar property alias showLyricsBar: adapter.showLyricsBar
property alias notifications: adapter.notifications property alias notifications: adapter.notifications
property alias location: adapter.location
property string settingsFilePath: Qt.resolvedUrl("../Assets/Config/Settings.json") property string settingsFilePath: Qt.resolvedUrl("../Assets/Config/Settings.json")
FileView { FileView {
@@ -25,6 +26,7 @@ Singleton {
property string primaryColor: "#89b4fa" property string primaryColor: "#89b4fa"
property bool showLyricsBar: false property bool showLyricsBar: false
property JsonObject notifications property JsonObject notifications
property string location: "New York"
notifications: JsonObject { notifications: JsonObject {
property bool doNotDisturb: false property bool doNotDisturb: false

View File

@@ -10,38 +10,48 @@ import qs.Services
ShellRoot { ShellRoot {
id: root id: root
Notification { Loader {
id: notification id: loader
}
IPCService { active: CacheService.loaded
id: ipcService
}
Bar { sourceComponent: Item {
id: bar Notification {
} id: notification
}
Corners { IPCService {
id: corners id: ipcService
} }
CalendarPanel { Bar {
id: calendarPanel id: bar
}
objectName: "calendarPanel" Corners {
} id: corners
}
ControlCenterPanel { CalendarPanel {
id: controlCenterPanel id: calendarPanel
objectName: "controlCenterPanel" objectName: "calendarPanel"
} }
NotificationHistoryPanel { ControlCenterPanel {
id: notificationHistoryPanel id: controlCenterPanel
objectName: "controlCenterPanel"
}
NotificationHistoryPanel {
id: notificationHistoryPanel
objectName: "notificationHistoryPanel"
}
}
objectName: "notificationHistoryPanel"
} }
} }