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"; }
// Media
XF86AudioRaiseVolume 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%- && 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%-"; }
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"; }
XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; }

View File

@@ -303,8 +303,8 @@ binds {
Mod+L { spawn-sh "loginctl lock-session"; }
// Media
XF86AudioRaiseVolume 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%- && 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%-"; }
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"; }
XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; }

View File

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

View File

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

View File

@@ -5,6 +5,7 @@ import Quickshell
import Quickshell.Widgets
import qs.Constants
import qs.Services
import qs.Utils
Item {
id: root
@@ -12,24 +13,22 @@ Item {
property real maxWidth: 250
property string fallbackIcon: "application-x-executable"
function getAppIcon() {
function getAppIcon(appId) {
try {
const focusedWindow = Niri.getFocusedWindow();
if (focusedWindow && focusedWindow.appId) {
if (appId) {
try {
const idValue = focusedWindow.appId;
const normalizedId = (typeof idValue === 'string') ? idValue : String(idValue);
const normalizedId = (typeof appId === 'string') ? appId : String(appId);
const iconResult = ThemeIcons.iconForAppId(normalizedId.toLowerCase());
if (iconResult && iconResult !== "")
return iconResult;
} catch (iconError) {
console.warn("Error getting icon from CompositorService:", iconError);
Logger.warn("FocusedWindow", "Error getting icon from CompositorService: " + iconError);
}
}
return ThemeIcons.iconFromName(root.fallbackIcon);
} catch (e) {
console.warn("Error in getAppIcon:", e);
Logger.warn("FocusedWindow", "Error in getAppIcon:", e);
return ThemeIcons.iconFromName(root.fallbackIcon);
}
}
@@ -55,7 +54,7 @@ Item {
id: windowIcon
anchors.fill: parent
source: getAppIcon()
source: getAppIcon(Niri.focusedWindowAppId)
asynchronous: true
smooth: true
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 {
property alias ip: cacheFileAdapter.ip
property string cacheFilePath: CacheService.ipCacheFile
property string countryCode: "N/A"
property real fetchInterval: 120 // in s
property real fetchTimeout: 10 // in s
@@ -150,7 +151,7 @@ Singleton {
FileView {
id: cacheFile
path: Qt.resolvedUrl("../Assets/Config/IpCache.json")
path: cacheFilePath
watchChanges: false
onLoaded: {
Logger.log("IpService", "Loaded IP from cache file: " + cacheFileAdapter.ip);

View File

@@ -12,8 +12,8 @@ Singleton {
id: root
property string locationName: "Munich"
property string locationFile: Qt.resolvedUrl("../Assets/Config/Location.json")
property string locationName: SettingsService.location
property string locationFile: CacheService.locationCacheFile
property int weatherUpdateFrequency: 30 * 60 // 30 minutes expressed in seconds
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.

View File

@@ -9,7 +9,7 @@ Singleton {
property int linesCount: 3
property int linesAhead: linesCount / 2
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 offsetStep: 500 // in ms
property int referenceCount: 0
@@ -26,7 +26,7 @@ Singleton {
Logger.log("LyricsService", "Starting lyrics syncing");
// fill lyrics with empty lines
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();
}
} catch (e) {
Logger.log("LyricsService", "Error reading offset file:", e);
Logger.error("LyricsService", "Error reading offset file:", e);
}
}
onLoadFailed: {
Logger.log("LyricsService", "Error loading offset file:", errorString);
Logger.error("LyricsService", "Error loading offset file:", errorString);
}
onSaveFailed: {
Logger.log("LyricsService", "Error saving offset file:", errorString);
}
onSaved: {
Logger.log("LyricsService", "Offset file saved.");
Logger.error("LyricsService", "Error saving offset file:", errorString);
}
}

View File

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

View File

@@ -16,7 +16,7 @@ Singleton {
// Configuration
property int maxVisible: 5
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 real lowUrgencyDuration: 3
property real normalUrgencyDuration: 8

View File

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

View File

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