qs: update

This commit is contained in:
2026-03-08 03:30:05 +01:00
parent ad6486c141
commit 0d13a02e29
11 changed files with 196 additions and 141 deletions
+2 -1
View File
@@ -13,7 +13,8 @@ binds {
Mod+C { spawn "code"; }
Mod+E { spawn "dolphin" "--new-window"; }
Mod+W { spawn-sh "zen || zen-browser"; }
Mod+X { spawn "gnome-text-editor" "--new-window"; }
Mod+X { spawn "qs" "ipc" "call" "notes" "openRecent"; }
Mod+Shift+X { spawn "qs" "ipc" "call" "notes" "createNote"; }
Mod+B { spawn-sh "pkill -x -n btop || wezterm -e btop"; }
Mod+Shift+T { spawn "wezterm"; }
Mod+Shift+Return { spawn "wezterm"; }
@@ -72,18 +72,18 @@ Variants {
RowLayout {
id: leftLayout
height: parent.height - 10
height: parent.height - Style.marginXS * 2
anchors {
left: parent.left
verticalCenter: parent.verticalCenter
leftMargin: 5
leftMargin: Style.marginXS
}
UIconButton {
textOverride: "󰣇"
fontFamily: Fonts.nerd
baseSize: parent.height - Style.marginXXS * 2
baseSize: parent.height - Style.marginXS * 2
iconSize: Style.fontNerd
colorFg: Colors.distro
onClicked: () => {
@@ -121,7 +121,7 @@ Variants {
RowLayout {
id: middleLayout
height: parent.height - 10
height: parent.height - Style.marginXS * 2
anchors {
horizontalCenter: parent.horizontalCenter
@@ -136,68 +136,127 @@ Variants {
RowLayout {
id: rightLayout
height: parent.height - 10
height: parent.height - Style.marginXS * 2
anchors {
right: parent.right
verticalCenter: parent.verticalCenter
rightMargin: 5
rightMargin: Style.marginXS
}
Loader {
sourceComponent: LyricsService.showLyricsBar ? lyricsComponent : monitorsComponent
Connections {
target: LyricsService
onShowLyricsBarChanged: {
if (LyricsService.showLyricsBar) {
LyricsService.registerComponent("LyricsBar");
SystemStatService.unregisterComponent("BarMonitors");
} else {
LyricsService.unregisterComponent("LyricsBar");
SystemStatService.registerComponent("BarMonitors");
}
}
}
Component {
id: monitorsComponent
Item {
Layout.fillHeight: true
Layout.fillWidth: true
RowLayout {
id: monitorsLayout
RowLayout {
id: monitorsLayout
height: rightLayout.height
spacing: Style.marginM
Component.onCompleted: {
anchors.right: parent.right
height: parent.height
y: LyricsService.showLyricsBar ? Style.barHeight : 0
opacity: LyricsService.showLyricsBar ? 0 : 1
spacing: Style.marginM
Component.onCompleted: {
if (!LyricsService.showLyricsBar)
SystemStatService.registerComponent("BarMonitors");
}
Component.onDestruction: {
SystemStatService.unregisterComponent("BarMonitors");
}
NetworkSpeed {
}
Separator {
}
RecordIndicator {
}
Ip {
}
CpuTemp {
}
MemUsage {
}
CpuUsage {
}
Battery {
}
Brightness {
screen: modelData
}
Volume {
}
Behavior on y {
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
NetworkSpeed {
}
}
Separator {
}
RecordIndicator {
}
Ip {
}
CpuTemp {
}
MemUsage {
}
CpuUsage {
}
Battery {
}
Brightness {
screen: modelData
}
Volume {
Behavior on opacity {
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
}
}
Component {
id: lyricsComponent
LyricsBar {
id: lyricsBar
anchors.right: parent.right
height: parent.height
y: LyricsService.showLyricsBar ? 0 : -Style.barHeight
opacity: LyricsService.showLyricsBar ? 1 : 0
Component.onCompleted: {
if (LyricsService.showLyricsBar)
LyricsService.registerComponent("LyricsBar");
}
Component.onDestruction: {
LyricsService.unregisterComponent("LyricsBar");
}
Behavior on y {
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
}
Behavior on opacity {
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
LyricsBar {
}
}
@@ -208,18 +267,18 @@ Variants {
}
RowLayout {
height: rightLayout.height
Layout.fillHeight: true
spacing: Style.marginS
TrayExpander {
screen: modelData
baseSize: rightLayout.height - Style.marginXXS * 2
baseSize: rightLayout.height - Style.marginXS * 2
}
UIconButton {
iconName: Caffeine.isInhibited ? "mug-off" : "mug"
colorFg: Caffeine.isInhibited ? Colors.mOrange : Colors.mYellow
baseSize: rightLayout.height - Style.marginXXS * 2
baseSize: rightLayout.height - Style.marginXS * 2
alwaysHover: Caffeine.isInhibited
onClicked: () => {
Caffeine.manualToggle();
@@ -229,7 +288,7 @@ Variants {
UIconButton {
iconName: "power"
colorFg: Colors.mRed
baseSize: rightLayout.height - Style.marginXXS * 2
baseSize: rightLayout.height - Style.marginXS * 2
onClicked: () => {
BarService.toggleRight();
}
@@ -10,12 +10,6 @@ Rectangle {
color: Colors.mSurface
border.color: Colors.mPrimary
border.width: Style.borderS
Component.onCompleted: {
LyricsService.startSyncing();
}
Component.onDestruction: {
LyricsService.stopSyncing();
}
implicitHeight: Style.barHeight - Style.marginXS * 2
implicitWidth: 600
@@ -148,14 +148,12 @@ UBox {
Layout.fillHeight: true
clip: true
Loader {
id: btContentLoader
BluetoothCard {
width: parent.width
height: parent.height
x: root.currentPanel === "bluetooth" ? 0 : -width
opacity: root.currentPanel === "bluetooth" ? 1 : 0
sourceComponent: bluetoothComponent
anchors.margins: Style.marginS
Behavior on x {
NumberAnimation {
@@ -175,14 +173,12 @@ UBox {
}
Loader {
id: wifiContentLoader
WifiCard {
width: parent.width
height: parent.height
x: root.currentPanel === "wifi" ? 0 : width
opacity: root.currentPanel === "wifi" ? 1 : 0
sourceComponent: wifiComponent
anchors.margins: Style.marginS
Behavior on x {
NumberAnimation {
@@ -202,26 +198,6 @@ UBox {
}
Component {
id: bluetoothComponent
BluetoothCard {
anchors.fill: parent
anchors.margins: Style.marginS
}
}
Component {
id: wifiComponent
WifiCard {
anchors.fill: parent
anchors.margins: Style.marginS
}
}
}
}
@@ -10,10 +10,10 @@ UBox {
id: lyricsBox
Component.onCompleted: {
LyricsService.startSyncing();
LyricsService.registerComponent("LyricsCard");
}
Component.onDestruction: {
LyricsService.stopSyncing();
LyricsService.unregisterComponent("LyricsCard");
}
ColumnLayout {
@@ -129,4 +129,16 @@ Item {
target: "brightness"
}
IpcHandler {
function openRecent() {
NotesService.openRecent();
}
function createNote() {
NotesService.createNote();
}
target: "notes"
}
}
@@ -15,7 +15,10 @@ Singleton {
readonly property string offsetFile: Paths.cacheDir + "/spotify-lyrics-offset.txt"
property int offset: 0 // in ms
readonly property int offsetStep: 500 // in ms
property int referenceCount: 0
property var _registered: ({
})
readonly property int _registeredCount: Object.keys(_registered).length
readonly property bool shouldRun: _registeredCount > 0
// with linesCount=3 and linesAhead=1, lyrics will be like:
// line 1
// line 2 <- current line
@@ -30,29 +33,35 @@ Singleton {
}
function startSyncing() {
referenceCount++;
Logger.d("LyricsService", "Reference count:", referenceCount);
if (referenceCount === 1) {
Logger.d("LyricsService", "Starting lyrics syncing");
// fill lyrics with empty lines
lyrics = Array(linesCount).fill(" ");
listenProcess.exec(["sh", "-c", `pkill -x spotify-lyrics -u $USER; spotify-lyrics listen -l ${linesCount} -a ${linesAhead} -f ${offsetFile}`]);
}
Logger.d("Lyrics", "Starting lyrics syncing");
// fill lyrics with empty lines
lyrics = Array(linesCount).fill(" ");
listenProcess.exec(["sh", "-c", `pkill -x spotify-lyrics -u $USER; spotify-lyrics listen -l ${linesCount} -a ${linesAhead} -f ${offsetFile}`]);
}
function stopSyncing() {
referenceCount--;
Logger.d("LyricsService", "Reference count:", referenceCount);
if (referenceCount <= 0) {
Logger.d("LyricsService", "Stopping lyrics syncing");
// kinda ugly but works, meanwhile:
// listenProcess.signal(9)
// listenProcess.signal(15)
// listenProcess.running = false
// counting on exec() to terminate previous exec()
// all don't work
listenProcess.exec(["sh", "-c", `pkill -x spotify-lyrics -u $USER`]);
}
Logger.d("Lyrics", "Stopping lyrics syncing");
// kinda ugly but works, meanwhile:
// listenProcess.signal(9)
// listenProcess.signal(15)
// listenProcess.running = false
// counting on exec() to terminate previous exec()
// all don't work
Quickshell.execDetached(["sh", "-c", `pkill -x spotify-lyrics -u $USER`]);
}
function registerComponent(componentId) {
root._registered[componentId] = true;
root._registered = Object.assign({
}, root._registered);
Logger.d("Lyrics", "Component registered:", componentId, "- total:", root._registeredCount);
}
function unregisterComponent(componentId) {
delete root._registered[componentId];
root._registered = Object.assign({
}, root._registered);
Logger.d("Lyrics", "Component unregistered:", componentId, "- total:", root._registeredCount);
}
function writeOffset() {
@@ -90,6 +99,12 @@ Singleton {
writeOffset();
}
onShouldRunChanged: {
if (shouldRun)
startSyncing();
else
stopSyncing();
}
Process {
id: listenProcess
@@ -129,7 +144,7 @@ Singleton {
const val = parseInt(fileContents);
if (!isNaN(val)) {
offset = val;
Logger.d("LyricsService", "Loaded offset:", offset);
Logger.d("Lyrics", "Loaded offset:", offset);
} else {
offset = 0;
writeOffset();
@@ -139,14 +154,14 @@ Singleton {
writeOffset();
}
} catch (e) {
Logger.e("LyricsService", "Error reading offset file:", e);
Logger.e("Lyrics", "Error reading offset file:", e);
}
}
onLoadFailed: {
Logger.e("LyricsService", "Error loading offset file.");
Logger.e("Lyrics", "Error loading offset file.");
}
onSaveFailed: {
Logger.e("LyricsService", "Error saving offset file.");
Logger.e("Lyrics", "Error saving offset file.");
}
}
@@ -9,6 +9,7 @@ Singleton {
id: root
property ListModel notesModel
property string recentNotePath: ""
function createNote() {
if (createProcess.running) {
@@ -36,9 +37,17 @@ Singleton {
}
function openNote(path) {
recentNotePath = path;
Quickshell.execDetached(["wezterm", "start", "--", "sh", "-c", `exec nvim "${path}"`]);
}
function openRecent() {
if (recentNotePath)
openNote(recentNotePath);
else
createNote();
}
function strToColor(str) {
let hash = 5381;
for (let i = 0; i < str.length; i++) {
@@ -86,6 +95,12 @@ Singleton {
break;
}
}
if (recentNotePath === currentPath)
if (notesModel.count > 0)
recentNotePath = notesModel.get(0).notePath;
else
recentNotePath = "";;
currentPath = "";
}
}
@@ -94,7 +109,7 @@ Singleton {
id: initProcess
running: true
command: ["sh", "-c", "ls -p -tr " + Paths.notesDir]
command: ["sh", "-c", "ls -p -t " + Paths.notesDir]
stdout: StdioCollector {
id: listCollector
@@ -113,6 +128,9 @@ Singleton {
});
Logger.d("Notes", "Loaded note: " + fileName);
}
if (notesModel.count > 0)
recentNotePath = notesModel.get(0).notePath;
}
}
+2 -13
View File
@@ -1,14 +1,3 @@
#!/usr/bin/env bash
#!/bin/sh
# Description:
# Wrapper for fzfclip to ensure only one instance is
# running and to launch it in terminal.
exec {LOCK_FD}>/tmp/"$(basename "$0")".lock
flock -n "$LOCK_FD" || {
echo "Another instance is running. Exiting." >&2
exit 1
}
wezterm start -- fzfclip "$@" {LOCK_FD}>&-
wezterm start -- fzfclip "$@"
@@ -17,7 +17,7 @@
},
"action": {
"onSelected": "qs ipc call background setWallpaper '{{ path }}'; change-colortheme -c '{{ colorHex }}'",
"onPreview": "qs ipc call background previewWallpaper '{{ path }}'; change-colortheme -c '{{ colorHex }}' quickshell niri",
"onPreview": "qs ipc call background previewWallpaper '{{ path }}'; touch '{{ path }}'; change-colortheme -c '{{ colorHex }}' quickshell niri",
"quitOnSelected": true,
"saveState": [
{
+5 -14
View File
@@ -145,20 +145,7 @@
- [7.4. Entering the Chroot Environment](https://www.linuxfromscratch.org/lfs/view/stable/chapter07/chroot.html)
如果想要使用 `arch-install-scripts` 提供的 `arch-chroot` 脚本偷懒,则必须确保环境变量的清洗与重新设置,至少应确保 `PATH`, `MAKEFLAGS` 和 `TESTSUITEFLAGS` 被正确设置
```bash
arch-chroot "$LFS" /usr/bin/env -i \
HOME=/root \
TERM="$TERM" \
PS1='(lfs chroot) \u:\w\$ ' \
PATH=/usr/local/bin:/usr/bin:/usr/sbin \
MAKEFLAGS="-j$(nproc)" \
TESTSUITEFLAGS="-j$(nproc)" \
/bin/bash --login
```
或者完全按照 LFS 书中的 chroot 步骤编写一个小脚本:
完全按照 LFS 书中的 chroot 步骤编写一个小脚本
```bash
#!/bin/bash
@@ -206,6 +193,10 @@
它的作用是自动挂载一系列虚拟文件系统,同时在退出 chroot 时自动清理。
> [!IMPORTANT]
>
> 不建议使用 `arch-install-scripts` 提供的 `arch-chroot` 脚本偷懒, 即使用的话也需要做一些修改, 如对 `/dev` 不同的处理方式与默认缺失的环境变量.
- [8.64. GRUB-2.12](https://www.linuxfromscratch.org/lfs/view/stable/chapter08/grub.html)
对于 UEFI 引导的系统,此时需要跳转 BLFS 安装 GRUB。为避免过早地陷入依赖地狱建议仅按照顺序安装以下包