This commit is contained in:
Zacharias-Brohn
2025-11-23 20:23:31 +01:00
parent dc5273ab83
commit d481be5f60
8 changed files with 334 additions and 12 deletions
+15
View File
@@ -0,0 +1,15 @@
import qs.Config
CustomText {
property real fill
property int grade: DynamicColors.light ? 0 : -25
font.family: "Material Symbols Rounded"
font.pointSize: 15
font.variableAxes: ({
FILL: fill.toFixed(1),
GRAD: grade,
opsz: fontInfo.pixelSize,
wght: fontInfo.weight
})
}
+110
View File
@@ -0,0 +1,110 @@
pragma Singleton
import qs.Config
import Caelestia.Services
import Quickshell
import Quickshell.Services.Pipewire
import QtQuick
Singleton {
id: root
property string previousSinkName: ""
property string previousSourceName: ""
readonly property var nodes: Pipewire.nodes.values.reduce((acc, node) => {
if (!node.isStream) {
if (node.isSink)
acc.sinks.push(node);
else if (node.audio)
acc.sources.push(node);
}
return acc;
}, {
sources: [],
sinks: []
})
readonly property list<PwNode> sinks: nodes.sinks
readonly property list<PwNode> sources: nodes.sources
readonly property PwNode sink: Pipewire.defaultAudioSink
readonly property PwNode source: Pipewire.defaultAudioSource
readonly property bool muted: !!sink?.audio?.muted
readonly property real volume: sink?.audio?.volume ?? 0
readonly property bool sourceMuted: !!source?.audio?.muted
readonly property real sourceVolume: source?.audio?.volume ?? 0
readonly property alias beatTracker: beatTracker
function setVolume(newVolume: real): void {
if (sink?.ready && sink?.audio) {
sink.audio.muted = false;
sink.audio.volume = Math.max(0, Math.min(100, newVolume));
}
}
function incrementVolume(amount: real): void {
setVolume(volume + (amount || 5));
}
function decrementVolume(amount: real): void {
setVolume(volume - (amount || 5));
}
function setSourceVolume(newVolume: real): void {
if (source?.ready && source?.audio) {
source.audio.muted = false;
source.audio.volume = Math.max(0, Math.min(100, newVolume));
}
}
function incrementSourceVolume(amount: real): void {
setSourceVolume(sourceVolume + (amount || 5));
}
function decrementSourceVolume(amount: real): void {
setSourceVolume(sourceVolume - (amount || 5));
}
function setAudioSink(newSink: PwNode): void {
Pipewire.preferredDefaultAudioSink = newSink;
}
function setAudioSource(newSource: PwNode): void {
Pipewire.preferredDefaultAudioSource = newSource;
}
onSinkChanged: {
if (!sink?.ready)
return;
const newSinkName = sink.description || sink.name || qsTr("Unknown Device");
previousSinkName = newSinkName;
}
onSourceChanged: {
if (!source?.ready)
return;
const newSourceName = source.description || source.name || qsTr("Unknown Device");
previousSourceName = newSourceName;
}
Component.onCompleted: {
previousSinkName = sink?.description || sink?.name || qsTr("Unknown Device");
previousSourceName = source?.description || source?.name || qsTr("Unknown Device");
}
PwObjectTracker {
objects: [...root.sinks, ...root.sources]
}
BeatTracker {
id: beatTracker
}
}
+34 -10
View File
@@ -7,12 +7,36 @@ import QtQuick.Layouts
import QtQuick.Controls
import qs.Config
import qs.Components
import qs.Daemons
Item {
CustomRect {
id: root
implicitWidth: layout.implicitWidth + 10 * 2
implicitHeight: layout.implicitHeight + 10 * 2
implicitHeight: 0
color: Config.useDynamicColors ? DynamicColors.tPalette.m3surface : "#40000000"
clip: true
property alias expanded: root.isExpanded
property bool isExpanded: false
Anim {
id: expandAnim
running: root.isExpanded
target: root
property: "implicitHeight"
to: layout.implicitHeight + 10 * 2
duration: MaterialEasing.standardTime
}
Anim {
id: collapseAnim
running: !root.isExpanded
target: root
property: "implicitHeight"
to: 0
duration: MaterialEasing.standardTime
}
ButtonGroup {
id: sinks
@@ -58,7 +82,7 @@ Item {
Repeater {
model: Audio.sources
StyledRadioButton {
CustomRadioButton {
required property PwNode modelData
ButtonGroup.group: sources
@@ -114,7 +138,7 @@ Item {
color: DynamicColors.palette.m3onPrimaryContainer
function onClicked(): void {
root.wrapper.hasCurrent = false;
root.isExpanded = !root.isExpanded;
Quickshell.execDetached(["app2unit", "--", "pavucontrol"]);
}
}
@@ -123,18 +147,18 @@ Item {
id: expandBtn
anchors.centerIn: parent
spacing: Appearance.spacing.small
spacing: 7
StyledText {
Layout.leftMargin: Appearance.padding.smaller
CustomText {
Layout.leftMargin: 7
text: qsTr("Open settings")
color: Colours.palette.m3onPrimaryContainer
color: DynamicColors.palette.m3onPrimaryContainer
}
MaterialIcon {
text: "chevron_right"
color: Colours.palette.m3onPrimaryContainer
font.pointSize: Appearance.font.size.large
color: DynamicColors.palette.m3onPrimaryContainer
font.pointSize: 18
}
}
}
+9 -2
View File
@@ -53,13 +53,20 @@ Item {
border.width: 0
}
AudioPopup {
id: audioPopup
anchors.left: parent.left
anchors.top: parent.bottom
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: root.expanded = true
onExited: root.expanded = false
onEntered: audioPopup.expanded = true
onExited: audioPopup.expanded = false
RowLayout {
anchors {
fill: parent
+1
View File
@@ -41,6 +41,7 @@ Item {
text: root.currentTitle
color: root.textColor
elide: Text.ElideRight
font.family: "Rubik"
font.pixelSize: 16
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
+48
View File
@@ -0,0 +1,48 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
quickshell = {
url = "git+https://git.outfoxxed.me/outfoxxed/quickshell";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
self,
nixpkgs,
...
} @ inputs: let
forAllSystems = fn:
nixpkgs.lib.genAttrs nixpkgs.lib.platforms.linux (
system: fn nixpkgs.legacyPackages.${system}
);
in {
formatter = forAllSystems (pkgs: pkgs.alejandra);
packages = forAllSystems (pkgs: rec {
zshell = pkgs.callPackage ./nix {
rev = self.rev or self.dirtyRev;
stdenv = pkgs.clangStdenv;
quickshell = inputs.quickshell.packages.${pkgs.stdenv.hostPlatform.system}.default.override {
withX11 = false;
withI3 = false;
};
app2unit = pkgs.callPackage ./nix/app2unit.nix {inherit pkgs;};
};
debug = zshell.override {debug = true;};
default = zshell;
});
devShells = forAllSystems (pkgs: {
default = let
shell = self.packages.${pkgs.stdenv.hostPlatform.system}.zshell;
in
pkgs.mkShell.override {stdenv = shell.stdenv;} {
inputsFrom = [shell shell.plugin shell.extras];
packages = with pkgs; [clazy material-symbols rubik nerd-fonts.caskaydia-cove];
CAELESTIA_XKB_RULES_PATH = "${pkgs.xkeyboard-config}/share/xkeyboard-config-2/rules/base.lst";
};
});
};
}
+14
View File
@@ -0,0 +1,14 @@
{
pkgs, # To ensure the nixpkgs version of app2unit
fetchFromGitHub,
...
}:
pkgs.app2unit.overrideAttrs (final: prev: rec {
version = "1.0.3"; # Fix old issue related to missing env var
src = fetchFromGitHub {
owner = "Vladimir-csp";
repo = "app2unit";
tag = "v${version}";
hash = "sha256-7eEVjgs+8k+/NLteSBKgn4gPaPLHC+3Uzlmz6XB0930=";
};
})
+103
View File
@@ -0,0 +1,103 @@
{
rev,
lib,
stdenv,
makeWrapper,
makeFontsConf,
app2unit,
lm_sensors,
swappy,
wl-clipboard,
libqalculate,
bash,
hyprland,
material-symbols,
rubik,
nerd-fonts,
qt6,
quickshell,
aubio,
fftw,
pipewire,
xkeyboard-config,
cmake,
ninja,
pkg-config,
debug ? false,
withCli ? false,
extraRuntimeDeps ? [],
}: let
version = "1.0.0";
runtimeDeps =
[
ddcutil
brightnessctl
app2unit
networkmanager
lm_sensors
swappy
wl-clipboard
libqalculate
bash
hyprland
]
++ extraRuntimeDeps
fontconfig = makeFontsConf {
fontDirectories = [material-symbols rubik nerd-fonts.caskaydia-cove];
};
cmakeBuildType =
if debug
then "Debug"
else "RelWithDebInfo";
plugin = stdenv.mkDerivation {
inherit cmakeBuildType;
name = "zshell-qml-plugin${lib.optionalString debug "-debug"}";
src = lib.fileset.toSource {
root = ./..;
fileset = lib.fileset.union ./../CMakeLists.txt ./../Plugins;
};
nativeBuildInputs = [cmake ninja pkg-config];
buildInputs = [qt6.qtbase qt6.qtdeclarative libqalculate pipewire aubio libcava fftw];
dontWrapQtApps = true;
};
in
stdenv.mkDerivation {
inherit version cmakeBuildType;
pname = "zshell${lib.optionalString debug "-debug"}";
src = ./..;
nativeBuildInputs = [cmake ninja makeWrapper qt6.wrapQtAppsHook];
buildInputs = [quickshell extras plugin xkeyboard-config qt6.qtbase];
propagatedBuildInputs = runtimeDeps;
cmakeFlags =
[
(lib.cmakeFeature "ENABLE_MODULES" "shell")
(lib.cmakeFeature "INSTALL_QSCONFDIR" "${placeholder "out"}/share/zshell")
]
++ cmakeVersionFlags;
dontStrip = debug;
prePatch = ''
substituteInPlace assets/pam.d/fprint \
--replace-fail pam_fprintd.so /run/current-system/sw/lib/security/pam_fprintd.so
substituteInPlace shell.qml \
--replace-fail 'ShellRoot {' 'ShellRoot { settings.watchFiles: false'
'';
postInstall = ''
mkdir -p $out/lib
ln -s ${extras}/lib/* $out/lib/
'';
passthru = {
inherit plugin;
};
}