some plays, some updates

This commit is contained in:
2026-01-11 06:05:48 +03:00
parent b7f0075276
commit 2eb01e9603
19 changed files with 262 additions and 622 deletions
+67 -2
View File
@@ -17,9 +17,74 @@
./modules/hypr/hypr.nix
++ lib.optional (builtins.pathExists ./modules/my.nix) ./modules/my.nix;
# TODO: make it universal
home.username = username;
home.homeDirectory = "/home/${username}";
home.stateVersion = "25.11";
gtk = {
enable = true;
iconTheme = {
name = "Nordzy";
package = pkgs.nordzy-icon-theme;
};
};
home.sessionVariables.QS_ICON_THEME = "Nordzy";
home.packages = with pkgs; [ vlc imv eog ];
xdg.mimeApps = {
enable = true;
# Optional but often helpful: ensure these associations exist at all
associations.added = {
"image/jpeg" = [ "imv.desktop" ];
"image/png" = [ "imv.desktop" ];
"video/mp4" = [ "vlc.desktop" ];
};
defaultApplications = {
# Images
"image/jpeg" = "imv.desktop";
"image/png" = "imv.desktop";
"image/webp" = "imv.desktop";
"image/gif" = "imv.desktop";
"image/svg+xml" = "org.gnome.eog.desktop"; # example: Eye of GNOME for SVG
# Videos
"video/mp4" = "vlc.desktop";
"video/x-matroska" = "vlc.desktop"; # mkv
"video/x-msvideo" = "vlc.desktop"; # avi
"video/quicktime" = "vlc.desktop"; # mov
"video/webm" = "vlc.desktop";
# Audio (optional: also vlc, or a dedicated player)
"audio/mpeg" = "vlc.desktop";
"audio/flac" = "vlc.desktop";
"audio/ogg" = "vlc.desktop";
# PDFs
# "application/pdf" = "org.gnome.Evince.desktop"; # or "okular.desktop"
# Plain text (example)
"text/plain" = "code.desktop"; # VS Code, for example
"x-scheme-handler/http" = "zen-twilight.desktop";
"x-scheme-handler/https" = "zen-twilight.desktop";
"x-scheme-handler/chrome" = "zen-twilight.desktop";
"text/html" = "zen-twilight.desktop";
"application/xhtml+xml" = "zen-twilight.desktop";
"application/x-extension-htm" = "zen-twilight.desktop";
"application/x-extension-html" = "zen-twilight.desktop";
"application/x-extension-shtml" = "zen-twilight.desktop";
"application/x-extension-xhtml" = "zen-twilight.desktop";
"application/x-extension-xht" = "zen-twilight.desktop";
"x-scheme-handler/tg" = "org.telegram.desktop.desktop";
"x-scheme-handler/tonsite" = "org.telegram.desktop.desktop";
"application/pdf" = "zen-twilight.desktop";
"application/zip" = "userapp-unzip-WB99H3.desktop";
};
};
}
+5 -1
View File
@@ -27,7 +27,7 @@
nemo
pywal
jq
# quickshell
quickshell
];
programs.vicinae.enable = true;
services.swww.enable = true;
@@ -39,8 +39,12 @@
home.file.".config/hypr/scripts" = {
source = ./scripts;
recursive = true;
executable = true;
};
home.file.".config/background".source =
config.lib.file.mkOutOfStoreSymlink "/home/krosh/Pictures/wallpaper.png";
wayland.windowManager.hyprland = {
enable = true;
plugins = [ pkgs.hyprlandPlugins.hyprexpo ];
@@ -26,6 +26,7 @@
"${super}, P, pseudo"
"${super}, Q, killactive"
"${super}+Shift+Alt, Q, exec, hyprctl kill"
"${super}+Shift, R, exec, reload"
"${super}, Left, movefocus, l"
"${super}, Right, movefocus, r"
@@ -86,7 +87,7 @@
''
"${super}, T, exec, Telegram"
''
${super}, E, exec, ~/.config/hypr/scripts/launch_first_available.sh "nemo" "dolphin" "nautilus" "thunar" "kitty -1 zsh -c yazi"''
${super}, E, exec, ~/.config/hypr/scripts/launch_first_available.sh "thunar" "nemo" "nautilus" "dolphin" "kitty -1 zsh -c yazi"''
''
${super}, W, exec, ~/.config/hypr/scripts/launch_first_available.sh "google-chrome-stable" "zen" "firefox" "brave" "chromium" "microsoft-edge-stable" "opera" "librewolf"''
''
@@ -104,7 +105,7 @@
"${super}+Shift, 8, exec, ~/.config/hypr/scripts/workspace_action.sh movetoworkspacesilent 8"
"${super}+Shift, 9, exec, ~/.config/hypr/scripts/workspace_action.sh movetoworkspacesilent 9"
"${super}+Shift, 0, exec, ~/.config/hypr/scripts/workspace_action.sh movetoworkspacesilent 10"
"${super}+Shift, S, movetoworkspacesilent, special"
# "${super}+Shift, S, movetoworkspacesilent, special"
"${super}, S, togglespecialworkspace, special"
"RCtrl, 1, togglespecialworkspace, s1"
@@ -128,7 +129,8 @@
bindd = [
"${super}, M, Toggle power profile,exec, ~/.config/hypr/scripts/switch_config.sh"
# "${super}+Shift, S, Screenshot, exec, hyprshot --freeze --clipboard-only --mode region --silent"
", Print, Screenshot, exec, hyprshot --freeze --clipboard-only --mode region --silent"
", Print, Screenshot screen to file, exec, hyprshot --mode output --mode active "
"${super}+Shift, S, Screenshot region, exec, hyprshot --freeze --clipboard-only --mode region --silent"
"${super}+Shift, T, OCR, exec, hyprshot -m region --raw | tesseract stdin stdout"
"${super}, L, Lock screen, exec, hyprlock --immediate-render --no-fade-in"
];
@@ -152,6 +154,7 @@
''
, XF86AudioNext, exec, playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"`''
", XF86AudioPrev, exec, playerctl previous"
", XF86AudioPlay, exec, playerctl play-pause"
# ", Print, exec, hyprshot -m output"
];
+43 -21
View File
@@ -1,6 +1,7 @@
{ config, pkgs, ... }:
{
home.packages = with pkgs; [ playerctl ];
programs.hyprlock = {
enable = true;
extraConfig = ''
@@ -29,8 +30,8 @@
color = rgba(181818FF)
path = ${config.home.homeDirectory}/Pictures/wallpaper.png
blur_size = 4
blur_passes = 3
blur_size = 0 # 4 by default
blur_passes = 0 # 3 by default
noise = 0.0117
contrast = 1.3000
brightness = 0.8000
@@ -80,7 +81,29 @@
valign = center
}
# FP
#Now playing
label {
monitor =
text = cmd[update:5000] ${config.home.homeDirectory}/.config/hypr/scripts/hyprlock/music.sh
color = $text_color
font_size = 18
font_family = $font_family
shadow_passes = 3
shadow_size = 4
# position = 30, 30
# halign = left
# valign = bottom
# position = 0, -80
# halign = center
# valign = center
position = -30, -30
halign = right
valign = top
}
# Fingerprint prompt
label {
monitor =
text = cmd[update:1000] echo $FPRINTPROMPT
@@ -142,23 +165,6 @@
valign = center
}
# Degrees
label {
monitor =
text = cmd[update:18000000] echo "<b>Feels like<big> $(curl -s \'wttr.in?format=%t\' | tr -d \'+\') </big></b>"
color = $text_color
font_size = 18
font_family = $font_family
shadow_passes = 3
shadow_size = 4
position = 0, 30
halign = center
valign = bottom
}
label { # User
monitor =
text = $USER
@@ -177,7 +183,7 @@
label { # Status bat
monitor =
text = cmd[update:5000] ${config.home.homeDirectory}/.config/hypr/scripts/hyprlock-status.sh
text = cmd[update:5000] ${config.home.homeDirectory}/.config/hypr/scripts/hyprlock/bat_status.sh
color = $text_color
shadow_passes = 3
@@ -190,6 +196,22 @@
halign = left
valign = top
}
# Degrees
label {
monitor =
text = cmd[update:120000] ${config.home.homeDirectory}/.config/hypr/scripts/hyprlock/weather.sh
color = $text_color
font_size = 18
font_family = $font_family
shadow_passes = 3
shadow_size = 4
position = 0, 30
halign = center
valign = bottom
}
'';
};
}
+16 -545
View File
@@ -1,552 +1,23 @@
{ config, pkgs, lib, ... }:
let
shellQml = pkgs.writeText "shell.qml" ''
import Quickshell
import QtQuick
import QtQuick.Layouts
import Quickshell.Wayland
import Quickshell.Hyprland
import Quickshell.Services.Mpris
import Quickshell.Services.Pipewire
import Quickshell.Services.SystemTray
import Quickshell.Services.UPower
import Quickshell.Bluetooth
import "widgets" as W
ShellRoot {
id: root
property int barHeight: 34
property int paddingX: 10
property int spacing: 10
property real backgroundOpacity: 0.45
property int radius: 10
property int borderWidth: 1
SystemClock { id: clock; precision: SystemClock.Minutes }
Variants {
model: Quickshell.screens
PanelWindow {
id: win
required property var modelData
screen: modelData
anchors {
top: true
left: true
right: true
}
implicitHeight: root.barHeight
exclusiveZone: implicitHeight
aboveWindows: true
focusable: false
color: "transparent"
Rectangle {
anchors.fill: parent
radius: root.radius
border.width: root.borderWidth
border.color: Qt.rgba(1, 1, 1, 0.15)
color: Qt.rgba(0, 0, 0, root.backgroundOpacity)
}
RowLayout {
anchors.fill: parent
anchors.leftMargin: root.paddingX
anchors.rightMargin: root.paddingX
spacing: root.spacing
RowLayout {
spacing: root.spacing
Layout.alignment: Qt.AlignLeft
W.DashboardButton { }
W.Workspaces { }
W.Separator { }
W.WindowTitle { screen: modelData }
}
Item { Layout.fillWidth: true }
RowLayout {
spacing: root.spacing
Layout.alignment: Qt.AlignHCenter
W.Media { }
}
Item { Layout.fillWidth: true }
RowLayout {
spacing: root.spacing
Layout.alignment: Qt.AlignRight
W.Volume { }
W.Network { }
W.BluetoothIndicator { }
W.Battery { }
W.Separator { }
W.Tray { parentWindow: win }
W.KeyboardLayout { }
W.Clock { clock: clock }
W.Notifications { }
}
}
}
}
}
'';
barButtonQml = pkgs.writeText "BarButton.qml" ''
import QtQuick
import QtQuick.Layouts
Item {
id: root
property string label: ""
property string iconSource: ""
property bool emphasized: false
signal clicked()
signal rightClicked()
implicitHeight: 24
implicitWidth: content.implicitWidth + 14
Rectangle {
anchors.fill: parent
radius: 8
color: emphasized ? Qt.rgba(1, 1, 1, 0.18) : Qt.rgba(1, 1, 1, 0.10)
border.width: 0
}
RowLayout {
id: content
anchors.centerIn: parent
spacing: 6
Image {
visible: root.iconSource !== ""
source: root.iconSource
width: 16
height: 16
fillMode: Image.PreserveAspectFit
smooth: true
}
Text {
text: root.label
font.weight: 300
color: "white"
elide: Text.ElideRight
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: function(mouse) {
if (mouse.button === Qt.LeftButton) root.clicked();
if (mouse.button === Qt.RightButton) root.rightClicked();
}
}
}
'';
separatorQml = pkgs.writeText "Separator.qml" ''
import QtQuick
import QtQuick.Layouts
Rectangle {
Layout.preferredWidth: 1
Layout.preferredHeight: 16
radius: 1
color: Qt.rgba(1, 1, 1, 0.18)
}
'';
dashboardQml = pkgs.writeText "DashboardButton.qml" ''
import QtQuick
import Quickshell.Io
import "."
BarButton {
label: ""
Process { id: proc }
function run(cmd) {
proc.running = false
proc.command = ["sh", "-lc", cmd]
proc.running = true
}
onClicked: run("command -v fuzzel >/dev/null && fuzzel || true")
onRightClicked: run("command -v wlogout >/dev/null && wlogout || true")
}
'';
workspacesQml = pkgs.writeText "Workspaces.qml" ''
import QtQuick
import QtQuick.Layouts
import Quickshell.Hyprland
import Quickshell.Io
import "."
RowLayout {
spacing: 6
Process { id: hypr }
function dispatchWorkspace(id) {
hypr.running = false
hypr.command = ["sh", "-lc", "hyprctl dispatch workspace " + id]
hypr.running = true
}
Repeater {
model: Hyprland.workspaces
delegate: BarButton {
label: (modelData.name && modelData.name !== "") ? modelData.name : ("" + modelData.id)
emphasized: modelData.focused
onClicked: {
if (modelData.activate) modelData.activate()
else dispatchWorkspace(modelData.id)
}
}
}
}
'';
windowTitleQml = pkgs.writeText "WindowTitle.qml" ''
import QtQuick
import Quickshell.Wayland
Item {
id: root
property var screen
implicitHeight: 24
implicitWidth: 320
Text {
anchors.verticalCenter: parent.verticalCenter
width: parent.implicitWidth
color: "white"
font.weight: 300
elide: Text.ElideRight
text: {
const t = ToplevelManager.activeToplevel; // singleton property :contentReference[oaicite:1]{index=1}
if (!t) return "";
// опционально: фильтр по монитору
if (root.screen && t.screens && t.screens.indexOf && t.screens.indexOf(root.screen) === -1)
return "";
return t.title || "";
}
}
}
'';
mediaQml = pkgs.writeText "Media.qml" ''
import QtQuick
import Quickshell.Services.Mpris
Item {
implicitHeight: 24
implicitWidth: 360
function pickPlayer() {
const list = Mpris.players.values || [];
if (list.length === 0) return null;
for (let i = 0; i < list.length; i++) {
if (list[i].playbackState === MprisPlaybackState.Playing) return list[i];
}
return list[0];
}
Text {
anchors.verticalCenter: parent.verticalCenter
width: parent.implicitWidth
color: "white"
font.weight: 300
elide: Text.ElideRight
text: {
const p = pickPlayer();
if (!p) return "";
const title = p.trackTitle || "";
const artist = p.trackArtist || "";
if (title === "" && artist === "") return "";
return "\"" + (title || "Unknown Title") + "\" by " + (artist || "Unknown Artist");
}
}
}
'';
volumeQml = pkgs.writeText "Volume.qml" ''
import QtQuick
import Quickshell.Services.Pipewire
import "."
BarButton {
id: root
PwObjectTracker { objects: [ Pipewire.defaultAudioSink ] }
function clamp(x, lo, hi) { return Math.max(lo, Math.min(hi, x)); }
label: {
const s = Pipewire.defaultAudioSink;
if (!s || !s.audio) return "Vol: --";
return "Vol: " + Math.round(s.audio.volume * 100) + "%";
}
WheelHandler {
onWheel: function(event) {
const s = Pipewire.defaultAudioSink;
if (!s || !s.audio) return;
const step = 0.05;
const dir = event.angleDelta.y > 0 ? -1 : 1;
s.audio.volume = root.clamp(s.audio.volume + (dir * step), 0.0, 1.0);
event.accepted = true;
}
}
}
'';
networkQml = pkgs.writeText "Network.qml" ''
import QtQuick
import Quickshell.Io
import "."
BarButton {
id: root
property string ssid: ""
property int signal: -1
Process {
id: proc
stdout: StdioCollector {
waitForEnd: true
onStreamFinished: {
const text = this.text || "";
const lines = text.split("\n");
for (let i = 0; i < lines.length; i++) {
const parts = lines[i].split(":");
if (parts.length >= 3 && parts[0] === "yes") {
root.ssid = parts[1] || "";
root.signal = parseInt(parts[2]) || -1;
return;
}
}
root.ssid = "";
root.signal = -1;
}
}
}
Timer {
interval: 5000
repeat: true
running: true
triggeredOnStart: true
onTriggered: {
proc.exec(["sh", "-lc", "nmcli -t -f active,ssid,signal dev wifi 2>/dev/null || true"]);
}
}
function trunc(s, n) { return (s.length > n) ? (s.slice(0, n) + "") : s; }
label: (ssid === "") ? "WiFi: --" : ("WiFi: " + trunc(ssid, 13))
}
'';
btQml = pkgs.writeText "BluetoothIndicator.qml" ''
import QtQuick
import Quickshell.Bluetooth
import "."
BarButton {
label: {
const n = (Bluetooth.devices && Bluetooth.devices.values) ? Bluetooth.devices.values.length : 0;
return n > 0 ? ("BT: " + n) : "BT: --";
}
}
'';
batteryQml = pkgs.writeText "Battery.qml" ''
import QtQuick
import Quickshell.Services.UPower
import "."
BarButton {
label: {
const d = UPower.displayDevice;
if (!d || !d.ready) return "Bat: --";
return "Bat: " + Math.round(d.percentage) + "%";
}
}
'';
trayQml = pkgs.writeText "Tray.qml" ''
import QtQuick
import QtQuick.Layouts
import Quickshell.Services.SystemTray
RowLayout {
id: root
property var parentWindow
spacing: 6
Repeater {
model: SystemTray.items
delegate: Item {
implicitWidth: 18
implicitHeight: 18
Image {
anchors.fill: parent
source: modelData.icon
fillMode: Image.PreserveAspectFit
smooth: true
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onClicked: function(mouse) {
if (mouse.button === Qt.LeftButton) {
if (!modelData.onlyMenu) modelData.activate();
else if (root.parentWindow) modelData.display(root.parentWindow, mouse.x, mouse.y);
} else if (mouse.button === Qt.RightButton) {
if (root.parentWindow && modelData.hasMenu) modelData.display(root.parentWindow, mouse.x, mouse.y);
else modelData.secondaryActivate();
} else if (mouse.button === Qt.MiddleButton) {
modelData.secondaryActivate();
}
}
}
}
}
}
'';
kbQml = pkgs.writeText "KeyboardLayout.qml" ''
import QtQuick
import Quickshell.Io
import "."
BarButton {
id: root
property string layout: "--"
Process {
id: proc
stdout: StdioCollector {
waitForEnd: true
onStreamFinished: {
try {
const obj = JSON.parse(this.text || "{}");
const kbs = obj.keyboards || [];
let active = null;
for (let i = 0; i < kbs.length; i++) {
if (kbs[i].main === true) { active = kbs[i]; break; }
}
if (!active && kbs.length > 0) active = kbs[0];
const km = active ? (active.active_keymap || active.keymap || "") : "";
root.layout = km !== "" ? km : "--";
} catch (e) {
root.layout = "--";
}
}
}
}
Timer {
interval: 3000
repeat: true
running: true
triggeredOnStart: true
onTriggered: {
proc.exec(["sh", "-lc", "hyprctl devices -j 2>/dev/null || echo '{}'"]);
}
}
label: "KB: " + layout
}
'';
clockQml = pkgs.writeText "Clock.qml" ''
import QtQuick
import "."
BarButton {
property var clock
label: clock ? Qt.formatDateTime(clock.date, "ddd dd HH:mm") : "--"
}
'';
notifQml = pkgs.writeText "Notifications.qml" ''
import QtQuick
import Quickshell.Io
import "."
BarButton {
label: "Notif"
Process { id: proc }
function run(cmd) {
proc.running = false
proc.command = ["sh", "-lc", cmd]
proc.running = true
}
onClicked: run(
"command -v swaync-client >/dev/null && swaync-client -t || " +
"command -v dunstctl >/dev/null && dunstctl history-pop || true"
)
}
'';
quickshellDefault = pkgs.runCommand "quickshell-default-config" { } ''
mkdir -p "$out/widgets"
install -m644 ${shellQml} "$out/shell.qml"
install -m644 ${barButtonQml} "$out/widgets/BarButton.qml"
install -m644 ${separatorQml} "$out/widgets/Separator.qml"
install -m644 ${dashboardQml} "$out/widgets/DashboardButton.qml"
install -m644 ${workspacesQml} "$out/widgets/Workspaces.qml"
install -m644 ${windowTitleQml} "$out/widgets/WindowTitle.qml"
install -m644 ${mediaQml} "$out/widgets/Media.qml"
install -m644 ${volumeQml} "$out/widgets/Volume.qml"
install -m644 ${networkQml} "$out/widgets/Network.qml"
install -m644 ${btQml} "$out/widgets/BluetoothIndicator.qml"
install -m644 ${batteryQml} "$out/widgets/Battery.qml"
install -m644 ${trayQml} "$out/widgets/Tray.qml"
install -m644 ${kbQml} "$out/widgets/KeyboardLayout.qml"
install -m644 ${clockQml} "$out/widgets/Clock.qml"
install -m644 ${notifQml} "$out/widgets/Notifications.qml"
qmlPrefix = pkgs.qt6Packages.qtbase.qtQmlPrefix;
qmlDir = pkg: "${pkg}/${qmlPrefix}";
qsWrapped = pkgs.writeShellScriptBin "qss" ''
export QML_IMPORT_PATH="${qmlDir pkgs.qt6Packages.qtpositioning}:${
qmlDir pkgs.qt6Packages.qtlocation
}:${qmlDir pkgs.qt6Packages.qt5compat}:''${QML_IMPORT_PATH:-}"
export QML2_IMPORT_PATH="$QML_IMPORT_PATH"
exec ${pkgs.quickshell}/bin/qs "$@"
'';
in {
home.packages = with pkgs; [ quickshell networkmanager ];
home.packages = [
pkgs.quickshell
pkgs.qt6Packages.qt5compat
pkgs.qt6Packages.qtpositioning
pkgs.qt6Packages.qtlocation
qsWrapped
];
# Важно: default должен быть обычной writable директорией в $HOME.
home.file.".config/quickshell/default" = {
source = quickshellDefault;
recursive = true;
force = true;
};
}
+9
View File
@@ -0,0 +1,9 @@
# check if playerctl status is playing ond output song info
status=$(playerctl status 2>/dev/null)
if [ "$status" = "Playing" ]; then
# song_info=$(playerctl metadata --format '\u266A {{ artist }} - {{ title }}' 2>/dev/null)
song_info=$(printf "\u266A %s - %s" "$(playerctl metadata artist 2>/dev/null)" "$(playerctl metadata title 2>/dev/null)")
echo "$song_info"
else
echo ""
fi
+1
View File
@@ -0,0 +1 @@
echo "<b>Feels like<big> $(curl -s 'wttr.in/Ramenki?format=%t' | tr -d '+') </big></b>"
+11 -10
View File
@@ -24,6 +24,7 @@
gtypist
zip
unzip
vlc
# yubikey-manager-qt
# paprefs
];
@@ -36,20 +37,20 @@
programs.direnv.enableZshIntegration = true;
imports = [ inputs.zen-browser.homeModules.twilight ];
programs.zen-browser = {
programs.zen-browser = {
enable = true;
#profiles."Default Profile" = {
# search = {
# default = "Perplexity"; # Use the ID of your custom engine below
#engines = {
#"perplexity" = { # Custom engine ID (lowercase, no spaces)
#name = "Perplexity";
#urls = [{
# template = "https://www.perplexity.ai/search?q=%s";
#}];
#definedAliases = [ "@per" ];
#};
# };
#engines = {
#"perplexity" = { # Custom engine ID (lowercase, no spaces)
#name = "Perplexity";
#urls = [{
# template = "https://www.perplexity.ai/search?q=%s";
#}];
#definedAliases = [ "@per" ];
#};
# };
#};
};
+2
View File
@@ -21,6 +21,8 @@
bat
ripgrep
entr
github-copilot-cli
];
home.file.".p10k.zsh".source = ./p10k.zsh;