mirror of
https://github.com/kristoferssolo/solorice.git
synced 2026-02-04 06:32:03 +00:00
Use dotter
This commit is contained in:
31
config/HybridBar/config.json
Normal file
31
config/HybridBar/config.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"hybrid": {
|
||||
"namespace": "hybrid-bar",
|
||||
"r": 22,
|
||||
"g": 22,
|
||||
"b": 30,
|
||||
"a": 0.5
|
||||
},
|
||||
"left-spacing_end": {
|
||||
"spacing_end": 5
|
||||
},
|
||||
"left-label_ws": {
|
||||
"text": "",
|
||||
"command": "hyprctl -j workspaces | jq '.[] .id' | sort -n | tr '\n' ' '"
|
||||
},
|
||||
"centered-label_window": {
|
||||
"text": "",
|
||||
"command": "hyprctl activewindow -j | jq --raw-output .title"
|
||||
},
|
||||
"right-label_volume": {
|
||||
"text": "",
|
||||
"command": "wpctl get-volume @DEFAULT_SINK@ | awk '{print $2}' | sed -e 's/^0.//' -e 's/^1./1/' -e 's/$/%/'"
|
||||
},
|
||||
"right-label_time": {
|
||||
"text": "",
|
||||
"command": "date +%H:%M:%S"
|
||||
},
|
||||
"right-spacing_end": {
|
||||
"spacing_end": 5
|
||||
}
|
||||
}
|
||||
21
config/HybridBar/scripts/change-active-workspace
Executable file
21
config/HybridBar/scripts/change-active-workspace
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
function clamp {
|
||||
min=$1
|
||||
max=$2
|
||||
val=$3
|
||||
python -c "print(max($min, min($val, $max)))"
|
||||
}
|
||||
|
||||
direction=$1
|
||||
current=$2
|
||||
if test "$direction" = "down"
|
||||
then
|
||||
target=$(clamp 1 10 $(($current+1)))
|
||||
echo "jumping to $target"
|
||||
hyprctl dispatch workspace $target
|
||||
elif test "$direction" = "up"
|
||||
then
|
||||
target=$(clamp 1 10 $(($current-1)))
|
||||
echo "jumping to $target"
|
||||
hyprctl dispatch workspace $target
|
||||
fi
|
||||
6
config/HybridBar/scripts/get-active-workspace
Executable file
6
config/HybridBar/scripts/get-active-workspace
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
hyprctl monitors -j | jq '.[] | select(.focused) | .activeWorkspace.id'
|
||||
|
||||
socat -u UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - |
|
||||
stdbuf -o0 awk -F '>>|,' -e '/^workspace>>/ {print $2}' -e '/^focusedmon>>/ {print $3}'
|
||||
3
config/HybridBar/scripts/get-window-title
Executable file
3
config/HybridBar/scripts/get-window-title
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
hyprctl activewindow -j | jq --raw-output .title
|
||||
socat -u UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - | stdbuf -o0 awk -F '>>|,' '/^activewindow>>/{print $3}'
|
||||
11
config/HybridBar/scripts/get-workspaces
Executable file
11
config/HybridBar/scripts/get-workspaces
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
spaces (){
|
||||
WORKSPACE_WINDOWS=$(hyprctl workspaces -j | jq 'map({key: .id | tostring, value: .windows}) | from_entries')
|
||||
seq 1 10 | jq --argjson windows "${WORKSPACE_WINDOWS}" --slurp -Mc 'map(tostring) | map({id: ., windows: ($windows[.]//0)})'
|
||||
}
|
||||
|
||||
spaces
|
||||
socat -u UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - | while read -r line; do
|
||||
spaces
|
||||
done
|
||||
76
config/HybridBar/style.css
Normal file
76
config/HybridBar/style.css
Normal file
@@ -0,0 +1,76 @@
|
||||
/* :root { */
|
||||
/* --bg: #1a1b26; */
|
||||
/* --bg-dark: #16161e; */
|
||||
/* --bg-float: #16161e; */
|
||||
/* --bg-highlight: #292e42; */
|
||||
/* --bg-popup: #16161e; */
|
||||
/* --bg-search: #3d59a1; */
|
||||
/* --bg-sidebar: #16161e; */
|
||||
/* --bg-statusline: #16161e; */
|
||||
/* --bg-visual: #283457; */
|
||||
/* --black: #15161e; */
|
||||
/* --blue: #7aa2f7; */
|
||||
/* --blue0: #3d59a1; */
|
||||
/* --blue1: #2ac3de; */
|
||||
/* --blue2: #0db9d7; */
|
||||
/* --blue5: #89ddff; */
|
||||
/* --blue6: #b4f9f8; */
|
||||
/* --blue7: #394b70; */
|
||||
/* --border: #15161e; */
|
||||
/* --border-highlight: #27a1b9; */
|
||||
/* --comment: #565f89; */
|
||||
/* --cyan: #7dcfff; */
|
||||
/* --dark3: #545c7e; */
|
||||
/* --dark5: #737aa2; */
|
||||
/* --delta-add: #2c5a66; */
|
||||
/* --delta-delete: #713137; */
|
||||
/* --diff-add: #20303b; */
|
||||
/* --diff-change: #1f2231; */
|
||||
/* --diff-delete: #37222c; */
|
||||
/* --diff-text: #394b70; */
|
||||
/* --error: #db4b4b; */
|
||||
/* --fg: #c0caf5; */
|
||||
/* --fg-dark: #a9b1d6; */
|
||||
/* --fg-float: #c0caf5; */
|
||||
/* --fg-gutter: #3b4261; */
|
||||
/* --fg-sidebar: #a9b1d6; */
|
||||
/* --git-add: #449dab; */
|
||||
/* --git-change: #6183bb; */
|
||||
/* --git-delete: #914c54; */
|
||||
/* --git-ignore: #545c7e; */
|
||||
/* --gitSigns-add: #266d6a; */
|
||||
/* --gitSigns-change: #536c9e; */
|
||||
/* --gitSigns-delete: #b2555b; */
|
||||
/* --green: #9ece6a; */
|
||||
/* --green1: #73daca; */
|
||||
/* --green2: #41a6b5; */
|
||||
/* --hint: #1abc9c; */
|
||||
/* --info: #0db9d7; */
|
||||
/* --magenta: #bb9af7; */
|
||||
/* --magenta2: #ff007c; */
|
||||
/* --orange: #ff9e64; */
|
||||
/* --purple: #9d7cd8; */
|
||||
/* --red: #f7768e; */
|
||||
/* --red1: #db4b4b; */
|
||||
/* --teal: #1abc9c; */
|
||||
/* --terminal-black: #414868; */
|
||||
/* --warning: #e0af68; */
|
||||
/* --yellow: #e0af68; */
|
||||
/* } */
|
||||
|
||||
label {
|
||||
color: #c0caf5;
|
||||
font-family: "JetBrainsMono NF";
|
||||
margin: 0 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
button {
|
||||
font-weight: normal;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
margin-bottom: -8px;
|
||||
margin-top: -8px;
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
217
config/alacritty/alacritty.toml
Normal file
217
config/alacritty/alacritty.toml
Normal file
@@ -0,0 +1,217 @@
|
||||
import = ["~/.config/alacritty/rose-pine.toml"]
|
||||
[colors]
|
||||
draw_bold_text_with_bright_colors = true
|
||||
transparent_background_colors = false
|
||||
|
||||
# [[colors.indexed_colors]]
|
||||
# index = 16
|
||||
# color = "#ff9e64"
|
||||
|
||||
# [[colors.indexed_colors]]
|
||||
# index = 17
|
||||
# color = "#db4b4b"
|
||||
|
||||
# [colors.bright]
|
||||
# black = "#414868"
|
||||
# red = "#f7768e"
|
||||
# green = "#9ece6a"
|
||||
# yellow = "#e0af68"
|
||||
# blue = "#7aa2f7"
|
||||
# magenta = "#bb9af7"
|
||||
# cyan = "#7dcfff"
|
||||
# white = "#c0caf5"
|
||||
|
||||
[colors.cursor]
|
||||
cursor = "CellForeground"
|
||||
text = "CellBackground"
|
||||
|
||||
# [colors.hints.end]
|
||||
# background = "#282a36"
|
||||
# foreground = "#f1fa8c"
|
||||
#
|
||||
# [colors.hints.start]
|
||||
# background = "#f1fa8c"
|
||||
# foreground = "#282a36"
|
||||
|
||||
# [colors.normal]
|
||||
# black = "#15161e"
|
||||
# red = "#f7768e"
|
||||
# green = "#9ece6a"
|
||||
# yellow = "#e0af68"
|
||||
# blue = "#7aa2f7"
|
||||
# magenta = "#bb9af7"
|
||||
# cyan = "#7dcfff"
|
||||
# white = "#a9b1d6"
|
||||
|
||||
# [colors.primary]
|
||||
# background = "#1a1b26"
|
||||
# bright_foreground = "#ffffff"
|
||||
# dim_foreground = "#828482"
|
||||
# foreground = "#c0caf5"
|
||||
|
||||
# [colors.search.focused_match]
|
||||
# background = "#ffb86c"
|
||||
# foreground = "#44475a"
|
||||
|
||||
# [colors.search.footer_bar]
|
||||
# background = "#282a36"
|
||||
# foreground = "#f8f8f2"
|
||||
|
||||
# [colors.search.matches]
|
||||
# background = "#50fa7b"
|
||||
# foreground = "#44475a"
|
||||
|
||||
[colors.selection]
|
||||
background = "CellForeground"
|
||||
text = "CellBackground"
|
||||
|
||||
[colors.vi_mode_cursor]
|
||||
cursor = "CellForeground"
|
||||
text = "CellBackground"
|
||||
|
||||
[cursor]
|
||||
unfocused_hollow = false
|
||||
vi_mode_style = "Block"
|
||||
|
||||
[cursor.style]
|
||||
shape = "Beam"
|
||||
|
||||
[env]
|
||||
TERM = "alacritty"
|
||||
|
||||
[font]
|
||||
size = {{font_size}}
|
||||
|
||||
[font.bold]
|
||||
family = "JetBrainsMono NF"
|
||||
style = "Bold"
|
||||
|
||||
[font.bold_italic]
|
||||
family = "JetBrainsMono NF"
|
||||
style = "Bold Italic"
|
||||
|
||||
[font.glyph_offset]
|
||||
x = 0
|
||||
y = 0
|
||||
|
||||
[font.italic]
|
||||
family = "JetBrainsMono NF"
|
||||
style = "Italic"
|
||||
|
||||
[font.normal]
|
||||
family = "JetBrainsMono NF"
|
||||
style = "Regular"
|
||||
|
||||
[font.offset]
|
||||
x = 0
|
||||
y = -1
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "ScrollPageUp"
|
||||
key = "Up"
|
||||
mode = "~Alt"
|
||||
mods = "Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "ScrollPageDown"
|
||||
key = "Down"
|
||||
mode = "~Alt"
|
||||
mods = "Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "ScrollToTop"
|
||||
key = "Home"
|
||||
mode = "~Alt"
|
||||
mods = "Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "ScrollToBottom"
|
||||
key = "End"
|
||||
mode = "~Alt"
|
||||
mods = "Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "Paste"
|
||||
key = "V"
|
||||
mode = "~Vi"
|
||||
mods = "Control|Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "Copy"
|
||||
key = "C"
|
||||
mods = "Control|Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchForward"
|
||||
key = "F"
|
||||
mode = "~Search"
|
||||
mods = "Control|Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchBackward"
|
||||
key = "B"
|
||||
mode = "~Search"
|
||||
mods = "Control|Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "ResetFontSize"
|
||||
key = "Key0"
|
||||
mods = "Control"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "IncreaseFontSize"
|
||||
key = "Equals"
|
||||
mods = "Control"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "IncreaseFontSize"
|
||||
key = "NumpadAdd"
|
||||
mods = "Control"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "DecreaseFontSize"
|
||||
key = "Minus"
|
||||
mods = "Control"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "DecreaseFontSize"
|
||||
key = "NumpadSubtract"
|
||||
mods = "Control"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "Quit"
|
||||
key = "Q"
|
||||
mods = "Control|Shift"
|
||||
|
||||
[[mouse.bindings]]
|
||||
action = "PasteSelection"
|
||||
mode = "~Vi"
|
||||
mouse = "Middle"
|
||||
|
||||
[scrolling]
|
||||
history = 10000
|
||||
multiplier = 3
|
||||
|
||||
[selection]
|
||||
save_to_clipboard = true
|
||||
semantic_escape_chars = ",│`|:\"' ()[]{}<>\t"
|
||||
|
||||
[shell]
|
||||
program = "/bin/zsh"
|
||||
|
||||
[window]
|
||||
decorations = "none"
|
||||
decorations_theme_variant = "Dark"
|
||||
dynamic_padding = true
|
||||
dynamic_title = true
|
||||
opacity = 0.95
|
||||
startup_mode = "Windowed"
|
||||
title = "Alacritty"
|
||||
|
||||
[window.dimensions]
|
||||
columns = 0
|
||||
lines = 0
|
||||
|
||||
[window.padding]
|
||||
x = 0
|
||||
y = 0
|
||||
74
config/alacritty/rose-pine-dawn.toml
Normal file
74
config/alacritty/rose-pine-dawn.toml
Normal file
@@ -0,0 +1,74 @@
|
||||
# Colors section of "Alacritty - TOML configuration file format"
|
||||
# https://github.com/alacritty/alacritty/blob/master/extra/man/alacritty.5.scd#colors
|
||||
|
||||
[colors.primary]
|
||||
foreground = "#575279"
|
||||
background = "#faf4ed"
|
||||
dim_foreground = "#797593"
|
||||
bright_foreground = "#575279"
|
||||
|
||||
[colors.cursor]
|
||||
text = "#575279"
|
||||
cursor = "#cecacd"
|
||||
|
||||
[colors.vi_mode_cursor]
|
||||
text = "#575279"
|
||||
cursor = "#cecacd"
|
||||
|
||||
[colors.search.matches]
|
||||
foreground = "#797593"
|
||||
background = "#f2e9e1"
|
||||
|
||||
[colors.search.focused_match]
|
||||
foreground = "#faf4ed"
|
||||
background = "#d7827e"
|
||||
|
||||
[colors.hints.start]
|
||||
foreground = "#797593"
|
||||
background = "#fffaf3"
|
||||
|
||||
[colors.hints.end]
|
||||
foreground = "#9893a5"
|
||||
background = "#fffaf3"
|
||||
|
||||
[colors.line_indicator]
|
||||
foreground = "None"
|
||||
background = "None"
|
||||
|
||||
[colors.footer_bar]
|
||||
foreground = "#575279"
|
||||
background = "#fffaf3"
|
||||
|
||||
[colors.selection]
|
||||
text = "#575279"
|
||||
background = "#dfdad9"
|
||||
|
||||
[colors.normal]
|
||||
black = "#f2e9e1"
|
||||
red = "#b4637a"
|
||||
green = "#286983"
|
||||
yellow = "#ea9d34"
|
||||
blue = "#56949f"
|
||||
magenta = "#907aa9"
|
||||
cyan = "#d7827e"
|
||||
white = "#575279"
|
||||
|
||||
[colors.bright]
|
||||
black = "#9893a5"
|
||||
red = "#b4637a"
|
||||
green = "#286983"
|
||||
yellow = "#ea9d34"
|
||||
blue = "#56949f"
|
||||
magenta = "#907aa9"
|
||||
cyan = "#d7827e"
|
||||
white = "#575279"
|
||||
|
||||
[colors.dim]
|
||||
black = "#9893a5"
|
||||
red = "#b4637a"
|
||||
green = "#286983"
|
||||
yellow = "#ea9d34"
|
||||
blue = "#56949f"
|
||||
magenta = "#907aa9"
|
||||
cyan = "#d7827e"
|
||||
white = "#575279"
|
||||
74
config/alacritty/rose-pine-moon.toml
Normal file
74
config/alacritty/rose-pine-moon.toml
Normal file
@@ -0,0 +1,74 @@
|
||||
# Colors section of "Alacritty - TOML configuration file format"
|
||||
# https://github.com/alacritty/alacritty/blob/master/extra/man/alacritty.5.scd#colors
|
||||
|
||||
[colors.primary]
|
||||
foreground = "#e0def4"
|
||||
background = "#232136"
|
||||
dim_foreground = "#908caa"
|
||||
bright_foreground = "#e0def4"
|
||||
|
||||
[colors.cursor]
|
||||
text = "#e0def4"
|
||||
cursor = "#56526e"
|
||||
|
||||
[colors.vi_mode_cursor]
|
||||
text = "#e0def4"
|
||||
cursor = "#56526e"
|
||||
|
||||
[colors.search.matches]
|
||||
foreground = "#908caa"
|
||||
background = "#393552"
|
||||
|
||||
[colors.search.focused_match]
|
||||
foreground = "#232136"
|
||||
background = "#ea9a97"
|
||||
|
||||
[colors.hints.start]
|
||||
foreground = "#908caa"
|
||||
background = "#2a273f"
|
||||
|
||||
[colors.hints.end]
|
||||
foreground = "#6e6a86"
|
||||
background = "#2a273f"
|
||||
|
||||
[colors.line_indicator]
|
||||
foreground = "None"
|
||||
background = "None"
|
||||
|
||||
[colors.footer_bar]
|
||||
foreground = "#e0def4"
|
||||
background = "#2a273f"
|
||||
|
||||
[colors.selection]
|
||||
text = "#e0def4"
|
||||
background = "#44415a"
|
||||
|
||||
[colors.normal]
|
||||
black = "#393552"
|
||||
red = "#eb6f92"
|
||||
green = "#3e8fb0"
|
||||
yellow = "#f6c177"
|
||||
blue = "#9ccfd8"
|
||||
magenta = "#c4a7e7"
|
||||
cyan = "#ea9a97"
|
||||
white = "#e0def4"
|
||||
|
||||
[colors.bright]
|
||||
black = "#6e6a86"
|
||||
red = "#eb6f92"
|
||||
green = "#3e8fb0"
|
||||
yellow = "#f6c177"
|
||||
blue = "#9ccfd8"
|
||||
magenta = "#c4a7e7"
|
||||
cyan = "#ea9a97"
|
||||
white = "#e0def4"
|
||||
|
||||
[colors.dim]
|
||||
black = "#6e6a86"
|
||||
red = "#eb6f92"
|
||||
green = "#3e8fb0"
|
||||
yellow = "#f6c177"
|
||||
blue = "#9ccfd8"
|
||||
magenta = "#c4a7e7"
|
||||
cyan = "#ea9a97"
|
||||
white = "#e0def4"
|
||||
74
config/alacritty/rose-pine.toml
Normal file
74
config/alacritty/rose-pine.toml
Normal file
@@ -0,0 +1,74 @@
|
||||
# Colors section of "Alacritty - TOML configuration file format"
|
||||
# https://github.com/alacritty/alacritty/blob/master/extra/man/alacritty.5.scd#colors
|
||||
|
||||
[colors.primary]
|
||||
foreground = "#e0def4"
|
||||
background = "#191724"
|
||||
dim_foreground = "#908caa"
|
||||
bright_foreground = "#e0def4"
|
||||
|
||||
[colors.cursor]
|
||||
text = "#e0def4"
|
||||
cursor = "#524f67"
|
||||
|
||||
[colors.vi_mode_cursor]
|
||||
text = "#e0def4"
|
||||
cursor = "#524f67"
|
||||
|
||||
[colors.search.matches]
|
||||
foreground = "#908caa"
|
||||
background = "#26233a"
|
||||
|
||||
[colors.search.focused_match]
|
||||
foreground = "#191724"
|
||||
background = "#ebbcba"
|
||||
|
||||
[colors.hints.start]
|
||||
foreground = "#908caa"
|
||||
background = "#1f1d2e"
|
||||
|
||||
[colors.hints.end]
|
||||
foreground = "#6e6a86"
|
||||
background = "#1f1d2e"
|
||||
|
||||
[colors.line_indicator]
|
||||
foreground = "None"
|
||||
background = "None"
|
||||
|
||||
[colors.footer_bar]
|
||||
foreground = "#e0def4"
|
||||
background = "#1f1d2e"
|
||||
|
||||
[colors.selection]
|
||||
text = "#e0def4"
|
||||
background = "#403d52"
|
||||
|
||||
[colors.normal]
|
||||
black = "#26233a"
|
||||
red = "#eb6f92"
|
||||
green = "#31748f"
|
||||
yellow = "#f6c177"
|
||||
blue = "#9ccfd8"
|
||||
magenta = "#c4a7e7"
|
||||
cyan = "#ebbcba"
|
||||
white = "#e0def4"
|
||||
|
||||
[colors.bright]
|
||||
black = "#6e6a86"
|
||||
red = "#eb6f92"
|
||||
green = "#31748f"
|
||||
yellow = "#f6c177"
|
||||
blue = "#9ccfd8"
|
||||
magenta = "#c4a7e7"
|
||||
cyan = "#ebbcba"
|
||||
white = "#e0def4"
|
||||
|
||||
[colors.dim]
|
||||
black = "#6e6a86"
|
||||
red = "#eb6f92"
|
||||
green = "#31748f"
|
||||
yellow = "#f6c177"
|
||||
blue = "#9ccfd8"
|
||||
magenta = "#c4a7e7"
|
||||
cyan = "#ebbcba"
|
||||
white = "#e0def4"
|
||||
10
config/awesome/awesome.yml
Normal file
10
config/awesome/awesome.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
base: lua51
|
||||
globals:
|
||||
awesome:
|
||||
any: true
|
||||
client:
|
||||
any: true
|
||||
screen:
|
||||
any: true
|
||||
root:
|
||||
any: true
|
||||
372
config/awesome/json.lua
Normal file
372
config/awesome/json.lua
Normal file
@@ -0,0 +1,372 @@
|
||||
--
|
||||
-- json.lua
|
||||
--
|
||||
-- Copyright (c) 2020 rxi
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
-- this software and associated documentation files (the "Software"), to deal in
|
||||
-- the Software without restriction, including without limitation the rights to
|
||||
-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
-- of the Software, and to permit persons to whom the Software is furnished to do
|
||||
-- so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in all
|
||||
-- copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
-- SOFTWARE.
|
||||
--
|
||||
|
||||
local json = { _version = "0.1.2" }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Encode
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local encode
|
||||
|
||||
local escape_char_map = {
|
||||
["\\"] = "\\",
|
||||
['"'] = '"',
|
||||
["\b"] = "b",
|
||||
["\f"] = "f",
|
||||
["\n"] = "n",
|
||||
["\r"] = "r",
|
||||
["\t"] = "t",
|
||||
}
|
||||
|
||||
local escape_char_map_inv = { ["/"] = "/" }
|
||||
for k, v in pairs(escape_char_map) do
|
||||
escape_char_map_inv[v] = k
|
||||
end
|
||||
|
||||
local function escape_char(c)
|
||||
return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte()))
|
||||
end
|
||||
|
||||
local function encode_nil()
|
||||
return "null"
|
||||
end
|
||||
|
||||
local function encode_table(val, stack)
|
||||
local res = {}
|
||||
stack = stack or {}
|
||||
|
||||
-- Circular reference?
|
||||
if stack[val] then
|
||||
error("circular reference")
|
||||
end
|
||||
|
||||
stack[val] = true
|
||||
|
||||
if rawget(val, 1) ~= nil or next(val) == nil then
|
||||
-- Treat as array -- check keys are valid and it is not sparse
|
||||
local n = 0
|
||||
for k in pairs(val) do
|
||||
if type(k) ~= "number" then
|
||||
error("invalid table: mixed or invalid key types")
|
||||
end
|
||||
n = n + 1
|
||||
end
|
||||
if n ~= #val then
|
||||
error("invalid table: sparse array")
|
||||
end
|
||||
-- Encode
|
||||
for _, v in ipairs(val) do
|
||||
table.insert(res, encode(v, stack))
|
||||
end
|
||||
stack[val] = nil
|
||||
return "[" .. table.concat(res, ",") .. "]"
|
||||
else
|
||||
-- Treat as an object
|
||||
for k, v in pairs(val) do
|
||||
if type(k) ~= "string" then
|
||||
error("invalid table: mixed or invalid key types")
|
||||
end
|
||||
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
|
||||
end
|
||||
stack[val] = nil
|
||||
return "{" .. table.concat(res, ",") .. "}"
|
||||
end
|
||||
end
|
||||
|
||||
local function encode_string(val)
|
||||
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
|
||||
end
|
||||
|
||||
local function encode_number(val)
|
||||
-- Check for NaN, -inf and inf
|
||||
if val ~= val or val <= -math.huge or val >= math.huge then
|
||||
error("unexpected number value '" .. tostring(val) .. "'")
|
||||
end
|
||||
return string.format("%.14g", val)
|
||||
end
|
||||
|
||||
local type_func_map = {
|
||||
["nil"] = encode_nil,
|
||||
["table"] = encode_table,
|
||||
["string"] = encode_string,
|
||||
["number"] = encode_number,
|
||||
["boolean"] = tostring,
|
||||
}
|
||||
|
||||
encode = function(val, stack)
|
||||
local t = type(val)
|
||||
local f = type_func_map[t]
|
||||
if f then
|
||||
return f(val, stack)
|
||||
end
|
||||
error("unexpected type '" .. t .. "'")
|
||||
end
|
||||
|
||||
function json.encode(val)
|
||||
return (encode(val))
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Decode
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local parse
|
||||
|
||||
local function create_set(...)
|
||||
local res = {}
|
||||
for i = 1, select("#", ...) do
|
||||
res[select(i, ...)] = true
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
local space_chars = create_set(" ", "\t", "\r", "\n")
|
||||
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
|
||||
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
|
||||
local literals = create_set("true", "false", "null")
|
||||
|
||||
local literal_map = {
|
||||
["true"] = true,
|
||||
["false"] = false,
|
||||
["null"] = nil,
|
||||
}
|
||||
|
||||
local function next_char(str, idx, set, negate)
|
||||
for i = idx, #str do
|
||||
if set[str:sub(i, i)] ~= negate then
|
||||
return i
|
||||
end
|
||||
end
|
||||
return #str + 1
|
||||
end
|
||||
|
||||
local function decode_error(str, idx, msg)
|
||||
local line_count = 1
|
||||
local col_count = 1
|
||||
for i = 1, idx - 1 do
|
||||
col_count = col_count + 1
|
||||
if str:sub(i, i) == "\n" then
|
||||
line_count = line_count + 1
|
||||
col_count = 1
|
||||
end
|
||||
end
|
||||
error(string.format("%s at line %d col %d", msg, line_count, col_count))
|
||||
end
|
||||
|
||||
local function codepoint_to_utf8(n)
|
||||
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
|
||||
local f = math.floor
|
||||
if n <= 0x7f then
|
||||
return string.char(n)
|
||||
elseif n <= 0x7ff then
|
||||
return string.char(f(n / 64) + 192, n % 64 + 128)
|
||||
elseif n <= 0xffff then
|
||||
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
|
||||
elseif n <= 0x10ffff then
|
||||
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128, f(n % 4096 / 64) + 128, n % 64 + 128)
|
||||
end
|
||||
error(string.format("invalid unicode codepoint '%x'", n))
|
||||
end
|
||||
|
||||
local function parse_unicode_escape(s)
|
||||
local n1 = tonumber(s:sub(1, 4), 16)
|
||||
local n2 = tonumber(s:sub(7, 10), 16)
|
||||
-- Surrogate pair?
|
||||
if n2 then
|
||||
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
|
||||
else
|
||||
return codepoint_to_utf8(n1)
|
||||
end
|
||||
end
|
||||
|
||||
local function parse_string(str, i)
|
||||
local res = ""
|
||||
local j = i + 1
|
||||
local k = j
|
||||
|
||||
while j <= #str do
|
||||
local x = str:byte(j)
|
||||
|
||||
if x < 32 then
|
||||
decode_error(str, j, "control character in string")
|
||||
elseif x == 92 then -- `\`: Escape
|
||||
res = res .. str:sub(k, j - 1)
|
||||
j = j + 1
|
||||
local c = str:sub(j, j)
|
||||
if c == "u" then
|
||||
local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1)
|
||||
or str:match("^%x%x%x%x", j + 1)
|
||||
or decode_error(str, j - 1, "invalid unicode escape in string")
|
||||
res = res .. parse_unicode_escape(hex)
|
||||
j = j + #hex
|
||||
else
|
||||
if not escape_chars[c] then
|
||||
decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string")
|
||||
end
|
||||
res = res .. escape_char_map_inv[c]
|
||||
end
|
||||
k = j + 1
|
||||
elseif x == 34 then -- `"`: End of string
|
||||
res = res .. str:sub(k, j - 1)
|
||||
return res, j + 1
|
||||
end
|
||||
|
||||
j = j + 1
|
||||
end
|
||||
|
||||
decode_error(str, i, "expected closing quote for string")
|
||||
end
|
||||
|
||||
local function parse_number(str, i)
|
||||
local x = next_char(str, i, delim_chars)
|
||||
local s = str:sub(i, x - 1)
|
||||
local n = tonumber(s)
|
||||
if not n then
|
||||
decode_error(str, i, "invalid number '" .. s .. "'")
|
||||
end
|
||||
return n, x
|
||||
end
|
||||
|
||||
local function parse_literal(str, i)
|
||||
local x = next_char(str, i, delim_chars)
|
||||
local word = str:sub(i, x - 1)
|
||||
if not literals[word] then
|
||||
decode_error(str, i, "invalid literal '" .. word .. "'")
|
||||
end
|
||||
return literal_map[word], x
|
||||
end
|
||||
|
||||
local function parse_array(str, i)
|
||||
local res = {}
|
||||
local n = 1
|
||||
i = i + 1
|
||||
while 1 do
|
||||
local x
|
||||
i = next_char(str, i, space_chars, true)
|
||||
-- Empty / end of array?
|
||||
if str:sub(i, i) == "]" then
|
||||
i = i + 1
|
||||
break
|
||||
end
|
||||
-- Read token
|
||||
x, i = parse(str, i)
|
||||
res[n] = x
|
||||
n = n + 1
|
||||
-- Next token
|
||||
i = next_char(str, i, space_chars, true)
|
||||
local chr = str:sub(i, i)
|
||||
i = i + 1
|
||||
if chr == "]" then
|
||||
break
|
||||
end
|
||||
if chr ~= "," then
|
||||
decode_error(str, i, "expected ']' or ','")
|
||||
end
|
||||
end
|
||||
return res, i
|
||||
end
|
||||
|
||||
local function parse_object(str, i)
|
||||
local res = {}
|
||||
i = i + 1
|
||||
while 1 do
|
||||
local key, val
|
||||
i = next_char(str, i, space_chars, true)
|
||||
-- Empty / end of object?
|
||||
if str:sub(i, i) == "}" then
|
||||
i = i + 1
|
||||
break
|
||||
end
|
||||
-- Read key
|
||||
if str:sub(i, i) ~= '"' then
|
||||
decode_error(str, i, "expected string for key")
|
||||
end
|
||||
key, i = parse(str, i)
|
||||
-- Read ':' delimiter
|
||||
i = next_char(str, i, space_chars, true)
|
||||
if str:sub(i, i) ~= ":" then
|
||||
decode_error(str, i, "expected ':' after key")
|
||||
end
|
||||
i = next_char(str, i + 1, space_chars, true)
|
||||
-- Read value
|
||||
val, i = parse(str, i)
|
||||
-- Set
|
||||
res[key] = val
|
||||
-- Next token
|
||||
i = next_char(str, i, space_chars, true)
|
||||
local chr = str:sub(i, i)
|
||||
i = i + 1
|
||||
if chr == "}" then
|
||||
break
|
||||
end
|
||||
if chr ~= "," then
|
||||
decode_error(str, i, "expected '}' or ','")
|
||||
end
|
||||
end
|
||||
return res, i
|
||||
end
|
||||
|
||||
local char_func_map = {
|
||||
['"'] = parse_string,
|
||||
["0"] = parse_number,
|
||||
["1"] = parse_number,
|
||||
["2"] = parse_number,
|
||||
["3"] = parse_number,
|
||||
["4"] = parse_number,
|
||||
["5"] = parse_number,
|
||||
["6"] = parse_number,
|
||||
["7"] = parse_number,
|
||||
["8"] = parse_number,
|
||||
["9"] = parse_number,
|
||||
["-"] = parse_number,
|
||||
["t"] = parse_literal,
|
||||
["f"] = parse_literal,
|
||||
["n"] = parse_literal,
|
||||
["["] = parse_array,
|
||||
["{"] = parse_object,
|
||||
}
|
||||
|
||||
parse = function(str, idx)
|
||||
local chr = str:sub(idx, idx)
|
||||
local f = char_func_map[chr]
|
||||
if f then
|
||||
return f(str, idx)
|
||||
end
|
||||
decode_error(str, idx, "unexpected character '" .. chr .. "'")
|
||||
end
|
||||
|
||||
function json.decode(str)
|
||||
if type(str) ~= "string" then
|
||||
error("expected argument of type string, got " .. type(str))
|
||||
end
|
||||
local res, idx = parse(str, next_char(str, 1, space_chars, true))
|
||||
idx = next_char(str, idx, space_chars, true)
|
||||
if idx <= #str then
|
||||
decode_error(str, idx, "trailing garbage")
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
return json
|
||||
141
config/awesome/mytheme.lua
Normal file
141
config/awesome/mytheme.lua
Normal file
@@ -0,0 +1,141 @@
|
||||
---------------------------
|
||||
-- Default awesome theme --
|
||||
---------------------------
|
||||
|
||||
local theme_assets = require("beautiful.theme_assets")
|
||||
local xresources = require("beautiful.xresources")
|
||||
local dpi = xresources.apply_dpi
|
||||
|
||||
local gfs = require("gears.filesystem")
|
||||
local themes_path = gfs.get_themes_dir()
|
||||
|
||||
local theme = {}
|
||||
|
||||
theme.font = "JetBrainsMono NF 8"
|
||||
|
||||
local base = "#191724"
|
||||
local surface = "#1f1d2e"
|
||||
local overlay = "#26233a"
|
||||
local muted = "#6e6a86"
|
||||
local subtle = "#908caa"
|
||||
local text = "#e0def4"
|
||||
local love = "#eb6f92"
|
||||
local gold = "#f6c177"
|
||||
local rose = "#ebbcba"
|
||||
local pine = "#31748f"
|
||||
local foam = "#9ccfd8"
|
||||
local iris = "#c4a7e7"
|
||||
local highlightLow = "#21202e"
|
||||
local highlightMed = "#403d52"
|
||||
local highlightHigh = "#524f67"
|
||||
|
||||
theme.bg_normal = base
|
||||
theme.bg_focus = surface
|
||||
theme.bg_urgent = love
|
||||
theme.bg_minimize = highlightMed
|
||||
theme.bg_systray = theme.bg_normal
|
||||
|
||||
theme.fg_normal = subtle
|
||||
theme.fg_urgent = text
|
||||
theme.fg_focus = text
|
||||
theme.fg_minimize = subtle
|
||||
|
||||
theme.useless_gap = dpi(4)
|
||||
theme.border_width = dpi(2)
|
||||
theme.border_normal = surface
|
||||
theme.border_focus = rose
|
||||
theme.border_marked = love
|
||||
|
||||
-- There are other variable sets
|
||||
-- overriding the default one when
|
||||
-- defined, the sets are:
|
||||
-- taglist_[bg|fg]_[focus|urgent|occupied|empty|volatile]
|
||||
-- tasklist_[bg|fg]_[focus|urgent]
|
||||
-- titlebar_[bg|fg]_[normal|focus]
|
||||
-- tooltip_[font|opacity|fg_color|bg_color|border_width|border_color]
|
||||
-- mouse_finder_[color|timeout|animate_timeout|radius|factor]
|
||||
-- prompt_[fg|bg|fg_cursor|bg_cursor|font]
|
||||
-- hotkeys_[bg|fg|border_width|border_color|shape|opacity|modifiers_fg|label_bg|label_fg|group_margin|font|description_font]
|
||||
|
||||
-- theme.taglist_bg_focus = love
|
||||
|
||||
-- Generate taglist squares:
|
||||
local taglist_square_size = dpi(4)
|
||||
theme.taglist_squares_sel = theme_assets.taglist_squares_sel(taglist_square_size, theme.fg_normal)
|
||||
theme.taglist_squares_unsel = theme_assets.taglist_squares_unsel(taglist_square_size, theme.fg_normal)
|
||||
|
||||
-- Variables set for theming notifications:
|
||||
-- notification_font
|
||||
-- notification_[bg|fg]
|
||||
-- notification_[width|height|margin]
|
||||
-- notification_[border_color|border_width|shape|opacity]
|
||||
|
||||
-- Variables set for theming the menu:
|
||||
-- menu_[bg|fg]_[normal|focus]
|
||||
-- menu_[border_color|border_width]
|
||||
theme.menu_submenu_icon = themes_path .. "default/submenu.png"
|
||||
theme.menu_height = dpi(16)
|
||||
theme.menu_width = dpi(100)
|
||||
|
||||
-- You can add as many variables as
|
||||
-- you wish and access them by using
|
||||
-- beautiful.variable in your rc.lua
|
||||
-- theme.bg_widget = love
|
||||
|
||||
-- Define the image to load
|
||||
theme.titlebar_close_button_normal = themes_path .. "default/titlebar/close_normal.png"
|
||||
theme.titlebar_close_button_focus = themes_path .. "default/titlebar/close_focus.png"
|
||||
|
||||
theme.titlebar_minimize_button_normal = themes_path .. "default/titlebar/minimize_normal.png"
|
||||
theme.titlebar_minimize_button_focus = themes_path .. "default/titlebar/minimize_focus.png"
|
||||
|
||||
theme.titlebar_ontop_button_normal_inactive = themes_path .. "default/titlebar/ontop_normal_inactive.png"
|
||||
theme.titlebar_ontop_button_focus_inactive = themes_path .. "default/titlebar/ontop_focus_inactive.png"
|
||||
theme.titlebar_ontop_button_normal_active = themes_path .. "default/titlebar/ontop_normal_active.png"
|
||||
theme.titlebar_ontop_button_focus_active = themes_path .. "default/titlebar/ontop_focus_active.png"
|
||||
|
||||
theme.titlebar_sticky_button_normal_inactive = themes_path .. "default/titlebar/sticky_normal_inactive.png"
|
||||
theme.titlebar_sticky_button_focus_inactive = themes_path .. "default/titlebar/sticky_focus_inactive.png"
|
||||
theme.titlebar_sticky_button_normal_active = themes_path .. "default/titlebar/sticky_normal_active.png"
|
||||
theme.titlebar_sticky_button_focus_active = themes_path .. "default/titlebar/sticky_focus_active.png"
|
||||
|
||||
theme.titlebar_floating_button_normal_inactive = themes_path .. "default/titlebar/floating_normal_inactive.png"
|
||||
theme.titlebar_floating_button_focus_inactive = themes_path .. "default/titlebar/floating_focus_inactive.png"
|
||||
theme.titlebar_floating_button_normal_active = themes_path .. "default/titlebar/floating_normal_active.png"
|
||||
theme.titlebar_floating_button_focus_active = themes_path .. "default/titlebar/floating_focus_active.png"
|
||||
|
||||
theme.titlebar_maximized_button_normal_inactive = themes_path .. "default/titlebar/maximized_normal_inactive.png"
|
||||
theme.titlebar_maximized_button_focus_inactive = themes_path .. "default/titlebar/maximized_focus_inactive.png"
|
||||
theme.titlebar_maximized_button_normal_active = themes_path .. "default/titlebar/maximized_normal_active.png"
|
||||
theme.titlebar_maximized_button_focus_active = themes_path .. "default/titlebar/maximized_focus_active.png"
|
||||
|
||||
theme.wallpaper = "~/.local/share/bg"
|
||||
|
||||
-- You can use your own layout icons like this:
|
||||
theme.layout_fairh = themes_path .. "default/layouts/fairhw.png"
|
||||
theme.layout_fairv = themes_path .. "default/layouts/fairvw.png"
|
||||
theme.layout_floating = themes_path .. "default/layouts/floatingw.png"
|
||||
theme.layout_magnifier = themes_path .. "default/layouts/magnifierw.png"
|
||||
theme.layout_max = themes_path .. "default/layouts/maxw.png"
|
||||
theme.layout_fullscreen = themes_path .. "default/layouts/fullscreenw.png"
|
||||
theme.layout_tilebottom = themes_path .. "default/layouts/tilebottomw.png"
|
||||
theme.layout_tileleft = themes_path .. "default/layouts/tileleftw.png"
|
||||
theme.layout_tile = themes_path .. "default/layouts/tilew.png"
|
||||
theme.layout_tiletop = themes_path .. "default/layouts/tiletopw.png"
|
||||
theme.layout_spiral = themes_path .. "default/layouts/spiralw.png"
|
||||
theme.layout_dwindle = themes_path .. "default/layouts/dwindlew.png"
|
||||
theme.layout_cornernw = themes_path .. "default/layouts/cornernww.png"
|
||||
theme.layout_cornerne = themes_path .. "default/layouts/cornernew.png"
|
||||
theme.layout_cornersw = themes_path .. "default/layouts/cornersww.png"
|
||||
theme.layout_cornerse = themes_path .. "default/layouts/cornersew.png"
|
||||
|
||||
-- Generate Awesome icon:
|
||||
theme.awesome_icon = theme_assets.awesome_icon(theme.menu_height, theme.bg_focus, theme.fg_focus)
|
||||
|
||||
-- Define the icon theme for application icons. If not set then the icons
|
||||
-- from /usr/share/icons and /usr/share/icons/hicolor will be used.
|
||||
theme.icon_theme = "/usr/share/icons/rose-pine-icons/"
|
||||
|
||||
return theme
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
758
config/awesome/rc-laptop.lua
Normal file
758
config/awesome/rc-laptop.lua
Normal file
@@ -0,0 +1,758 @@
|
||||
-- If LuaRocks is installed, make sure that packages installed through it are
|
||||
-- found (e.g. lgi). If LuaRocks is not installed, do nothing.
|
||||
pcall(require, "luarocks.loader")
|
||||
|
||||
-- AwesomeWM Widgets
|
||||
local calendar_widget = require("awesome-wm-widgets.calendar-widget.calendar")
|
||||
local cpu_widget = require("awesome-wm-widgets.cpu-widget.cpu-widget")
|
||||
local logout_menu_widget = require("awesome-wm-widgets.logout-menu-widget.logout-menu")
|
||||
local net_speed_widget = require("awesome-wm-widgets.net-speed-widget.net-speed")
|
||||
local spotify_shell = require("awesome-wm-widgets.spotify-shell.spotify-shell")
|
||||
local spotify_widget = require("awesome-wm-widgets.spotify-widget.spotify")
|
||||
local github_activity_widget = require("awesome-wm-widgets.github-activity-widget.github-activity-widget")
|
||||
local github_contributions_widget =
|
||||
require("awesome-wm-widgets.github-contributions-widget.github-contributions-widget")
|
||||
local docker_widget = require("awesome-wm-widgets.docker-widget.docker")
|
||||
local batteryarc_widget = require("awesome-wm-widgets.batteryarc-widget.batteryarc")
|
||||
|
||||
-- Standard awesome library
|
||||
local gears = require("gears")
|
||||
local awful = require("awful")
|
||||
require("awful.autofocus")
|
||||
-- Widget and layout library
|
||||
local wibox = require("wibox")
|
||||
-- Theme handling library
|
||||
local beautiful = require("beautiful")
|
||||
-- Notification library
|
||||
local naughty = require("naughty")
|
||||
local menubar = require("menubar")
|
||||
local hotkeys_popup = require("awful.hotkeys_popup")
|
||||
-- Enable hotkeys help widget for VIM and other apps
|
||||
-- when client with a matching name is opened:
|
||||
require("awful.hotkeys_popup.keys")
|
||||
|
||||
-- {{{ Error handling
|
||||
-- Check if awesome encountered an error during startup and fell back to
|
||||
-- another config (This code will only ever execute for the fallback config)
|
||||
if awesome.startup_errors then
|
||||
naughty.notify({
|
||||
preset = naughty.config.presets.critical,
|
||||
title = "Oops, there were errors during startup!",
|
||||
text = awesome.startup_errors,
|
||||
})
|
||||
end
|
||||
|
||||
-- Handle runtime errors after startup
|
||||
do
|
||||
local in_error = false
|
||||
awesome.connect_signal("debug::error", function(err)
|
||||
-- Make sure we don't go into an endless error loop
|
||||
if in_error then
|
||||
return
|
||||
end
|
||||
in_error = true
|
||||
|
||||
naughty.notify({
|
||||
preset = naughty.config.presets.critical,
|
||||
title = "Oops, an error happened!",
|
||||
text = tostring(err),
|
||||
})
|
||||
in_error = false
|
||||
end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Variable definitions
|
||||
-- Themes define colours, icons, font and wallpapers.
|
||||
-- beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua")
|
||||
beautiful.init(gears.filesystem.get_configuration_dir() .. "mytheme.lua")
|
||||
|
||||
-- This is used later as the default terminal and editor to run.
|
||||
local terminal = "alacritty"
|
||||
local editor = os.getenv("EDITOR") or "nvim"
|
||||
local editor_cmd = terminal .. " -e " .. editor
|
||||
|
||||
-- Default modkey.
|
||||
-- Usually, Mod4 is the key with a logo between Control and Alt.
|
||||
-- If you do not like this or do not have such a key,
|
||||
-- I suggest you to remap Mod4 to another key using xmodmap or other tools.
|
||||
-- However, you can use another modifier like Mod1, but it may interact with others.
|
||||
|
||||
local modkey = "Mod4"
|
||||
|
||||
-- Table of layouts to cover with awful.layout.inc, order matters.
|
||||
awful.layout.layouts = {
|
||||
awful.layout.suit.tile,
|
||||
awful.layout.suit.tile.left,
|
||||
awful.layout.suit.fair,
|
||||
awful.layout.suit.fair.horizontal,
|
||||
-- awful.layout.suit.spiral.dwindle,
|
||||
-- awful.layout.suit.spiral,
|
||||
-- awful.layout.suit.floating,
|
||||
-- awful.layout.suit.tile.bottom,
|
||||
-- awful.layout.suit.tile.top,
|
||||
-- awful.layout.suit.max,
|
||||
-- awful.layout.suit.max.fullscreen,
|
||||
-- awful.layout.suit.magnifier,
|
||||
awful.layout.suit.corner.nw,
|
||||
-- awful.layout.suit.corner.ne,
|
||||
-- awful.layout.suit.corner.sw,
|
||||
-- awful.layout.suit.corner.se,
|
||||
}
|
||||
-- }}}
|
||||
|
||||
-- {{{ Menu
|
||||
-- Create a launcher widget and a main menu
|
||||
local myawesomemenu = {
|
||||
{
|
||||
"hotkeys",
|
||||
function()
|
||||
hotkeys_popup.show_help(nil, awful.screen.focused())
|
||||
end,
|
||||
},
|
||||
{ "manual", terminal .. " -e man awesome" },
|
||||
{ "edit config", editor_cmd .. " " .. awesome.conffile },
|
||||
{ "restart", awesome.restart },
|
||||
{
|
||||
"quit",
|
||||
function()
|
||||
awesome.quit()
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
local mymainmenu =
|
||||
awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon }, { "open terminal", terminal } } })
|
||||
|
||||
-- local mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon, menu = mymainmenu })
|
||||
|
||||
-- Menubar configuration
|
||||
menubar.utils.terminal = terminal -- Set the terminal for applications that require it
|
||||
-- }}}
|
||||
|
||||
-- Keyboard map indicator and switcher
|
||||
-- local mykeyboardlayout = awful.widget.keyboardlayout()
|
||||
|
||||
-- {{{ Wibar
|
||||
-- Create a textclock widget
|
||||
local mytextclock = wibox.widget.textclock(" %d.%m.%Y, %H:%M:%S ", 1)
|
||||
|
||||
local cw = calendar_widget({
|
||||
theme = "naughty",
|
||||
placement = "top_right",
|
||||
previous_month_button = 4,
|
||||
next_month_button = 5,
|
||||
})
|
||||
mytextclock:connect_signal("button::press", function(_, _, _, button)
|
||||
if button == 1 then
|
||||
cw.toggle()
|
||||
end
|
||||
end)
|
||||
|
||||
-- Create a wibox for each screen and add it
|
||||
local taglist_buttons = gears.table.join(
|
||||
awful.button({}, 1, function(t)
|
||||
t:view_only()
|
||||
end),
|
||||
awful.button({ modkey }, 1, function(t)
|
||||
if client.focus then
|
||||
client.focus:move_to_tag(t)
|
||||
end
|
||||
end),
|
||||
awful.button({}, 3, awful.tag.viewtoggle),
|
||||
awful.button({ modkey }, 3, function(t)
|
||||
if client.focus then
|
||||
client.focus:toggle_tag(t)
|
||||
end
|
||||
end),
|
||||
awful.button({}, 4, function(t)
|
||||
awful.tag.viewnext(t.screen)
|
||||
end),
|
||||
awful.button({}, 5, function(t)
|
||||
awful.tag.viewprev(t.screen)
|
||||
end)
|
||||
)
|
||||
|
||||
local tasklist_buttons = gears.table.join(
|
||||
awful.button({}, 1, function(c)
|
||||
if c == client.focus then
|
||||
c.minimized = true
|
||||
else
|
||||
c:emit_signal("request::activate", "tasklist", { raise = true })
|
||||
end
|
||||
end),
|
||||
awful.button({}, 3, function()
|
||||
awful.menu.client_list({ theme = { width = 250 } })
|
||||
end),
|
||||
awful.button({}, 4, function()
|
||||
awful.client.focus.byidx(1)
|
||||
end),
|
||||
awful.button({}, 5, function()
|
||||
awful.client.focus.byidx(-1)
|
||||
end)
|
||||
)
|
||||
|
||||
local function set_wallpaper(s)
|
||||
-- Wallpaper
|
||||
if beautiful.wallpaper then
|
||||
local wallpaper = beautiful.wallpaper
|
||||
-- If wallpaper is a function, call it with the screen
|
||||
if type(wallpaper) == "function" then
|
||||
wallpaper = wallpaper(s)
|
||||
end
|
||||
gears.wallpaper.maximized(wallpaper, s, true)
|
||||
end
|
||||
end
|
||||
|
||||
-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
|
||||
screen.connect_signal("property::geometry", set_wallpaper)
|
||||
|
||||
awful.screen.connect_for_each_screen(function(s)
|
||||
-- Wallpaper
|
||||
set_wallpaper(s)
|
||||
|
||||
-- Each screen has its own tag table.
|
||||
awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[1])
|
||||
|
||||
-- Create a promptbox for each screen
|
||||
s.mypromptbox = awful.widget.prompt()
|
||||
-- Create an imagebox widget which will contain an icon indicating which layout we're using.
|
||||
-- We need one layoutbox per screen.
|
||||
s.mylayoutbox = awful.widget.layoutbox(s)
|
||||
s.mylayoutbox:buttons(gears.table.join(
|
||||
awful.button({}, 1, function()
|
||||
awful.layout.inc(1)
|
||||
end),
|
||||
awful.button({}, 3, function()
|
||||
awful.layout.inc(-1)
|
||||
end),
|
||||
awful.button({}, 4, function()
|
||||
awful.layout.inc(1)
|
||||
end),
|
||||
awful.button({}, 5, function()
|
||||
awful.layout.inc(-1)
|
||||
end)
|
||||
))
|
||||
-- Create a taglist widget
|
||||
s.mytaglist = awful.widget.taglist({
|
||||
screen = s,
|
||||
filter = awful.widget.taglist.filter.all,
|
||||
buttons = taglist_buttons,
|
||||
})
|
||||
|
||||
-- Create a tasklist widget
|
||||
s.mytasklist = awful.widget.tasklist({
|
||||
screen = s,
|
||||
filter = awful.widget.tasklist.filter.currenttags,
|
||||
buttons = tasklist_buttons,
|
||||
})
|
||||
|
||||
-- Create the wibox
|
||||
s.mywibox = awful.wibar({ position = "top", screen = s })
|
||||
|
||||
-- Add widgets to the wibox
|
||||
s.mywibox:setup({
|
||||
layout = wibox.layout.align.horizontal,
|
||||
{
|
||||
-- Left widgets
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
--mylauncher,
|
||||
s.mytaglist,
|
||||
s.mypromptbox,
|
||||
},
|
||||
s.mytasklist, -- Middle widget
|
||||
{
|
||||
-- Right widgets
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
github_contributions_widget({
|
||||
username = "kristoferssolo",
|
||||
days = 356,
|
||||
color_of_empty_cells = "",
|
||||
with_border = true,
|
||||
margin_top = 1,
|
||||
theme = "teal",
|
||||
}),
|
||||
github_activity_widget({
|
||||
username = "kristoferssolo",
|
||||
number_of_events = 10,
|
||||
}),
|
||||
wibox.widget.systray(),
|
||||
cpu_widget({
|
||||
width = 50,
|
||||
step_width = 2,
|
||||
step_spacing = 0,
|
||||
color = beautiful.fg_nromal,
|
||||
enable_kill_button = true,
|
||||
process_info_max_length = -1,
|
||||
timeout = 1,
|
||||
}),
|
||||
net_speed_widget(),
|
||||
docker_widget(),
|
||||
spotify_widget({
|
||||
play_icon = "/usr/share/icons/Papirus-Light/24x24/categories/spotify.svg",
|
||||
pause_icon = "/usr/share/icons/Papirus-Dark/24x24/panel/spotify-indicator.svg",
|
||||
font = "JetBrainsMono NF 10",
|
||||
dim_when_paused = true,
|
||||
dim_opacity = 0.5,
|
||||
max_length = -1,
|
||||
show_tooltip = true,
|
||||
timeout = 1,
|
||||
}),
|
||||
batteryarc_widget({
|
||||
show_current_level = true,
|
||||
arc_thickness = 1,
|
||||
size = 8,
|
||||
}),
|
||||
logout_menu_widget({
|
||||
font = "JetBrainsMono NF 10",
|
||||
onlogout = function()
|
||||
awful.spawn.with_shell("loginctl kill-session self")
|
||||
end,
|
||||
onlock = function()
|
||||
awful.spawn.with_shell("xlock -mode random -duration 10")
|
||||
end,
|
||||
onreboot = function()
|
||||
awful.spawn.with_shell("loginctl reboot")
|
||||
end,
|
||||
onsuspend = function()
|
||||
awful.spawn.with_shell("doas zzz")
|
||||
end,
|
||||
onpoweroff = function()
|
||||
awful.spawn.with_shell("loginctl poweroff")
|
||||
end,
|
||||
}),
|
||||
mytextclock,
|
||||
s.mylayoutbox,
|
||||
},
|
||||
})
|
||||
end)
|
||||
-- }}}
|
||||
|
||||
-- {{{ Mouse bindings
|
||||
root.buttons(gears.table.join(
|
||||
awful.button({}, 3, function()
|
||||
mymainmenu:toggle()
|
||||
end),
|
||||
awful.button({}, 4, awful.tag.viewnext),
|
||||
awful.button({}, 5, awful.tag.viewprev)
|
||||
))
|
||||
-- }}}
|
||||
|
||||
-- {{{ Key bindings
|
||||
local globalkeys = gears.table.join(
|
||||
|
||||
awful.key({ "Shift" }, "Pause", function()
|
||||
awful.spawn.with_shell("playerctl play-pause -a")
|
||||
end, { description = "pause/play all", group = "media controls" }),
|
||||
|
||||
awful.key({ "Control" }, "Pause", function()
|
||||
awful.spawn.with_shell("playerctl pause -a")
|
||||
end, { description = "pause all", group = "media controls" }),
|
||||
|
||||
awful.key({}, "Pause", function()
|
||||
awful.spawn.with_shell("sp play")
|
||||
end, { description = "spotify pause/play", group = "media controls" }),
|
||||
|
||||
awful.key({}, "#117", function()
|
||||
awful.spawn.with_shell("sp next")
|
||||
end, { description = "spotify next", group = "media controls" }),
|
||||
|
||||
awful.key({}, "#112", function()
|
||||
awful.spawn.with_shell("sp prev")
|
||||
end, { description = "spotify previous", group = "media controls" }),
|
||||
|
||||
awful.key({ modkey }, "d", function()
|
||||
spotify_shell.launch()
|
||||
end, { description = "spotify shell", group = "media controls" }),
|
||||
|
||||
awful.key({}, "#171", function()
|
||||
awful.spawn.with_shell("sp next")
|
||||
end), -- play next
|
||||
|
||||
awful.key({}, "#173", function()
|
||||
awful.spawn.with_shell("sp previous")
|
||||
end), -- play previous
|
||||
|
||||
awful.key({}, "#174", function()
|
||||
awful.spawn.with_shell("playerctl -a stop")
|
||||
end), -- stop
|
||||
|
||||
awful.key({}, "#172", function()
|
||||
awful.spawn.with_shell("playerctl -a play-pause")
|
||||
end), -- play/pause all
|
||||
|
||||
awful.key({}, "#123", function()
|
||||
awful.spawn.with_shell("pulsemixer --change-volume +5")
|
||||
end), -- increase volume
|
||||
|
||||
awful.key({}, "#122", function()
|
||||
awful.spawn.with_shell("pulsemixer --change-volume -5")
|
||||
end), -- decrease volume
|
||||
|
||||
awful.key({}, "#121", function()
|
||||
awful.spawn.with_shell("pulsemixer --toggle-mute")
|
||||
end), -- mute
|
||||
|
||||
awful.key({ "Control" }, "#107", function()
|
||||
awful.spawn.with_shell("( flameshot &; ) && ( sleep 0.5s && flameshot gui )")
|
||||
end, { description = "take region screenshot", group = "launcher" }), -- take region screenshot
|
||||
|
||||
awful.key({ modkey }, "s", hotkeys_popup.show_help, { description = "show help", group = "awesome" }),
|
||||
awful.key({ modkey }, "Left", awful.tag.viewprev, { description = "view previous", group = "tag" }),
|
||||
awful.key({ modkey }, "Right", awful.tag.viewnext, { description = "view next", group = "tag" }),
|
||||
awful.key({ modkey }, "Escape", awful.tag.history.restore, { description = "go back", group = "tag" }),
|
||||
awful.key({ modkey }, "j", function()
|
||||
awful.client.focus.byidx(1)
|
||||
end, { description = "focus next by index", group = "client" }),
|
||||
awful.key({ modkey }, "k", function()
|
||||
awful.client.focus.byidx(-1)
|
||||
end, { description = "focus previous by index", group = "client" }),
|
||||
awful.key({ modkey }, "w", function()
|
||||
mymainmenu:show()
|
||||
end, { description = "show main menu", group = "awesome" }),
|
||||
|
||||
-- Layout manipulation
|
||||
awful.key({ modkey, "Shift" }, "j", function()
|
||||
awful.client.swap.byidx(1)
|
||||
end, { description = "swap with next client by index", group = "client" }),
|
||||
awful.key({ modkey, "Shift" }, "k", function()
|
||||
awful.client.swap.byidx(-1)
|
||||
end, { description = "swap with previous client by index", group = "client" }),
|
||||
awful.key({ modkey, "Control" }, "j", function()
|
||||
awful.screen.focus_relative(1)
|
||||
end, { description = "focus the next screen", group = "screen" }),
|
||||
awful.key({ modkey, "Control" }, "k", function()
|
||||
awful.screen.focus_relative(-1)
|
||||
end, { description = "focus the previous screen", group = "screen" }),
|
||||
awful.key({ modkey }, "u", awful.client.urgent.jumpto, { description = "jump to urgent client", group = "client" }),
|
||||
awful.key({ modkey }, "Tab", function()
|
||||
awful.client.focus.history.previous()
|
||||
if client.focus then
|
||||
client.focus:raise()
|
||||
end
|
||||
end, { description = "go back", group = "client" }),
|
||||
|
||||
-- Standard program
|
||||
awful.key({ modkey }, "Return", function()
|
||||
awful.spawn(terminal)
|
||||
end, { description = "open a terminal", group = "launcher" }),
|
||||
awful.key({ modkey, "Control" }, "r", awesome.restart, { description = "reload awesome", group = "awesome" }),
|
||||
|
||||
-- awful.key({ modkey, "Control" }, "q", awesome.quit, { description = "quit awesome", group = "awesome" }),
|
||||
|
||||
awful.key({ modkey }, "b", function()
|
||||
awful.spawn("floorp")
|
||||
end, { description = "open browser", group = "launcher" }),
|
||||
awful.key({ modkey }, "n", function()
|
||||
awful.spawn("alacritty -e yazi")
|
||||
end, { description = "open yazi", group = "launcher" }),
|
||||
|
||||
awful.key({ modkey }, "l", function()
|
||||
awful.tag.incmwfact(0.05)
|
||||
end, { description = "increase master width factor", group = "layout" }),
|
||||
awful.key({ modkey }, "h", function()
|
||||
awful.tag.incmwfact(-0.05)
|
||||
end, { description = "decrease master width factor", group = "layout" }),
|
||||
awful.key({ modkey, "Shift" }, "h", function()
|
||||
awful.tag.incnmaster(1, nil, true)
|
||||
end, { description = "increase the number of master clients", group = "layout" }),
|
||||
awful.key({ modkey, "Shift" }, "l", function()
|
||||
awful.tag.incnmaster(-1, nil, true)
|
||||
end, { description = "decrease the number of master clients", group = "layout" }),
|
||||
awful.key({ modkey, "Control" }, "h", function()
|
||||
awful.tag.incncol(1, nil, true)
|
||||
end, { description = "increase the number of columns", group = "layout" }),
|
||||
awful.key({ modkey, "Control" }, "l", function()
|
||||
awful.tag.incncol(-1, nil, true)
|
||||
end, { description = "decrease the number of columns", group = "layout" }),
|
||||
awful.key({ modkey }, "space", function()
|
||||
awful.layout.inc(1)
|
||||
end, { description = "select next", group = "layout" }),
|
||||
awful.key({ modkey, "Shift" }, "space", function()
|
||||
awful.layout.inc(-1)
|
||||
end, { description = "select previous", group = "layout" }),
|
||||
|
||||
-- awful.key({ modkey, "Control" }, "n", function()
|
||||
-- local c = awful.client.restore()
|
||||
-- -- Focus restored client
|
||||
-- if c then
|
||||
-- c:emit_signal("request::activate", "key.unminimize", { raise = true })
|
||||
-- end
|
||||
-- end, { description = "restore minimized", group = "client" }),
|
||||
|
||||
-- Prompt
|
||||
awful.key({ modkey }, "r", function()
|
||||
awful.screen.focused().mypromptbox:run()
|
||||
end, { description = "run prompt", group = "launcher" }),
|
||||
|
||||
awful.key({ modkey }, "x", function()
|
||||
awful.prompt.run({
|
||||
prompt = "Run Lua code: ",
|
||||
textbox = awful.screen.focused().mypromptbox.widget,
|
||||
exe_callback = awful.util.eval,
|
||||
history_path = awful.util.get_cache_dir() .. "/history_eval",
|
||||
})
|
||||
end, { description = "lua execute prompt", group = "awesome" }),
|
||||
-- Menubar
|
||||
awful.key({ modkey }, "p", function()
|
||||
menubar.show()
|
||||
end, { description = "show the menubar", group = "launcher" })
|
||||
)
|
||||
|
||||
local clientkeys = gears.table.join(
|
||||
awful.key({ modkey }, "f", function(c)
|
||||
c.fullscreen = not c.fullscreen
|
||||
c:raise()
|
||||
end, { description = "toggle fullscreen", group = "client" }),
|
||||
awful.key({ modkey, "Shift" }, "q", function(c)
|
||||
c:kill()
|
||||
end, { description = "close", group = "client" }),
|
||||
awful.key(
|
||||
{ modkey, "Control" },
|
||||
"space",
|
||||
awful.client.floating.toggle,
|
||||
{ description = "toggle floating", group = "client" }
|
||||
),
|
||||
awful.key({ modkey, "Control" }, "Return", function(c)
|
||||
c:swap(awful.client.getmaster())
|
||||
end, { description = "move to master", group = "client" }),
|
||||
awful.key({ modkey }, "o", function(c)
|
||||
c:move_to_screen()
|
||||
end, { description = "move to screen", group = "client" }),
|
||||
awful.key({ modkey }, "t", function(c)
|
||||
c.ontop = not c.ontop
|
||||
end, { description = "toggle keep on top", group = "client" }),
|
||||
-- awful.key({ modkey }, "n", function(c)
|
||||
-- -- The client currently has the input focus, so it cannot be
|
||||
-- -- minimized, since minimized clients can't have the focus.
|
||||
-- c.minimized = true
|
||||
-- end, { description = "minimize", group = "client" }),
|
||||
awful.key({ modkey }, "m", function(c)
|
||||
c.maximized = not c.maximized
|
||||
c:raise()
|
||||
end, { description = "(un)maximize", group = "client" }),
|
||||
awful.key({ modkey, "Control" }, "m", function(c)
|
||||
c.maximized_vertical = not c.maximized_vertical
|
||||
c:raise()
|
||||
end, { description = "(un)maximize vertically", group = "client" }),
|
||||
awful.key({ modkey, "Shift" }, "m", function(c)
|
||||
c.maximized_horizontal = not c.maximized_horizontal
|
||||
c:raise()
|
||||
end, { description = "(un)maximize horizontally", group = "client" })
|
||||
)
|
||||
|
||||
-- Bind all key numbers to tags.
|
||||
-- Be careful: we use keycodes to make it work on any keyboard layout.
|
||||
-- This should map on the top row of your keyboard, usually 1 to 9.
|
||||
for i = 1, 9 do
|
||||
globalkeys = gears.table.join(
|
||||
globalkeys,
|
||||
-- View tag only.
|
||||
awful.key({ modkey }, "#" .. i + 9, function()
|
||||
local screen = awful.screen.focused()
|
||||
local tag = screen.tags[i]
|
||||
if tag then
|
||||
tag:view_only()
|
||||
end
|
||||
end, { description = "view tag #" .. i, group = "tag" }),
|
||||
-- Toggle tag display.
|
||||
awful.key({ modkey, "Control" }, "#" .. i + 9, function()
|
||||
local screen = awful.screen.focused()
|
||||
local tag = screen.tags[i]
|
||||
if tag then
|
||||
awful.tag.viewtoggle(tag)
|
||||
end
|
||||
end, { description = "toggle tag #" .. i, group = "tag" }),
|
||||
-- Move client to tag.
|
||||
awful.key({ modkey, "Shift" }, "#" .. i + 9, function()
|
||||
if client.focus then
|
||||
local tag = client.focus.screen.tags[i]
|
||||
if tag then
|
||||
client.focus:move_to_tag(tag)
|
||||
end
|
||||
end
|
||||
end, { description = "move focused client to tag #" .. i, group = "tag" }),
|
||||
-- Toggle tag on focused client.
|
||||
awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9, function()
|
||||
if client.focus then
|
||||
local tag = client.focus.screen.tags[i]
|
||||
if tag then
|
||||
client.focus:toggle_tag(tag)
|
||||
end
|
||||
end
|
||||
end, { description = "toggle focused client on tag #" .. i, group = "tag" })
|
||||
)
|
||||
end
|
||||
|
||||
local clientbuttons = gears.table.join(
|
||||
awful.button({}, 1, function(c)
|
||||
c:emit_signal("request::activate", "mouse_click", { raise = true })
|
||||
end),
|
||||
awful.button({ modkey }, 1, function(c)
|
||||
c:emit_signal("request::activate", "mouse_click", { raise = true })
|
||||
awful.mouse.client.move(c)
|
||||
end),
|
||||
awful.button({ modkey }, 3, function(c)
|
||||
c:emit_signal("request::activate", "mouse_click", { raise = true })
|
||||
awful.mouse.client.resize(c)
|
||||
end)
|
||||
)
|
||||
|
||||
-- Set keys
|
||||
root.keys(globalkeys)
|
||||
-- }}}
|
||||
|
||||
-- {{{ Rules
|
||||
-- Rules to apply to new clients (through the "manage" signal).
|
||||
awful.rules.rules = {
|
||||
-- All clients will match this rule.
|
||||
{
|
||||
rule = {},
|
||||
properties = {
|
||||
border_width = beautiful.border_width,
|
||||
border_color = beautiful.border_normal,
|
||||
focus = awful.client.focus.filter,
|
||||
raise = true,
|
||||
keys = clientkeys,
|
||||
buttons = clientbuttons,
|
||||
screen = awful.screen.preferred,
|
||||
placement = awful.placement.no_overlap + awful.placement.no_offscreen,
|
||||
},
|
||||
},
|
||||
|
||||
-- Floating clients.
|
||||
{
|
||||
rule_any = {
|
||||
instance = {
|
||||
"DTA", -- Firefox addon DownThemAll.
|
||||
"copyq", -- Includes session name in class.
|
||||
"pinentry",
|
||||
},
|
||||
class = {
|
||||
"Arandr",
|
||||
"Blueman-manager",
|
||||
"Gpick",
|
||||
"Kruler",
|
||||
"MessageWin", -- kalarm.
|
||||
"Tor Browser", -- Needs a fixed window size to avoid fingerprinting by screen size.
|
||||
"Wpa_gui",
|
||||
"veromix",
|
||||
"xtightvncviewer",
|
||||
"Nsxiv",
|
||||
"Galculator",
|
||||
},
|
||||
-- Note that the name property shown in xprop might be set slightly after creation of the client
|
||||
-- and the name shown there might not match defined rules here.
|
||||
name = {
|
||||
"Event Tester", -- xev.
|
||||
},
|
||||
role = {
|
||||
"AlarmWindow", -- Thunderbird's calendar.
|
||||
"ConfigManager", -- Thunderbird's about:config.
|
||||
"pop-up", -- e.g. Google Chrome's (detached) Developer Tools.
|
||||
},
|
||||
},
|
||||
properties = { floating = true, placement = awful.placement.centered, beautiful.useless },
|
||||
},
|
||||
|
||||
-- Add titlebars to normal clients and dialogs
|
||||
{ rule_any = { type = { "normal", "dialog" } }, properties = { titlebars_enabled = false } },
|
||||
|
||||
{
|
||||
rule_any = {
|
||||
class = {
|
||||
-- "steam_app_1172470",
|
||||
-- "steam_app_1237970",
|
||||
-- "steam_app_289070",
|
||||
-- "steam_app_1172380",
|
||||
"steam_app_1774580",
|
||||
"steam_app_1182480",
|
||||
},
|
||||
},
|
||||
properties = { screen = 1, fullscreen = true, floating = true },
|
||||
},
|
||||
{
|
||||
rule_any = { class = { "Ferdium" } },
|
||||
properties = { screen = 1, tag = "5" },
|
||||
},
|
||||
{
|
||||
rule_any = { class = { "discord", "TelegramDesktop", "ripcord", "KotatogramDesktop" } },
|
||||
properties = { screen = 1, tag = "8" },
|
||||
},
|
||||
{
|
||||
rule_any = { class = { "easyeffects" } },
|
||||
properties = { screen = 1, tag = "9" },
|
||||
},
|
||||
{ rule_any = { class = { "kdeconnect.app" } }, properties = { screen = 1, tag = "7" } },
|
||||
{ rule_any = { class = { "Spotify" } }, properties = { screen = 1, tag = "9" } },
|
||||
{ rule_any = { class = { "mpv" } }, properties = { fullscreen = true } },
|
||||
}
|
||||
|
||||
-- {{{ Signals
|
||||
-- Signal function to execute when a new client appears.
|
||||
client.connect_signal("manage", function(c)
|
||||
-- Set the windows at the slave,
|
||||
-- i.e. put it at the end of others instead of setting it master.
|
||||
-- if not awesome.startup then awful.client.setslave(c) end
|
||||
|
||||
if awesome.startup and not c.size_hints.user_position and not c.size_hints.program_position then
|
||||
-- Prevent clients from being unreachable after screen count changes.
|
||||
awful.placement.no_offscreen(c)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Add a titlebar if titlebars_enabled is set to true in the rules.
|
||||
client.connect_signal("request::titlebars", function(c)
|
||||
-- buttons for the titlebar
|
||||
local buttons = gears.table.join(
|
||||
awful.button({}, 1, function()
|
||||
c:emit_signal("request::activate", "titlebar", { raise = true })
|
||||
awful.mouse.client.move(c)
|
||||
end),
|
||||
awful.button({}, 3, function()
|
||||
c:emit_signal("request::activate", "titlebar", { raise = true })
|
||||
awful.mouse.client.resize(c)
|
||||
end)
|
||||
)
|
||||
|
||||
awful.titlebar(c):setup({
|
||||
{
|
||||
-- Left
|
||||
awful.titlebar.widget.iconwidget(c),
|
||||
buttons = buttons,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
{
|
||||
-- Middle
|
||||
{
|
||||
-- Title
|
||||
align = "center",
|
||||
widget = awful.titlebar.widget.titlewidget(c),
|
||||
},
|
||||
buttons = buttons,
|
||||
layout = wibox.layout.flex.horizontal,
|
||||
},
|
||||
{
|
||||
-- Right
|
||||
awful.titlebar.widget.floatingbutton(c),
|
||||
awful.titlebar.widget.maximizedbutton(c),
|
||||
awful.titlebar.widget.stickybutton(c),
|
||||
awful.titlebar.widget.ontopbutton(c),
|
||||
awful.titlebar.widget.closebutton(c),
|
||||
layout = wibox.layout.fixed.horizontal(),
|
||||
},
|
||||
layout = wibox.layout.align.horizontal,
|
||||
})
|
||||
end)
|
||||
|
||||
-- Enable sloppy focus, so that focus follows mouse.
|
||||
client.connect_signal("mouse::enter", function(c)
|
||||
c:emit_signal("request::activate", "mouse_enter", { raise = false })
|
||||
end)
|
||||
|
||||
client.connect_signal("focus", function(c)
|
||||
c.border_color = beautiful.border_focus
|
||||
end)
|
||||
client.connect_signal("unfocus", function(c)
|
||||
c.border_color = beautiful.border_normal
|
||||
end)
|
||||
752
config/awesome/rc.lua
Normal file
752
config/awesome/rc.lua
Normal file
@@ -0,0 +1,752 @@
|
||||
-- If LuaRocks is installed, make sure that packages installed through it are
|
||||
-- found (e.g. lgi). If LuaRocks is not installed, do nothing.
|
||||
pcall(require, "luarocks.loader")
|
||||
|
||||
-- AwesomeWM Widgets
|
||||
local calendar_widget = require("awesome-wm-widgets.calendar-widget.calendar")
|
||||
local cpu_widget = require("awesome-wm-widgets.cpu-widget.cpu-widget")
|
||||
local logout_menu_widget = require("awesome-wm-widgets.logout-menu-widget.logout-menu")
|
||||
local net_speed_widget = require("awesome-wm-widgets.net-speed-widget.net-speed")
|
||||
local spotify_shell = require("awesome-wm-widgets.spotify-shell.spotify-shell")
|
||||
local spotify_widget = require("awesome-wm-widgets.spotify-widget.spotify")
|
||||
local github_activity_widget = require("awesome-wm-widgets.github-activity-widget.github-activity-widget")
|
||||
local github_contributions_widget =
|
||||
require("awesome-wm-widgets.github-contributions-widget.github-contributions-widget")
|
||||
-- local docker_widget = require("awesome-wm-widgets.docker-widget.docker")
|
||||
|
||||
-- Standard awesome library
|
||||
local gears = require("gears")
|
||||
local awful = require("awful")
|
||||
require("awful.autofocus")
|
||||
-- Widget and layout library
|
||||
local wibox = require("wibox")
|
||||
-- Theme handling library
|
||||
local beautiful = require("beautiful")
|
||||
-- Notification library
|
||||
local naughty = require("naughty")
|
||||
local menubar = require("menubar")
|
||||
local hotkeys_popup = require("awful.hotkeys_popup")
|
||||
-- Enable hotkeys help widget for VIM and other apps
|
||||
-- when client with a matching name is opened:
|
||||
require("awful.hotkeys_popup.keys")
|
||||
|
||||
-- {{{ Error handling
|
||||
-- Check if awesome encountered an error during startup and fell back to
|
||||
-- another config (This code will only ever execute for the fallback config)
|
||||
if awesome.startup_errors then
|
||||
naughty.notify({
|
||||
preset = naughty.config.presets.critical,
|
||||
title = "Oops, there were errors during startup!",
|
||||
text = awesome.startup_errors,
|
||||
})
|
||||
end
|
||||
|
||||
-- Handle runtime errors after startup
|
||||
do
|
||||
local in_error = false
|
||||
awesome.connect_signal("debug::error", function(err)
|
||||
-- Make sure we don't go into an endless error loop
|
||||
if in_error then
|
||||
return
|
||||
end
|
||||
in_error = true
|
||||
|
||||
naughty.notify({
|
||||
preset = naughty.config.presets.critical,
|
||||
title = "Oops, an error happened!",
|
||||
text = tostring(err),
|
||||
})
|
||||
in_error = false
|
||||
end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Variable definitions
|
||||
-- Themes define colours, icons, font and wallpapers.
|
||||
-- beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua")
|
||||
beautiful.init(gears.filesystem.get_configuration_dir() .. "mytheme.lua")
|
||||
|
||||
-- This is used later as the default terminal and editor to run.
|
||||
local terminal = "alacritty"
|
||||
local editor = os.getenv("EDITOR") or "nvim"
|
||||
local editor_cmd = terminal .. " -e " .. editor
|
||||
|
||||
-- Default modkey.
|
||||
-- Usually, Mod4 is the key with a logo between Control and Alt.
|
||||
-- If you do not like this or do not have such a key,
|
||||
-- I suggest you to remap Mod4 to another key using xmodmap or other tools.
|
||||
-- However, you can use another modifier like Mod1, but it may interact with others.
|
||||
|
||||
local modkey = "Mod4"
|
||||
|
||||
-- Table of layouts to cover with awful.layout.inc, order matters.
|
||||
awful.layout.layouts = {
|
||||
awful.layout.suit.tile,
|
||||
awful.layout.suit.tile.left,
|
||||
awful.layout.suit.fair,
|
||||
awful.layout.suit.fair.horizontal,
|
||||
-- awful.layout.suit.spiral.dwindle,
|
||||
-- awful.layout.suit.spiral,
|
||||
-- awful.layout.suit.floating,
|
||||
-- awful.layout.suit.tile.bottom,
|
||||
-- awful.layout.suit.tile.top,
|
||||
-- awful.layout.suit.max,
|
||||
-- awful.layout.suit.max.fullscreen,
|
||||
-- awful.layout.suit.magnifier,
|
||||
awful.layout.suit.corner.nw,
|
||||
-- awful.layout.suit.corner.ne,
|
||||
-- awful.layout.suit.corner.sw,
|
||||
-- awful.layout.suit.corner.se,
|
||||
}
|
||||
-- }}}
|
||||
|
||||
-- {{{ Menu
|
||||
-- Create a launcher widget and a main menu
|
||||
local myawesomemenu = {
|
||||
{
|
||||
"hotkeys",
|
||||
function()
|
||||
hotkeys_popup.show_help(nil, awful.screen.focused())
|
||||
end,
|
||||
},
|
||||
{ "manual", terminal .. " -e man awesome" },
|
||||
{ "edit config", editor_cmd .. " " .. awesome.conffile },
|
||||
{ "restart", awesome.restart },
|
||||
{
|
||||
"quit",
|
||||
function()
|
||||
awesome.quit()
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
local mymainmenu =
|
||||
awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon }, { "open terminal", terminal } } })
|
||||
|
||||
-- local mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon, menu = mymainmenu })
|
||||
|
||||
-- Menubar configuration
|
||||
menubar.utils.terminal = terminal -- Set the terminal for applications that require it
|
||||
-- }}}
|
||||
|
||||
-- Keyboard map indicator and switcher
|
||||
-- local mykeyboardlayout = awful.widget.keyboardlayout()
|
||||
|
||||
-- {{{ Wibar
|
||||
-- Create a textclock widget
|
||||
local mytextclock = wibox.widget.textclock(" %d.%m.%Y, %H:%M:%S ", 1)
|
||||
|
||||
local cw = calendar_widget({
|
||||
theme = "naughty",
|
||||
placement = "top_right",
|
||||
previous_month_button = 4,
|
||||
next_month_button = 5,
|
||||
})
|
||||
mytextclock:connect_signal("button::press", function(_, _, _, button)
|
||||
if button == 1 then
|
||||
cw.toggle()
|
||||
end
|
||||
end)
|
||||
|
||||
-- Create a wibox for each screen and add it
|
||||
local taglist_buttons = gears.table.join(
|
||||
awful.button({}, 1, function(t)
|
||||
t:view_only()
|
||||
end),
|
||||
awful.button({ modkey }, 1, function(t)
|
||||
if client.focus then
|
||||
client.focus:move_to_tag(t)
|
||||
end
|
||||
end),
|
||||
awful.button({}, 3, awful.tag.viewtoggle),
|
||||
awful.button({ modkey }, 3, function(t)
|
||||
if client.focus then
|
||||
client.focus:toggle_tag(t)
|
||||
end
|
||||
end),
|
||||
awful.button({}, 4, function(t)
|
||||
awful.tag.viewnext(t.screen)
|
||||
end),
|
||||
awful.button({}, 5, function(t)
|
||||
awful.tag.viewprev(t.screen)
|
||||
end)
|
||||
)
|
||||
|
||||
local tasklist_buttons = gears.table.join(
|
||||
awful.button({}, 1, function(c)
|
||||
if c == client.focus then
|
||||
c.minimized = true
|
||||
else
|
||||
c:emit_signal("request::activate", "tasklist", { raise = true })
|
||||
end
|
||||
end),
|
||||
awful.button({}, 3, function()
|
||||
awful.menu.client_list({ theme = { width = 250 } })
|
||||
end),
|
||||
awful.button({}, 4, function()
|
||||
awful.client.focus.byidx(1)
|
||||
end),
|
||||
awful.button({}, 5, function()
|
||||
awful.client.focus.byidx(-1)
|
||||
end)
|
||||
)
|
||||
|
||||
local function set_wallpaper(s)
|
||||
-- Wallpaper
|
||||
if beautiful.wallpaper then
|
||||
local wallpaper = beautiful.wallpaper
|
||||
-- If wallpaper is a function, call it with the screen
|
||||
if type(wallpaper) == "function" then
|
||||
wallpaper = wallpaper(s)
|
||||
end
|
||||
gears.wallpaper.maximized(wallpaper, s, true)
|
||||
end
|
||||
end
|
||||
|
||||
-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
|
||||
screen.connect_signal("property::geometry", set_wallpaper)
|
||||
|
||||
awful.screen.connect_for_each_screen(function(s)
|
||||
-- Wallpaper
|
||||
set_wallpaper(s)
|
||||
|
||||
-- Each screen has its own tag table.
|
||||
awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[1])
|
||||
|
||||
-- Create a promptbox for each screen
|
||||
s.mypromptbox = awful.widget.prompt()
|
||||
-- Create an imagebox widget which will contain an icon indicating which layout we're using.
|
||||
-- We need one layoutbox per screen.
|
||||
s.mylayoutbox = awful.widget.layoutbox(s)
|
||||
s.mylayoutbox:buttons(gears.table.join(
|
||||
awful.button({}, 1, function()
|
||||
awful.layout.inc(1)
|
||||
end),
|
||||
awful.button({}, 3, function()
|
||||
awful.layout.inc(-1)
|
||||
end),
|
||||
awful.button({}, 4, function()
|
||||
awful.layout.inc(1)
|
||||
end),
|
||||
awful.button({}, 5, function()
|
||||
awful.layout.inc(-1)
|
||||
end)
|
||||
))
|
||||
-- Create a taglist widget
|
||||
s.mytaglist = awful.widget.taglist({
|
||||
screen = s,
|
||||
filter = awful.widget.taglist.filter.all,
|
||||
buttons = taglist_buttons,
|
||||
})
|
||||
|
||||
-- Create a tasklist widget
|
||||
s.mytasklist = awful.widget.tasklist({
|
||||
screen = s,
|
||||
filter = awful.widget.tasklist.filter.currenttags,
|
||||
buttons = tasklist_buttons,
|
||||
})
|
||||
|
||||
-- Create the wibox
|
||||
s.mywibox = awful.wibar({ position = "top", screen = s })
|
||||
|
||||
-- Add widgets to the wibox
|
||||
s.mywibox:setup({
|
||||
layout = wibox.layout.align.horizontal,
|
||||
{
|
||||
-- Left widgets
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
--mylauncher,
|
||||
s.mytaglist,
|
||||
s.mypromptbox,
|
||||
},
|
||||
s.mytasklist, -- Middle widget
|
||||
{
|
||||
-- Right widgets
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
github_contributions_widget({
|
||||
username = "kristoferssolo",
|
||||
days = 356,
|
||||
color_of_empty_cells = "",
|
||||
with_border = true,
|
||||
margin_top = 1,
|
||||
theme = "teal",
|
||||
}),
|
||||
github_activity_widget({
|
||||
username = "kristoferssolo",
|
||||
number_of_events = 10,
|
||||
}),
|
||||
wibox.widget.systray(),
|
||||
cpu_widget({
|
||||
width = 50,
|
||||
step_width = 2,
|
||||
step_spacing = 0,
|
||||
color = beautiful.fg_nromal,
|
||||
enable_kill_button = true,
|
||||
process_info_max_length = -1,
|
||||
timeout = 1,
|
||||
}),
|
||||
net_speed_widget(),
|
||||
-- docker_widget(),
|
||||
spotify_widget({
|
||||
play_icon = "/usr/share/icons/Papirus-Light/24x24/categories/spotify.svg",
|
||||
pause_icon = "/usr/share/icons/Papirus-Dark/24x24/panel/spotify-indicator.svg",
|
||||
font = "JetBrainsMono NF 10",
|
||||
dim_when_paused = true,
|
||||
dim_opacity = 0.5,
|
||||
max_length = -1,
|
||||
show_tooltip = true,
|
||||
timeout = 1,
|
||||
}),
|
||||
logout_menu_widget({
|
||||
font = "JetBrainsMono NF 10",
|
||||
onlogout = function()
|
||||
awful.spawn.with_shell("loginctl kill-session self")
|
||||
end,
|
||||
onlock = function()
|
||||
awful.spawn.with_shell("xlock -mode random -duration 10")
|
||||
end,
|
||||
onreboot = function()
|
||||
awful.spawn.with_shell("loginctl reboot")
|
||||
end,
|
||||
onsuspend = function()
|
||||
awful.spawn.with_shell("doas zzz")
|
||||
end,
|
||||
onpoweroff = function()
|
||||
awful.spawn.with_shell("loginctl poweroff")
|
||||
end,
|
||||
}),
|
||||
mytextclock,
|
||||
s.mylayoutbox,
|
||||
},
|
||||
})
|
||||
end)
|
||||
-- }}}
|
||||
|
||||
-- {{{ Mouse bindings
|
||||
root.buttons(gears.table.join(
|
||||
awful.button({}, 3, function()
|
||||
mymainmenu:toggle()
|
||||
end),
|
||||
awful.button({}, 4, awful.tag.viewnext),
|
||||
awful.button({}, 5, awful.tag.viewprev)
|
||||
))
|
||||
-- }}}
|
||||
|
||||
-- {{{ Key bindings
|
||||
local globalkeys = gears.table.join(
|
||||
|
||||
awful.key({ "Shift" }, "Pause", function()
|
||||
awful.spawn.with_shell("playerctl play-pause -a")
|
||||
end, { description = "pause/play all", group = "media controls" }),
|
||||
|
||||
awful.key({ "Control" }, "Pause", function()
|
||||
awful.spawn.with_shell("playerctl pause -a")
|
||||
end, { description = "pause all", group = "media controls" }),
|
||||
|
||||
awful.key({}, "Pause", function()
|
||||
awful.spawn.with_shell("sp play")
|
||||
end, { description = "spotify pause/play", group = "media controls" }),
|
||||
|
||||
awful.key({}, "#117", function()
|
||||
awful.spawn.with_shell("sp next")
|
||||
end, { description = "spotify next", group = "media controls" }),
|
||||
|
||||
awful.key({}, "#112", function()
|
||||
awful.spawn.with_shell("sp prev")
|
||||
end, { description = "spotify previous", group = "media controls" }),
|
||||
|
||||
awful.key({ modkey }, "d", function()
|
||||
spotify_shell.launch()
|
||||
end, { description = "spotify shell", group = "media controls" }),
|
||||
|
||||
awful.key({}, "#171", function()
|
||||
awful.spawn.with_shell("sp next")
|
||||
end), -- play next
|
||||
|
||||
awful.key({}, "#173", function()
|
||||
awful.spawn.with_shell("sp previous")
|
||||
end), -- play previous
|
||||
|
||||
awful.key({}, "#174", function()
|
||||
awful.spawn.with_shell("playerctl -a stop")
|
||||
end), -- stop
|
||||
|
||||
awful.key({}, "#172", function()
|
||||
awful.spawn.with_shell("playerctl -a play-pause")
|
||||
end), -- play/pause all
|
||||
|
||||
awful.key({}, "#123", function()
|
||||
awful.spawn.with_shell("pulsemixer --change-volume +5")
|
||||
end), -- increase volume
|
||||
|
||||
awful.key({}, "#122", function()
|
||||
awful.spawn.with_shell("pulsemixer --change-volume -5")
|
||||
end), -- decrease volume
|
||||
|
||||
awful.key({}, "#121", function()
|
||||
awful.spawn.with_shell("pulsemixer --toggle-mute")
|
||||
end), -- mute
|
||||
|
||||
awful.key({ "Control" }, "#107", function()
|
||||
awful.spawn.with_shell("( flameshot &; ) && ( sleep 0.5s && flameshot gui )")
|
||||
end, { description = "take region screenshot", group = "launcher" }), -- take region screenshot
|
||||
|
||||
awful.key({ modkey }, "s", hotkeys_popup.show_help, { description = "show help", group = "awesome" }),
|
||||
awful.key({ modkey }, "Left", awful.tag.viewprev, { description = "view previous", group = "tag" }),
|
||||
awful.key({ modkey }, "Right", awful.tag.viewnext, { description = "view next", group = "tag" }),
|
||||
awful.key({ modkey }, "Escape", awful.tag.history.restore, { description = "go back", group = "tag" }),
|
||||
awful.key({ modkey }, "j", function()
|
||||
awful.client.focus.byidx(1)
|
||||
end, { description = "focus next by index", group = "client" }),
|
||||
awful.key({ modkey }, "k", function()
|
||||
awful.client.focus.byidx(-1)
|
||||
end, { description = "focus previous by index", group = "client" }),
|
||||
awful.key({ modkey }, "w", function()
|
||||
mymainmenu:show()
|
||||
end, { description = "show main menu", group = "awesome" }),
|
||||
|
||||
-- Layout manipulation
|
||||
awful.key({ modkey, "Shift" }, "j", function()
|
||||
awful.client.swap.byidx(1)
|
||||
end, { description = "swap with next client by index", group = "client" }),
|
||||
awful.key({ modkey, "Shift" }, "k", function()
|
||||
awful.client.swap.byidx(-1)
|
||||
end, { description = "swap with previous client by index", group = "client" }),
|
||||
awful.key({ modkey, "Control" }, "j", function()
|
||||
awful.screen.focus_relative(1)
|
||||
end, { description = "focus the next screen", group = "screen" }),
|
||||
awful.key({ modkey, "Control" }, "k", function()
|
||||
awful.screen.focus_relative(-1)
|
||||
end, { description = "focus the previous screen", group = "screen" }),
|
||||
awful.key({ modkey }, "u", awful.client.urgent.jumpto, { description = "jump to urgent client", group = "client" }),
|
||||
awful.key({ modkey }, "Tab", function()
|
||||
awful.client.focus.history.previous()
|
||||
if client.focus then
|
||||
client.focus:raise()
|
||||
end
|
||||
end, { description = "go back", group = "client" }),
|
||||
|
||||
-- Standard program
|
||||
awful.key({ modkey }, "Return", function()
|
||||
awful.spawn(terminal)
|
||||
end, { description = "open a terminal", group = "launcher" }),
|
||||
awful.key({ modkey, "Control" }, "r", awesome.restart, { description = "reload awesome", group = "awesome" }),
|
||||
|
||||
-- awful.key({ modkey, "Control" }, "q", awesome.quit, { description = "quit awesome", group = "awesome" }),
|
||||
|
||||
awful.key({ modkey }, "b", function()
|
||||
awful.spawn("floorp")
|
||||
end, { description = "open browser", group = "launcher" }),
|
||||
awful.key({ modkey }, "n", function()
|
||||
awful.spawn("alacritty -e yazi")
|
||||
end, { description = "open yazi", group = "launcher" }),
|
||||
|
||||
awful.key({ modkey }, "l", function()
|
||||
awful.tag.incmwfact(0.05)
|
||||
end, { description = "increase master width factor", group = "layout" }),
|
||||
awful.key({ modkey }, "h", function()
|
||||
awful.tag.incmwfact(-0.05)
|
||||
end, { description = "decrease master width factor", group = "layout" }),
|
||||
awful.key({ modkey, "Shift" }, "h", function()
|
||||
awful.tag.incnmaster(1, nil, true)
|
||||
end, { description = "increase the number of master clients", group = "layout" }),
|
||||
awful.key({ modkey, "Shift" }, "l", function()
|
||||
awful.tag.incnmaster(-1, nil, true)
|
||||
end, { description = "decrease the number of master clients", group = "layout" }),
|
||||
awful.key({ modkey, "Control" }, "h", function()
|
||||
awful.tag.incncol(1, nil, true)
|
||||
end, { description = "increase the number of columns", group = "layout" }),
|
||||
awful.key({ modkey, "Control" }, "l", function()
|
||||
awful.tag.incncol(-1, nil, true)
|
||||
end, { description = "decrease the number of columns", group = "layout" }),
|
||||
awful.key({ modkey }, "space", function()
|
||||
awful.layout.inc(1)
|
||||
end, { description = "select next", group = "layout" }),
|
||||
awful.key({ modkey, "Shift" }, "space", function()
|
||||
awful.layout.inc(-1)
|
||||
end, { description = "select previous", group = "layout" }),
|
||||
|
||||
-- awful.key({ modkey, "Control" }, "n", function()
|
||||
-- local c = awful.client.restore()
|
||||
-- -- Focus restored client
|
||||
-- if c then
|
||||
-- c:emit_signal("request::activate", "key.unminimize", { raise = true })
|
||||
-- end
|
||||
-- end, { description = "restore minimized", group = "client" }),
|
||||
|
||||
-- Prompt
|
||||
awful.key({ modkey }, "r", function()
|
||||
awful.screen.focused().mypromptbox:run()
|
||||
end, { description = "run prompt", group = "launcher" }),
|
||||
|
||||
awful.key({ modkey }, "x", function()
|
||||
awful.prompt.run({
|
||||
prompt = "Run Lua code: ",
|
||||
textbox = awful.screen.focused().mypromptbox.widget,
|
||||
exe_callback = awful.util.eval,
|
||||
history_path = awful.util.get_cache_dir() .. "/history_eval",
|
||||
})
|
||||
end, { description = "lua execute prompt", group = "awesome" }),
|
||||
-- Menubar
|
||||
awful.key({ modkey }, "p", function()
|
||||
menubar.show()
|
||||
end, { description = "show the menubar", group = "launcher" })
|
||||
)
|
||||
|
||||
local clientkeys = gears.table.join(
|
||||
awful.key({ modkey }, "f", function(c)
|
||||
c.fullscreen = not c.fullscreen
|
||||
c:raise()
|
||||
end, { description = "toggle fullscreen", group = "client" }),
|
||||
awful.key({ modkey, "Shift" }, "q", function(c)
|
||||
c:kill()
|
||||
end, { description = "close", group = "client" }),
|
||||
awful.key(
|
||||
{ modkey, "Control" },
|
||||
"space",
|
||||
awful.client.floating.toggle,
|
||||
{ description = "toggle floating", group = "client" }
|
||||
),
|
||||
awful.key({ modkey, "Control" }, "Return", function(c)
|
||||
c:swap(awful.client.getmaster())
|
||||
end, { description = "move to master", group = "client" }),
|
||||
awful.key({ modkey }, "o", function(c)
|
||||
c:move_to_screen()
|
||||
end, { description = "move to screen", group = "client" }),
|
||||
awful.key({ modkey }, "t", function(c)
|
||||
c.ontop = not c.ontop
|
||||
end, { description = "toggle keep on top", group = "client" }),
|
||||
-- awful.key({ modkey }, "n", function(c)
|
||||
-- -- The client currently has the input focus, so it cannot be
|
||||
-- -- minimized, since minimized clients can't have the focus.
|
||||
-- c.minimized = true
|
||||
-- end, { description = "minimize", group = "client" }),
|
||||
awful.key({ modkey }, "m", function(c)
|
||||
c.maximized = not c.maximized
|
||||
c:raise()
|
||||
end, { description = "(un)maximize", group = "client" }),
|
||||
awful.key({ modkey, "Control" }, "m", function(c)
|
||||
c.maximized_vertical = not c.maximized_vertical
|
||||
c:raise()
|
||||
end, { description = "(un)maximize vertically", group = "client" }),
|
||||
awful.key({ modkey, "Shift" }, "m", function(c)
|
||||
c.maximized_horizontal = not c.maximized_horizontal
|
||||
c:raise()
|
||||
end, { description = "(un)maximize horizontally", group = "client" })
|
||||
)
|
||||
|
||||
-- Bind all key numbers to tags.
|
||||
-- Be careful: we use keycodes to make it work on any keyboard layout.
|
||||
-- This should map on the top row of your keyboard, usually 1 to 9.
|
||||
for i = 1, 9 do
|
||||
globalkeys = gears.table.join(
|
||||
globalkeys,
|
||||
-- View tag only.
|
||||
awful.key({ modkey }, "#" .. i + 9, function()
|
||||
local screen = awful.screen.focused()
|
||||
local tag = screen.tags[i]
|
||||
if tag then
|
||||
tag:view_only()
|
||||
end
|
||||
end, { description = "view tag #" .. i, group = "tag" }),
|
||||
-- Toggle tag display.
|
||||
awful.key({ modkey, "Control" }, "#" .. i + 9, function()
|
||||
local screen = awful.screen.focused()
|
||||
local tag = screen.tags[i]
|
||||
if tag then
|
||||
awful.tag.viewtoggle(tag)
|
||||
end
|
||||
end, { description = "toggle tag #" .. i, group = "tag" }),
|
||||
-- Move client to tag.
|
||||
awful.key({ modkey, "Shift" }, "#" .. i + 9, function()
|
||||
if client.focus then
|
||||
local tag = client.focus.screen.tags[i]
|
||||
if tag then
|
||||
client.focus:move_to_tag(tag)
|
||||
end
|
||||
end
|
||||
end, { description = "move focused client to tag #" .. i, group = "tag" }),
|
||||
-- Toggle tag on focused client.
|
||||
awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9, function()
|
||||
if client.focus then
|
||||
local tag = client.focus.screen.tags[i]
|
||||
if tag then
|
||||
client.focus:toggle_tag(tag)
|
||||
end
|
||||
end
|
||||
end, { description = "toggle focused client on tag #" .. i, group = "tag" })
|
||||
)
|
||||
end
|
||||
|
||||
local clientbuttons = gears.table.join(
|
||||
awful.button({}, 1, function(c)
|
||||
c:emit_signal("request::activate", "mouse_click", { raise = true })
|
||||
end),
|
||||
awful.button({ modkey }, 1, function(c)
|
||||
c:emit_signal("request::activate", "mouse_click", { raise = true })
|
||||
awful.mouse.client.move(c)
|
||||
end),
|
||||
awful.button({ modkey }, 3, function(c)
|
||||
c:emit_signal("request::activate", "mouse_click", { raise = true })
|
||||
awful.mouse.client.resize(c)
|
||||
end)
|
||||
)
|
||||
|
||||
-- Set keys
|
||||
root.keys(globalkeys)
|
||||
-- }}}
|
||||
|
||||
-- {{{ Rules
|
||||
-- Rules to apply to new clients (through the "manage" signal).
|
||||
awful.rules.rules = {
|
||||
-- All clients will match this rule.
|
||||
{
|
||||
rule = {},
|
||||
properties = {
|
||||
border_width = beautiful.border_width,
|
||||
border_color = beautiful.border_normal,
|
||||
focus = awful.client.focus.filter,
|
||||
raise = true,
|
||||
keys = clientkeys,
|
||||
buttons = clientbuttons,
|
||||
screen = awful.screen.preferred,
|
||||
placement = awful.placement.no_overlap + awful.placement.no_offscreen,
|
||||
},
|
||||
},
|
||||
|
||||
-- Floating clients.
|
||||
{
|
||||
rule_any = {
|
||||
instance = {
|
||||
"DTA", -- Firefox addon DownThemAll.
|
||||
"copyq", -- Includes session name in class.
|
||||
"pinentry",
|
||||
},
|
||||
class = {
|
||||
"Arandr",
|
||||
"Blueman-manager",
|
||||
"Gpick",
|
||||
"Kruler",
|
||||
"MessageWin", -- kalarm.
|
||||
"Tor Browser", -- Needs a fixed window size to avoid fingerprinting by screen size.
|
||||
"Wpa_gui",
|
||||
"veromix",
|
||||
"xtightvncviewer",
|
||||
"Nsxiv",
|
||||
"Galculator",
|
||||
},
|
||||
-- Note that the name property shown in xprop might be set slightly after creation of the client
|
||||
-- and the name shown there might not match defined rules here.
|
||||
name = {
|
||||
"Event Tester", -- xev.
|
||||
},
|
||||
role = {
|
||||
"AlarmWindow", -- Thunderbird's calendar.
|
||||
"ConfigManager", -- Thunderbird's about:config.
|
||||
"pop-up", -- e.g. Google Chrome's (detached) Developer Tools.
|
||||
},
|
||||
},
|
||||
properties = { floating = true, placement = awful.placement.centered, beautiful.useless },
|
||||
},
|
||||
|
||||
-- Add titlebars to normal clients and dialogs
|
||||
{ rule_any = { type = { "normal", "dialog" } }, properties = { titlebars_enabled = false } },
|
||||
|
||||
{
|
||||
rule_any = {
|
||||
class = {
|
||||
-- "steam_app_1172470",
|
||||
-- "steam_app_1237970",
|
||||
-- "steam_app_289070",
|
||||
-- "steam_app_1172380",
|
||||
"steam_app_1774580",
|
||||
"steam_app_1182480",
|
||||
},
|
||||
},
|
||||
properties = { screen = 1, fullscreen = true, floating = true },
|
||||
},
|
||||
{
|
||||
rule_any = { class = { "Ferdium" } },
|
||||
properties = { screen = 2, tag = "5" },
|
||||
},
|
||||
{
|
||||
rule_any = { class = { "discord", "TelegramDesktop", "ripcord", "KotatogramDesktop" } },
|
||||
properties = { screen = 2, tag = "8" },
|
||||
},
|
||||
{
|
||||
rule_any = { class = { "easyeffects" } },
|
||||
properties = { screen = 1, tag = "9" },
|
||||
},
|
||||
{ rule_any = { class = { "kdeconnect.app" } }, properties = { screen = 2, tag = "7" } },
|
||||
{ rule_any = { class = { "Spotify" } }, properties = { screen = 2, tag = "9" } },
|
||||
{ rule_any = { class = { "mpv" } }, properties = { fullscreen = true } },
|
||||
}
|
||||
|
||||
-- {{{ Signals
|
||||
-- Signal function to execute when a new client appears.
|
||||
client.connect_signal("manage", function(c)
|
||||
-- Set the windows at the slave,
|
||||
-- i.e. put it at the end of others instead of setting it master.
|
||||
-- if not awesome.startup then awful.client.setslave(c) end
|
||||
|
||||
if awesome.startup and not c.size_hints.user_position and not c.size_hints.program_position then
|
||||
-- Prevent clients from being unreachable after screen count changes.
|
||||
awful.placement.no_offscreen(c)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Add a titlebar if titlebars_enabled is set to true in the rules.
|
||||
client.connect_signal("request::titlebars", function(c)
|
||||
-- buttons for the titlebar
|
||||
local buttons = gears.table.join(
|
||||
awful.button({}, 1, function()
|
||||
c:emit_signal("request::activate", "titlebar", { raise = true })
|
||||
awful.mouse.client.move(c)
|
||||
end),
|
||||
awful.button({}, 3, function()
|
||||
c:emit_signal("request::activate", "titlebar", { raise = true })
|
||||
awful.mouse.client.resize(c)
|
||||
end)
|
||||
)
|
||||
|
||||
awful.titlebar(c):setup({
|
||||
{
|
||||
-- Left
|
||||
awful.titlebar.widget.iconwidget(c),
|
||||
buttons = buttons,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
{
|
||||
-- Middle
|
||||
{
|
||||
-- Title
|
||||
align = "center",
|
||||
widget = awful.titlebar.widget.titlewidget(c),
|
||||
},
|
||||
buttons = buttons,
|
||||
layout = wibox.layout.flex.horizontal,
|
||||
},
|
||||
{
|
||||
-- Right
|
||||
awful.titlebar.widget.floatingbutton(c),
|
||||
awful.titlebar.widget.maximizedbutton(c),
|
||||
awful.titlebar.widget.stickybutton(c),
|
||||
awful.titlebar.widget.ontopbutton(c),
|
||||
awful.titlebar.widget.closebutton(c),
|
||||
layout = wibox.layout.fixed.horizontal(),
|
||||
},
|
||||
layout = wibox.layout.align.horizontal,
|
||||
})
|
||||
end)
|
||||
|
||||
-- Enable sloppy focus, so that focus follows mouse.
|
||||
client.connect_signal("mouse::enter", function(c)
|
||||
c:emit_signal("request::activate", "mouse_enter", { raise = false })
|
||||
end)
|
||||
|
||||
client.connect_signal("focus", function(c)
|
||||
c.border_color = beautiful.border_focus
|
||||
end)
|
||||
client.connect_signal("unfocus", function(c)
|
||||
c.border_color = beautiful.border_normal
|
||||
end)
|
||||
7
config/awesome/selene.toml
Normal file
7
config/awesome/selene.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
std = "awesome"
|
||||
|
||||
[rules]
|
||||
global_usage = "allow"
|
||||
multiple_statements = "allow"
|
||||
incorrect_standard_library_use = "allow"
|
||||
mixed_table = "allow"
|
||||
25
config/batrc
Normal file
25
config/batrc
Normal file
@@ -0,0 +1,25 @@
|
||||
# This is `bat`s configuration file. Each line either contains a comment or
|
||||
# a command-line option that you want to pass to `bat` by default. You can
|
||||
# run `bat --help` to get a list of all possible configuration options.
|
||||
|
||||
# Specify desired highlighting theme (e.g. "TwoDark"). Run `bat --list-themes`
|
||||
# for a list of all available themes
|
||||
--theme="base16-256"
|
||||
|
||||
# Enable this to use italic text on the terminal. This is not supported on all
|
||||
# terminal emulators (like tmux, by default):
|
||||
#--italic-text=always
|
||||
|
||||
# Uncomment the following line to disable automatic paging:
|
||||
#--paging=never
|
||||
|
||||
# Uncomment the following line if you are using less version >= 551 and want to
|
||||
# enable mouse scrolling support in `bat` when running inside tmux. This might
|
||||
# disable text selection, unless you press shift.
|
||||
#--pager="less --RAW-CONTROL-CHARS --quit-if-one-screen --mouse"
|
||||
|
||||
# Syntax mappings: map a certain filename pattern to a language.
|
||||
# Example 1: use the C++ syntax for Arduino .ino files
|
||||
# Example 2: Use ".gitignore"-style highlighting for ".ignore" files
|
||||
#--map-syntax "*.ino:C++"
|
||||
#--map-syntax ".ignore:Git Ignore"
|
||||
218
config/btop/btop.conf
Normal file
218
config/btop/btop.conf
Normal file
@@ -0,0 +1,218 @@
|
||||
#? Config file for btop v. 1.3.2
|
||||
|
||||
#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes.
|
||||
#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes"
|
||||
color_theme = "/home/kristofers/.config/btop/themes/rose-pine.theme"
|
||||
|
||||
#* If the theme set background should be shown, set to False if you want terminal background transparency.
|
||||
theme_background = False
|
||||
|
||||
#* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false.
|
||||
truecolor = True
|
||||
|
||||
#* Set to true to force tty mode regardless if a real tty has been detected or not.
|
||||
#* Will force 16-color mode and TTY theme, set all graph symbols to "tty" and swap out other non tty friendly symbols.
|
||||
force_tty = False
|
||||
|
||||
#* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets.
|
||||
#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box.
|
||||
#* Use whitespace " " as separator between different presets.
|
||||
#* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty"
|
||||
presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty"
|
||||
|
||||
#* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists.
|
||||
#* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift.
|
||||
vim_keys = True
|
||||
|
||||
#* Rounded corners on boxes, is ignored if TTY mode is ON.
|
||||
rounded_corners = True
|
||||
|
||||
#* Default symbols to use for graph creation, "braille", "block" or "tty".
|
||||
#* "braille" offers the highest resolution but might not be included in all fonts.
|
||||
#* "block" has half the resolution of braille but uses more common characters.
|
||||
#* "tty" uses only 3 different symbols but will work with most fonts and should work in a real TTY.
|
||||
#* Note that "tty" only has half the horizontal resolution of the other two, so will show a shorter historical view.
|
||||
graph_symbol = "braille"
|
||||
|
||||
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
|
||||
graph_symbol_cpu = "default"
|
||||
|
||||
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
|
||||
graph_symbol_mem = "default"
|
||||
|
||||
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
|
||||
graph_symbol_net = "default"
|
||||
|
||||
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
|
||||
graph_symbol_proc = "default"
|
||||
|
||||
#* Manually set which boxes to show. Available values are "cpu mem net proc" and "gpu0" through "gpu5", separate values with whitespace.
|
||||
shown_boxes = "mem net proc cpu"
|
||||
|
||||
#* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs.
|
||||
update_ms = 500
|
||||
|
||||
#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct",
|
||||
#* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly.
|
||||
proc_sorting = "cpu direct"
|
||||
|
||||
#* Reverse sorting order, True or False.
|
||||
proc_reversed = False
|
||||
|
||||
#* Show processes as a tree.
|
||||
proc_tree = False
|
||||
|
||||
#* Use the cpu graph colors in the process list.
|
||||
proc_colors = True
|
||||
|
||||
#* Use a darkening gradient in the process list.
|
||||
proc_gradient = True
|
||||
|
||||
#* If process cpu usage should be of the core it's running on or usage of the total available cpu power.
|
||||
proc_per_core = False
|
||||
|
||||
#* Show process memory as bytes instead of percent.
|
||||
proc_mem_bytes = True
|
||||
|
||||
#* Show cpu graph for each process.
|
||||
proc_cpu_graphs = True
|
||||
|
||||
#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate)
|
||||
proc_info_smaps = False
|
||||
|
||||
#* Show proc box on left side of screen instead of right.
|
||||
proc_left = False
|
||||
|
||||
#* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop).
|
||||
proc_filter_kernel = False
|
||||
|
||||
#* In tree-view, always accumulate child process resources in the parent process.
|
||||
proc_aggregate = False
|
||||
|
||||
#* Sets the CPU stat shown in upper half of the CPU graph, "total" is always available.
|
||||
#* Select from a list of detected attributes from the options menu.
|
||||
cpu_graph_upper = "total"
|
||||
|
||||
#* Sets the CPU stat shown in lower half of the CPU graph, "total" is always available.
|
||||
#* Select from a list of detected attributes from the options menu.
|
||||
cpu_graph_lower = "total"
|
||||
|
||||
#* Toggles if the lower CPU graph should be inverted.
|
||||
cpu_invert_lower = True
|
||||
|
||||
#* Set to True to completely disable the lower CPU graph.
|
||||
cpu_single_graph = False
|
||||
|
||||
#* Show cpu box at bottom of screen instead of top.
|
||||
cpu_bottom = False
|
||||
|
||||
#* Shows the system uptime in the CPU box.
|
||||
show_uptime = True
|
||||
|
||||
#* Show cpu temperature.
|
||||
check_temp = True
|
||||
|
||||
#* Which sensor to use for cpu temperature, use options menu to select from list of available sensors.
|
||||
cpu_sensor = "Auto"
|
||||
|
||||
#* Show temperatures for cpu cores also if check_temp is True and sensors has been found.
|
||||
show_coretemp = True
|
||||
|
||||
#* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core.
|
||||
#* Use lm-sensors or similar to see which cores are reporting temperatures on your machine.
|
||||
#* Format "x:y" x=core with wrong temp, y=core with correct temp, use space as separator between multiple entries.
|
||||
#* Example: "4:0 5:1 6:3"
|
||||
cpu_core_map = ""
|
||||
|
||||
#* Which temperature scale to use, available values: "celsius", "fahrenheit", "kelvin" and "rankine".
|
||||
temp_scale = "celsius"
|
||||
|
||||
#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024.
|
||||
base_10_sizes = False
|
||||
|
||||
#* Show CPU frequency.
|
||||
show_cpu_freq = True
|
||||
|
||||
#* Draw a clock at top of screen, formatting according to strftime, empty string to disable.
|
||||
#* Special formatting: /host = hostname | /user = username | /uptime = system uptime
|
||||
clock_format = "%X"
|
||||
|
||||
#* Update main ui in background when menus are showing, set this to false if the menus is flickering too much for comfort.
|
||||
background_update = True
|
||||
|
||||
#* Custom cpu model name, empty string to disable.
|
||||
custom_cpu_name = ""
|
||||
|
||||
#* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace " ".
|
||||
#* Begin line with "exclude=" to change to exclude filter, otherwise defaults to "most include" filter. Example: disks_filter="exclude=/boot /home/user".
|
||||
disks_filter = "exclude=/boot"
|
||||
|
||||
#* Show graphs instead of meters for memory values.
|
||||
mem_graphs = True
|
||||
|
||||
#* Show mem box below net box instead of above.
|
||||
mem_below_net = False
|
||||
|
||||
#* Count ZFS ARC in cached and available memory.
|
||||
zfs_arc_cached = True
|
||||
|
||||
#* If swap memory should be shown in memory box.
|
||||
show_swap = True
|
||||
|
||||
#* Show swap as a disk, ignores show_swap value above, inserts itself after first disk.
|
||||
swap_disk = False
|
||||
|
||||
#* If mem box should be split to also show disks info.
|
||||
show_disks = True
|
||||
|
||||
#* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar.
|
||||
only_physical = True
|
||||
|
||||
#* Read disks list from /etc/fstab. This also disables only_physical.
|
||||
use_fstab = False
|
||||
|
||||
#* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool)
|
||||
zfs_hide_datasets = False
|
||||
|
||||
#* Set to true to show available disk space for privileged users.
|
||||
disk_free_priv = False
|
||||
|
||||
#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view.
|
||||
show_io_stat = True
|
||||
|
||||
#* Toggles io mode for disks, showing big graphs for disk read/write speeds.
|
||||
io_mode = False
|
||||
|
||||
#* Set to True to show combined read/write io graphs in io mode.
|
||||
io_graph_combined = True
|
||||
|
||||
#* Set the top speed for the io graphs in MiB/s (100 by default), use format "mountpoint:speed" separate disks with whitespace " ".
|
||||
#* Example: "/mnt/media:100 /:20 /boot:1".
|
||||
io_graph_speeds = ""
|
||||
|
||||
#* Set fixed values for network graphs in Mebibits. Is only used if net_auto is also set to False.
|
||||
net_download = 100
|
||||
|
||||
net_upload = 100
|
||||
|
||||
#* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest.
|
||||
net_auto = True
|
||||
|
||||
#* Sync the auto scaling for download and upload to whichever currently has the highest scale.
|
||||
net_sync = False
|
||||
|
||||
#* Starts with the Network Interface specified here.
|
||||
net_iface = ""
|
||||
|
||||
#* Show battery stats in top right if battery is present.
|
||||
show_battery = True
|
||||
|
||||
#* Which battery to use if multiple are present. "Auto" for auto detection.
|
||||
selected_battery = "Auto"
|
||||
|
||||
#* Show power stats of battery next to charge indicator.
|
||||
show_battery_watts = True
|
||||
|
||||
#* Set loglevel for "~/.config/btop/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG".
|
||||
#* The level set includes all lower levels, i.e. "DEBUG" will show all logging info.
|
||||
log_level = "WARNING"
|
||||
89
config/btop/themes/rose-pine-dawn.theme
Normal file
89
config/btop/themes/rose-pine-dawn.theme
Normal file
@@ -0,0 +1,89 @@
|
||||
# Main background, empty for terminal default, need to be empty if you want transparent background
|
||||
theme[main_bg]="#faf4ed"
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#575279"
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#797593"
|
||||
|
||||
# Highlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#575279"
|
||||
|
||||
# Background color of selected item in processes box
|
||||
theme[selected_bg]="#cecacd"
|
||||
|
||||
# Foreground color of selected item in processes box
|
||||
theme[selected_fg]="#ea9d34"
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#dfdad9"
|
||||
|
||||
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
|
||||
theme[graph_text]="#56949f"
|
||||
|
||||
# Background color of the percentage meters
|
||||
theme[meter_bg]="#56949f"
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#907aa9"
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#d7827e"
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#286983"
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#907aa9"
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#b4637a"
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#9893a5"
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#d7827e"
|
||||
theme[temp_mid]="#ea9d34"
|
||||
theme[temp_end]="#b4637a"
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#ea9d34"
|
||||
theme[cpu_mid]="#d7827e"
|
||||
theme[cpu_end]="#b4637a"
|
||||
|
||||
# Mem/Disk free meter
|
||||
theme[free_start]="#b4637a"
|
||||
theme[free_mid]="#b4637a"
|
||||
theme[free_end]="#b4637a"
|
||||
|
||||
# Mem/Disk cached meter
|
||||
theme[cached_start]="#907aa9"
|
||||
theme[cached_mid]="#907aa9"
|
||||
theme[cached_end]="#907aa9"
|
||||
|
||||
# Mem/Disk available meter
|
||||
theme[available_start]="#286983"
|
||||
theme[available_mid]="#286983"
|
||||
theme[available_end]="#286983"
|
||||
|
||||
# Mem/Disk used meter
|
||||
theme[used_start]="#d7827e"
|
||||
theme[used_mid]="#d7827e"
|
||||
theme[used_end]="#d7827e"
|
||||
|
||||
# Download graph colors
|
||||
theme[download_start]="#286983"
|
||||
theme[download_mid]="#56949f"
|
||||
theme[download_end]="#56949f"
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#d7827e"
|
||||
theme[upload_mid]="#b4637a"
|
||||
theme[upload_end]="#b4637a"
|
||||
|
||||
# Process box color gradient for threads, mem and cpu usage
|
||||
theme[process_start]="#286983"
|
||||
theme[process_mid]="#56949f"
|
||||
theme[process_end]="#56949f"
|
||||
89
config/btop/themes/rose-pine-moon.theme
Normal file
89
config/btop/themes/rose-pine-moon.theme
Normal file
@@ -0,0 +1,89 @@
|
||||
# Main background, empty for terminal default, need to be empty if you want transparent background
|
||||
theme[main_bg]="#232136"
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#e0def4"
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#908caa"
|
||||
|
||||
# Highlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#e0def4"
|
||||
|
||||
# Background color of selected item in processes box
|
||||
theme[selected_bg]="#56526e"
|
||||
|
||||
# Foreground color of selected item in processes box
|
||||
theme[selected_fg]="#f6c177"
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#44415a"
|
||||
|
||||
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
|
||||
theme[graph_text]="#9ccfd8"
|
||||
|
||||
# Background color of the percentage meters
|
||||
theme[meter_bg]="#9ccfd8"
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#c4a7e7"
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#ea9a97"
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#3e8fb0"
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#c4a7e7"
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#eb6f92"
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#6e6a86"
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#ea9a97"
|
||||
theme[temp_mid]="#f6c177"
|
||||
theme[temp_end]="#eb6f92"
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#f6c177"
|
||||
theme[cpu_mid]="#ea9a97"
|
||||
theme[cpu_end]="#eb6f92"
|
||||
|
||||
# Mem/Disk free meter
|
||||
theme[free_start]="#eb6f92"
|
||||
theme[free_mid]="#eb6f92"
|
||||
theme[free_end]="#eb6f92"
|
||||
|
||||
# Mem/Disk cached meter
|
||||
theme[cached_start]="#c4a7e7"
|
||||
theme[cached_mid]="#c4a7e7"
|
||||
theme[cached_end]="#c4a7e7"
|
||||
|
||||
# Mem/Disk available meter
|
||||
theme[available_start]="#3e8fb0"
|
||||
theme[available_mid]="#3e8fb0"
|
||||
theme[available_end]="#3e8fb0"
|
||||
|
||||
# Mem/Disk used meter
|
||||
theme[used_start]="#ea9a97"
|
||||
theme[used_mid]="#ea9a97"
|
||||
theme[used_end]="#ea9a97"
|
||||
|
||||
# Download graph colors
|
||||
theme[download_start]="#3e8fb0"
|
||||
theme[download_mid]="#9ccfd8"
|
||||
theme[download_end]="#9ccfd8"
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#ea9a97"
|
||||
theme[upload_mid]="#eb6f92"
|
||||
theme[upload_end]="#eb6f92"
|
||||
|
||||
# Process box color gradient for threads, mem and cpu usage
|
||||
theme[process_start]="#3e8fb0"
|
||||
theme[process_mid]="#9ccfd8"
|
||||
theme[process_end]="#9ccfd8"
|
||||
119
config/btop/themes/rose-pine.theme
Normal file
119
config/btop/themes/rose-pine.theme
Normal file
@@ -0,0 +1,119 @@
|
||||
# Main background, empty for terminal default, need to be empty if you want transparent background
|
||||
theme[main_bg]="#191724"
|
||||
# Base
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#e0def4"
|
||||
# Text
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#908caa"
|
||||
# Subtle
|
||||
|
||||
# Highlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#e0def4"
|
||||
# Text
|
||||
|
||||
# Background color of selected item in processes box
|
||||
theme[selected_bg]="#524f67"
|
||||
# HL High
|
||||
|
||||
# Foreground color of selected item in processes box
|
||||
theme[selected_fg]="#f6c177"
|
||||
# Gold
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#403d52"
|
||||
# HL Med
|
||||
|
||||
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
|
||||
theme[graph_text]="#9ccfd8"
|
||||
# Foam
|
||||
|
||||
# Background color of the percentage meters
|
||||
theme[meter_bg]="#9ccfd8"
|
||||
# Foam
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#c4a7e7"
|
||||
# Iris
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#ebbcba"
|
||||
# Rose
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#31748f"
|
||||
# Pine
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#c4a7e7"
|
||||
# Iris
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#eb6f92"
|
||||
# Love
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#6e6a86"
|
||||
# Muted
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#ebbcba"
|
||||
# Rose
|
||||
theme[temp_mid]="#f6c177"
|
||||
# Gold
|
||||
theme[temp_end]="#eb6f92"
|
||||
# Love
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#f6c177"
|
||||
# Gold
|
||||
theme[cpu_mid]="#ebbcba"
|
||||
# Rose
|
||||
theme[cpu_end]="#eb6f92"
|
||||
# Love
|
||||
|
||||
# Mem/Disk free meter
|
||||
# all love
|
||||
theme[free_start]="#eb6f92"
|
||||
theme[free_mid]="#eb6f92"
|
||||
theme[free_end]="#eb6f92"
|
||||
|
||||
# Mem/Disk cached meter
|
||||
# all iris
|
||||
theme[cached_start]="#c4a7e7"
|
||||
theme[cached_mid]="#c4a7e7"
|
||||
theme[cached_end]="#c4a7e7"
|
||||
|
||||
# Mem/Disk available meter
|
||||
# all pine
|
||||
theme[available_start]="#31748f"
|
||||
theme[available_mid]="#31748f"
|
||||
theme[available_end]="#31748f"
|
||||
|
||||
# Mem/Disk used meter
|
||||
# all rose
|
||||
theme[used_start]="#ebbcba"
|
||||
theme[used_mid]="#ebbcba"
|
||||
theme[used_end]="#ebbcba"
|
||||
|
||||
# Download graph colors
|
||||
# Pine for start, foam for the rest
|
||||
theme[download_start]="#31748f"
|
||||
theme[download_mid]="#9ccfd8"
|
||||
theme[download_end]="#9ccfd8"
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#ebbcba"
|
||||
# Rose for start
|
||||
theme[upload_mid]="#eb6f92"
|
||||
# Love for mid and end
|
||||
theme[upload_end]="#eb6f92"
|
||||
|
||||
# Process box color gradient for threads, mem and cpu usage
|
||||
theme[process_start]="#31748f"
|
||||
# Pine
|
||||
theme[process_mid]="#9ccfd8"
|
||||
# Foam for mid and end
|
||||
theme[process_end]="#9ccfd8"
|
||||
473
config/dunst/dunstrc
Normal file
473
config/dunst/dunstrc
Normal file
@@ -0,0 +1,473 @@
|
||||
# See dunst(5) for all configuration options
|
||||
|
||||
[global]
|
||||
### Display ###
|
||||
|
||||
# Which monitor should the notifications be displayed on.
|
||||
monitor = 0
|
||||
|
||||
# Display notification on focused monitor. Possible modes are:
|
||||
# mouse: follow mouse pointer
|
||||
# keyboard: follow window with keyboard focus
|
||||
# none: don't follow anything
|
||||
#
|
||||
# "keyboard" needs a window manager that exports the
|
||||
# _NET_ACTIVE_WINDOW property.
|
||||
# This should be the case for almost all modern window managers.
|
||||
#
|
||||
# If this option is set to mouse or keyboard, the monitor option
|
||||
# will be ignored.
|
||||
follow = none
|
||||
|
||||
### Geometry ###
|
||||
|
||||
# dynamic width from 0 to 300
|
||||
width = (0, 300)
|
||||
# constant width of 300
|
||||
# width = 300
|
||||
|
||||
# The maximum height of a single notification, excluding the frame.
|
||||
height = 300
|
||||
|
||||
# Position the notification in the top right corner
|
||||
origin = top-right
|
||||
|
||||
# Offset from the origin
|
||||
offset = 5x25
|
||||
|
||||
# Scale factor. It is auto-detected if value is 0.
|
||||
scale = 0
|
||||
|
||||
# Maximum number of notification (0 means no limit)
|
||||
notification_limit = 0
|
||||
|
||||
### Progress bar ###
|
||||
|
||||
# Turn on the progess bar. It appears when a progress hint is passed with
|
||||
# for example dunstify -h int:value:12
|
||||
progress_bar = true
|
||||
|
||||
# Set the progress bar height. This includes the frame, so make sure
|
||||
# it's at least twice as big as the frame width.
|
||||
progress_bar_height = 10
|
||||
|
||||
# Set the frame width of the progress bar
|
||||
progress_bar_frame_width = 1
|
||||
|
||||
# Set the minimum width for the progress bar
|
||||
progress_bar_min_width = 150
|
||||
|
||||
# Set the maximum width for the progress bar
|
||||
progress_bar_max_width = 300
|
||||
|
||||
# Corner radius for the progress bar. 0 disables rounded corners.
|
||||
progress_bar_corner_radius = 0
|
||||
|
||||
# Corner radius for the icon image.
|
||||
icon_corner_radius = 0
|
||||
|
||||
# Show how many messages are currently hidden (because of
|
||||
# notification_limit).
|
||||
indicate_hidden = yes
|
||||
|
||||
# The transparency of the window. Range: [0; 100].
|
||||
# This option will only work if a compositing window manager is
|
||||
# present (e.g. xcompmgr, compiz, etc.). (X11 only)
|
||||
transparency = 25
|
||||
|
||||
# Draw a line of "separator_height" pixel height between two
|
||||
# notifications.
|
||||
# Set to 0 to disable.
|
||||
# If gap_size is greater than 0, this setting will be ignored.
|
||||
separator_height = 1
|
||||
|
||||
# Padding between text and separator.
|
||||
padding = 10
|
||||
|
||||
# Horizontal padding.
|
||||
horizontal_padding = 10
|
||||
|
||||
# Padding between text and icon.
|
||||
text_icon_padding = 0
|
||||
|
||||
# Defines width in pixels of frame around the notification window.
|
||||
# Set to 0 to disable.
|
||||
frame_width = 1
|
||||
|
||||
# Defines color of the frame around the notification window.
|
||||
frame_color = "#15161e"
|
||||
|
||||
# Size of gap to display between notifications - requires a compositor.
|
||||
# If value is greater than 0, separator_height will be ignored and a border
|
||||
# of size frame_width will be drawn around each notification instead.
|
||||
# Click events on gaps do not currently propagate to applications below.
|
||||
gap_size = 3
|
||||
|
||||
# Define a color for the separator.
|
||||
# possible values are:
|
||||
# * auto: dunst tries to find a color fitting to the background;
|
||||
# * foreground: use the same color as the foreground;
|
||||
# * frame: use the same color as the frame;
|
||||
# * anything else will be interpreted as a X color.
|
||||
separator_color = frame
|
||||
|
||||
# Sort messages by urgency.
|
||||
sort = yes
|
||||
|
||||
# Don't remove messages, if the user is idle (no mouse or keyboard input)
|
||||
# for longer than idle_threshold seconds.
|
||||
# Set to 0 to disable.
|
||||
# A client can set the 'transient' hint to bypass this. See the rules
|
||||
# section for how to disable this if necessary
|
||||
idle_threshold = 120
|
||||
|
||||
### Text ###
|
||||
|
||||
font = JetBrainsMono NF 8
|
||||
|
||||
icon_theme = "rose-pine-icons"
|
||||
enable_recursive_icon_lookup = true
|
||||
corner_radius = 2
|
||||
|
||||
background = "#26233a"
|
||||
foreground = "#e0def4"
|
||||
|
||||
# The spacing between lines. If the height is smaller than the
|
||||
# font height, it will get raised to the font height.
|
||||
line_height = 0
|
||||
|
||||
# Possible values are:
|
||||
# full: Allow a small subset of html markup in notifications:
|
||||
# <b>bold</b>
|
||||
# <i>italic</i>
|
||||
# <s>strikethrough</s>
|
||||
# <u>underline</u>
|
||||
#
|
||||
# For a complete reference see
|
||||
# <https://docs.gtk.org/Pango/pango_markup.html>.
|
||||
#
|
||||
# strip: This setting is provided for compatibility with some broken
|
||||
# clients that send markup even though it's not enabled on the
|
||||
# server. Dunst will try to strip the markup but the parsing is
|
||||
# simplistic so using this option outside of matching rules for
|
||||
# specific applications *IS GREATLY DISCOURAGED*.
|
||||
#
|
||||
# no: Disable markup parsing, incoming notifications will be treated as
|
||||
# plain text. Dunst will not advertise that it has the body-markup
|
||||
# capability if this is set as a global setting.
|
||||
#
|
||||
# It's important to note that markup inside the format option will be parsed
|
||||
# regardless of what this is set to.
|
||||
markup = full
|
||||
|
||||
# The format of the message. Possible variables are:
|
||||
# %a appname
|
||||
# %s summary
|
||||
# %b body
|
||||
# %i iconname (including its path)
|
||||
# %I iconname (without its path)
|
||||
# %p progress value if set ([ 0%] to [100%]) or nothing
|
||||
# %n progress value if set without any extra characters
|
||||
# %% Literal %
|
||||
# Markup is allowed
|
||||
format = "<b>%s</b>%p\n%b"
|
||||
|
||||
# Alignment of message text.
|
||||
# Possible values are "left", "center" and "right".
|
||||
alignment = left
|
||||
|
||||
# Vertical alignment of message text and icon.
|
||||
# Possible values are "top", "center" and "bottom".
|
||||
vertical_alignment = center
|
||||
|
||||
# Show age of message if message is older than show_age_threshold
|
||||
# seconds.
|
||||
# Set to -1 to disable.
|
||||
show_age_threshold = 60
|
||||
|
||||
# Specify where to make an ellipsis in long lines.
|
||||
# Possible values are "start", "middle" and "end".
|
||||
ellipsize = middle
|
||||
|
||||
# Ignore newlines '\n' in notifications.
|
||||
ignore_newline = no
|
||||
|
||||
# Stack together notifications with the same content
|
||||
stack_duplicates = true
|
||||
|
||||
# Hide the count of stacked notifications with the same content
|
||||
hide_duplicate_count = false
|
||||
|
||||
# Display indicators for URLs (U) and actions (A).
|
||||
show_indicators = yes
|
||||
|
||||
### Icons ###
|
||||
|
||||
# Recursive icon lookup. You can set a single theme, instead of having to
|
||||
# define all lookup paths.
|
||||
enable_recursive_icon_lookup = true
|
||||
|
||||
# Set icon theme (only used for recursive icon lookup)
|
||||
icon_theme = Papirus
|
||||
# You can also set multiple icon themes, with the leftmost one being used first.
|
||||
# icon_theme = "Adwaita, breeze"
|
||||
|
||||
# Align icons left/right/top/off
|
||||
icon_position = left
|
||||
|
||||
# Scale small icons up to this size, set to 0 to disable. Helpful
|
||||
# for e.g. small files or high-dpi screens. In case of conflict,
|
||||
# max_icon_size takes precedence over this.
|
||||
min_icon_size = 32
|
||||
|
||||
# Scale larger icons down to this size, set to 0 to disable
|
||||
max_icon_size = 128
|
||||
|
||||
# Paths to default icons (only necessary when not using recursive icon lookup)
|
||||
icon_path = /usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/
|
||||
|
||||
### History ###
|
||||
|
||||
# Should a notification popped up from history be sticky or timeout
|
||||
# as if it would normally do.
|
||||
sticky_history = yes
|
||||
|
||||
# Maximum amount of notifications kept in history
|
||||
history_length = 20
|
||||
|
||||
### Misc/Advanced ###
|
||||
|
||||
# dmenu path.
|
||||
dmenu = /usr/bin/dmenu -p dunst:
|
||||
|
||||
# Browser for opening urls in context menu.
|
||||
browser = /usr/bin/xdg-open
|
||||
|
||||
# Always run rule-defined scripts, even if the notification is suppressed
|
||||
always_run_script = true
|
||||
|
||||
# Define the title of the windows spawned by dunst
|
||||
title = Dunst
|
||||
|
||||
# Define the class of the windows spawned by dunst
|
||||
class = Dunst
|
||||
|
||||
# Define the corner radius of the notification window
|
||||
# in pixel size. If the radius is 0, you have no rounded
|
||||
# corners.
|
||||
# The radius will be automatically lowered if it exceeds half of the
|
||||
# notification height to avoid clipping text and/or icons.
|
||||
corner_radius = 8
|
||||
|
||||
# Ignore the dbus closeNotification message.
|
||||
# Useful to enforce the timeout set by dunst configuration. Without this
|
||||
# parameter, an application may close the notification sent before the
|
||||
# user defined timeout.
|
||||
ignore_dbusclose = false
|
||||
|
||||
### Wayland ###
|
||||
# These settings are Wayland-specific. They have no effect when using X11
|
||||
|
||||
# Uncomment this if you want to let notications appear under fullscreen
|
||||
# applications (default: overlay)
|
||||
# layer = top
|
||||
|
||||
# Set this to true to use X11 output on Wayland.
|
||||
force_xwayland = false
|
||||
|
||||
### Legacy
|
||||
|
||||
# Use the Xinerama extension instead of RandR for multi-monitor support.
|
||||
# This setting is provided for compatibility with older nVidia drivers that
|
||||
# do not support RandR and using it on systems that support RandR is highly
|
||||
# discouraged.
|
||||
#
|
||||
# By enabling this setting dunst will not be able to detect when a monitor
|
||||
# is connected or disconnected which might break follow mode if the screen
|
||||
# layout changes.
|
||||
force_xinerama = false
|
||||
|
||||
### mouse
|
||||
|
||||
# Defines list of actions for each mouse event
|
||||
# Possible values are:
|
||||
# * none: Don't do anything.
|
||||
# * do_action: Invoke the action determined by the action_name rule. If there is no
|
||||
# such action, open the context menu.
|
||||
# * open_url: If the notification has exactly one url, open it. If there are multiple
|
||||
# ones, open the context menu.
|
||||
# * close_current: Close current notification.
|
||||
# * close_all: Close all notifications.
|
||||
# * context: Open context menu for the notification.
|
||||
# * context_all: Open context menu for all notifications.
|
||||
# These values can be strung together for each mouse event, and
|
||||
# will be executed in sequence.
|
||||
mouse_left_click = close_current
|
||||
mouse_middle_click = do_action, close_current
|
||||
mouse_right_click = close_all
|
||||
|
||||
# Experimental features that may or may not work correctly. Do not expect them
|
||||
# to have a consistent behaviour across releases.
|
||||
[experimental]
|
||||
# Calculate the dpi to use on a per-monitor basis.
|
||||
# If this setting is enabled the Xft.dpi value will be ignored and instead
|
||||
# dunst will attempt to calculate an appropriate dpi value for each monitor
|
||||
# using the resolution and physical size. This might be useful in setups
|
||||
# where there are multiple screens with very different dpi values.
|
||||
per_monitor_dpi = false
|
||||
|
||||
[urgency_low]
|
||||
# IMPORTANT: colors have to be defined in quotation marks.
|
||||
# Otherwise the "#" and following would be interpreted as a comment.
|
||||
background = "#26273d"
|
||||
highlight = "#31748f"
|
||||
frame_color = "#31748f"
|
||||
timeout = 5
|
||||
default_icon = "dialog-information"
|
||||
format = "<b><span foreground='#31748f'>%s</span></b>\n%b"
|
||||
# Icon for notifications with low urgency, uncomment to enable
|
||||
#new_icon = /path/to/icon
|
||||
|
||||
[urgency_normal]
|
||||
background = "#362e3c"
|
||||
highlight = "#f6c177"
|
||||
frame_color = "#f6c177"
|
||||
timeout = 10
|
||||
default_icon = "dialog-warning"
|
||||
format = "<b><span foreground='#f6c177'>%s</span></b>\n%b"
|
||||
# Icon for notifications with normal urgency, uncomment to enable
|
||||
#new_icon = /path/to/icon
|
||||
|
||||
[urgency_critical]
|
||||
background = "#35263d"
|
||||
highlight = "#eb6f92"
|
||||
frame_color = "#eb6f92"
|
||||
timeout = 0
|
||||
default_icon = "dialog-error"
|
||||
format = "<b><span foreground='#eb6f92'>%s</span></b>\n%b"
|
||||
# Icon for notifications with critical urgency, uncomment to enable
|
||||
#new_icon = /path/to/icon
|
||||
|
||||
# Every section that isn't one of the above is interpreted as a rules to
|
||||
# override settings for certain messages.
|
||||
#
|
||||
# Messages can be matched by
|
||||
# appname (discouraged, see desktop_entry)
|
||||
# body
|
||||
# category
|
||||
# desktop_entry
|
||||
# icon
|
||||
# match_transient
|
||||
# msg_urgency
|
||||
# stack_tag
|
||||
# summary
|
||||
#
|
||||
# and you can override the
|
||||
# background
|
||||
# foreground
|
||||
# format
|
||||
# frame_color
|
||||
# fullscreen
|
||||
# new_icon
|
||||
# set_stack_tag
|
||||
# set_transient
|
||||
# set_category
|
||||
# timeout
|
||||
# urgency
|
||||
# icon_position
|
||||
# skip_display
|
||||
# history_ignore
|
||||
# action_name
|
||||
# word_wrap
|
||||
# ellipsize
|
||||
# alignment
|
||||
# hide_text
|
||||
#
|
||||
# Shell-like globbing will get expanded.
|
||||
#
|
||||
# Instead of the appname filter, it's recommended to use the desktop_entry filter.
|
||||
# GLib based applications export their desktop-entry name. In comparison to the appname,
|
||||
# the desktop-entry won't get localized.
|
||||
#
|
||||
# SCRIPTING
|
||||
# You can specify a script that gets run when the rule matches by
|
||||
# setting the "script" option.
|
||||
# The script will be called as follows:
|
||||
# script appname summary body icon urgency
|
||||
# where urgency can be "LOW", "NORMAL" or "CRITICAL".
|
||||
#
|
||||
# NOTE: It might be helpful to run dunst -print in a terminal in order
|
||||
# to find fitting options for rules.
|
||||
|
||||
# Disable the transient hint so that idle_threshold cannot be bypassed from the
|
||||
# client
|
||||
#[transient_disable]
|
||||
# match_transient = yes
|
||||
# set_transient = no
|
||||
#
|
||||
# Make the handling of transient notifications more strict by making them not
|
||||
# be placed in history.
|
||||
#[transient_history_ignore]
|
||||
# match_transient = yes
|
||||
# history_ignore = yes
|
||||
|
||||
# fullscreen values
|
||||
# show: show the notifications, regardless if there is a fullscreen window opened
|
||||
# delay: displays the new notification, if there is no fullscreen window active
|
||||
# If the notification is already drawn, it won't get undrawn.
|
||||
# pushback: same as delay, but when switching into fullscreen, the notification will get
|
||||
# withdrawn from screen again and will get delayed like a new notification
|
||||
#[fullscreen_delay_everything]
|
||||
# fullscreen = delay
|
||||
#[fullscreen_show_critical]
|
||||
# msg_urgency = critical
|
||||
# fullscreen = show
|
||||
|
||||
#[espeak]
|
||||
# summary = "*"
|
||||
# script = dunst_espeak.sh
|
||||
|
||||
#[script-test]
|
||||
# summary = "*script*"
|
||||
# script = dunst_test.sh
|
||||
|
||||
#[ignore]
|
||||
# # This notification will not be displayed
|
||||
# summary = "foobar"
|
||||
# skip_display = true
|
||||
|
||||
#[history-ignore]
|
||||
# # This notification will not be saved in history
|
||||
# summary = "foobar"
|
||||
# history_ignore = yes
|
||||
|
||||
#[skip-display]
|
||||
# # This notification will not be displayed, but will be included in the history
|
||||
# summary = "foobar"
|
||||
# skip_display = yes
|
||||
|
||||
#[signed_on]
|
||||
# appname = Pidgin
|
||||
# summary = "*signed on*"
|
||||
# urgency = low
|
||||
#
|
||||
#[signed_off]
|
||||
# appname = Pidgin
|
||||
# summary = *signed off*
|
||||
# urgency = low
|
||||
#
|
||||
#[says]
|
||||
# appname = Pidgin
|
||||
# summary = *says*
|
||||
# urgency = critical
|
||||
#
|
||||
#[twitter]
|
||||
# appname = Pidgin
|
||||
# summary = *twitter.com*
|
||||
# urgency = normal
|
||||
#
|
||||
#[stack-volumes]
|
||||
# appname = "some_volume_notifiers"
|
||||
# set_stack_tag = "volume"
|
||||
#
|
||||
# vim: ft=cfg
|
||||
42
config/dunst/dunstrc.d/50-theme.conf
Normal file
42
config/dunst/dunstrc.d/50-theme.conf
Normal file
@@ -0,0 +1,42 @@
|
||||
[global]
|
||||
width = 400
|
||||
offset = 5x5
|
||||
|
||||
progress_bar_min_width = 380
|
||||
progress_bar_max_width = 380
|
||||
progress_bar_corner_radius = 2
|
||||
|
||||
padding = 10
|
||||
horizontal_padding = 10
|
||||
frame_width = 1
|
||||
gap_size = 3
|
||||
font = "Monospace 14"
|
||||
|
||||
icon_theme = "rose-pine-icons"
|
||||
enable_recursive_icon_lookup = true
|
||||
corner_radius = 2
|
||||
|
||||
background = "#26233a"
|
||||
foreground = "#e0def4"
|
||||
|
||||
[urgency_low]
|
||||
background = "#26273d"
|
||||
highlight = "#31748f"
|
||||
frame_color = "#31748f"
|
||||
default_icon = "dialog-information"
|
||||
format = "<b><span foreground='#31748f'>%s</span></b>\n%b"
|
||||
|
||||
[urgency_normal]
|
||||
background = "#362e3c"
|
||||
highlight = "#f6c177"
|
||||
frame_color = "#f6c177"
|
||||
default_icon = "dialog-warning"
|
||||
format = "<b><span foreground='#f6c177'>%s</span></b>\n%b"
|
||||
|
||||
[urgency_critical]
|
||||
background = "#35263d"
|
||||
highlight = "#eb6f92"
|
||||
frame_color = "#eb6f92"
|
||||
default_icon = "dialog-error"
|
||||
format = "<b><span foreground='#eb6f92'>%s</span></b>\n%b"
|
||||
|
||||
170
config/eww/eww.scss
Normal file
170
config/eww/eww.scss
Normal file
@@ -0,0 +1,170 @@
|
||||
$bg: #1a1b26;
|
||||
$bg_dark: #16161e;
|
||||
$bg_float: #16161e;
|
||||
$bg_highlight: #292e42;
|
||||
$bg_popup: #16161e;
|
||||
$bg_search: #3d59a1;
|
||||
$bg_sidebar: #16161e;
|
||||
$bg_statusline: #16161e;
|
||||
$bg_visual: #283457;
|
||||
$black: #15161e;
|
||||
$blue: #7aa2f7;
|
||||
$blue0: #3d59a1;
|
||||
$blue1: #2ac3de;
|
||||
$blue2: #0db9d7;
|
||||
$blue5: #89ddff;
|
||||
$blue6: #b4f9f8;
|
||||
$blue7: #394b70;
|
||||
$border: #15161e;
|
||||
$border_highlight: #27a1b9;
|
||||
$comment: #565f89;
|
||||
$cyan: #7dcfff;
|
||||
$dark3: #545c7e;
|
||||
$dark5: #737aa2;
|
||||
$delta_add: #2c5a66;
|
||||
$delta_delete: #713137;
|
||||
$diff_add: #20303b;
|
||||
$diff_change: #1f2231;
|
||||
$diff_delete: #37222c;
|
||||
$diff_text: #394b70;
|
||||
$error: #db4b4b;
|
||||
$fg: #c0caf5;
|
||||
$fg_dark: #a9b1d6;
|
||||
$fg_float: #c0caf5;
|
||||
$fg_gutter: #3b4261;
|
||||
$fg_sidebar: #a9b1d6;
|
||||
$git_add: #449dab;
|
||||
$git_change: #6183bb;
|
||||
$git_delete: #914c54;
|
||||
$git_ignore: #545c7e;
|
||||
$gitSigns_add: #266d6a;
|
||||
$gitSigns_change: #536c9e;
|
||||
$gitSigns_delete: #b2555b;
|
||||
$green: #9ece6a;
|
||||
$green1: #73daca;
|
||||
$green2: #41a6b5;
|
||||
$hint: #1abc9c;
|
||||
$info: #0db9d7;
|
||||
$magenta: #bb9af7;
|
||||
$magenta2: #ff007c;
|
||||
$orange: #ff9e64;
|
||||
$purple: #9d7cd8;
|
||||
$red: #f7768e;
|
||||
$red1: #db4b4b;
|
||||
$teal: #1abc9c;
|
||||
$terminal_black: #414868;
|
||||
$warning: #e0af68;
|
||||
$yellow: #e0af68;
|
||||
|
||||
* {
|
||||
all: unset; //Unsets everything so you can style everything from scratch
|
||||
}
|
||||
|
||||
//Global Styles
|
||||
.bar,
|
||||
.bar-1 {
|
||||
background-color: rgba(22, 22, 30, 0.7);
|
||||
color: $fg;
|
||||
font-family: "JetBrainsMono NF";
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
// Styles on classes (see eww.yuck for more information)
|
||||
|
||||
.sidestuff slider {
|
||||
all: unset;
|
||||
}
|
||||
|
||||
.metric scale trough highlight {
|
||||
all: unset;
|
||||
background-color: $error;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.metric scale trough {
|
||||
all: unset;
|
||||
background-color: $bg_visual;
|
||||
border-radius: 50px;
|
||||
min-height: 3px;
|
||||
min-width: 50px;
|
||||
margin-left: 1px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.metric scale trough highlight {
|
||||
all: unset;
|
||||
// background-color: $fg_sidebar;
|
||||
background-color: $teal;
|
||||
color: $bg;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.metric scale trough {
|
||||
all: unset;
|
||||
background-color: $bg_visual;
|
||||
border-radius: 50px;
|
||||
min-height: 3px;
|
||||
min-width: 50px;
|
||||
margin-left: 1px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.label-ram {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.music {
|
||||
&.playing {
|
||||
color: $teal;
|
||||
}
|
||||
|
||||
&.paused {
|
||||
color: $terminal_black;
|
||||
}
|
||||
}
|
||||
|
||||
.workspaces {
|
||||
.current {
|
||||
color: $hint;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-module {
|
||||
& > &__icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.cpu {
|
||||
&.warning {
|
||||
color: $warning;
|
||||
}
|
||||
|
||||
&.danger {
|
||||
color: $red;
|
||||
}
|
||||
}
|
||||
|
||||
.battery {
|
||||
&.warning {
|
||||
color: $warning;
|
||||
}
|
||||
|
||||
&.critical {
|
||||
color: $red;
|
||||
}
|
||||
|
||||
&.Charging {
|
||||
color: $teal;
|
||||
}
|
||||
}
|
||||
|
||||
.network {
|
||||
&.disconnected {
|
||||
color: $error;
|
||||
}
|
||||
}
|
||||
|
||||
.workspaces button:hover {
|
||||
background: $bg_highlight;
|
||||
}
|
||||
198
config/eww/eww.yuck
Normal file
198
config/eww/eww.yuck
Normal file
@@ -0,0 +1,198 @@
|
||||
(defwidget bar []
|
||||
(centerbox :orientation "h"
|
||||
(workspaces)
|
||||
(window)
|
||||
(sidestuff)))
|
||||
|
||||
(defwidget sidestuff []
|
||||
(box
|
||||
:class "sidestuff"
|
||||
:orientation "h"
|
||||
:space-evenly false
|
||||
:halign "end"
|
||||
:spacing 10
|
||||
(music)
|
||||
(metric
|
||||
:label ""
|
||||
:value volume
|
||||
:onchange "pulsemixer --set-volume {}" )
|
||||
;; (metric_extended
|
||||
;; :label ""
|
||||
;; :value brightness
|
||||
;; :onchange "doas brightnessctl set {}" )
|
||||
(cpu)
|
||||
(github)
|
||||
;; (network)
|
||||
(battery)
|
||||
time
|
||||
date
|
||||
))
|
||||
|
||||
|
||||
(deflisten workspaces :initial "[]" "bash ~/.config/eww/scripts/get-workspaces")
|
||||
(deflisten current_workspace :initial "1" "bash ~/.config/eww/scripts/get-active-workspace")
|
||||
|
||||
(defwidget workspaces []
|
||||
(eventbox :onscroll "bash ~/.config/eww/scripts/change-active-workspace {} ${current_workspace}" :class "workspaces"
|
||||
(box :space-evenly true :halign "start" :spacing 10
|
||||
(label :text "${workspaces}${current_workspace}" :visible false)
|
||||
(for workspace in workspaces
|
||||
(button :onclick "hyprctl dispatch workspace ${workspace.id}"
|
||||
(box :class "workspaces ${workspace.id == current_workspace ? "current" : ""}"
|
||||
(label :text "${workspace.id}")))))))
|
||||
|
||||
|
||||
(deflisten window :initial "..." "bash ~/.config/eww/scripts/get-window-title")
|
||||
(defwidget window []
|
||||
(box :class "window"
|
||||
(label :text "${window}")))
|
||||
|
||||
(defwidget music []
|
||||
(box :class "music ${music_status == "Playing" ? "playing" : "paused"}"
|
||||
:orientation "h"
|
||||
:space-evenly false
|
||||
:halign "center"
|
||||
(button :onclick "sp play" {music != "" ? "${music}" : ""})))
|
||||
|
||||
(defwidget icon-module [icon ?class ?visible]
|
||||
(box :class "${class} icon-module"
|
||||
:orientation "h"
|
||||
:halign "end"
|
||||
:space-evenly false
|
||||
:visible {visible ?: true} ; because the argument is optional
|
||||
(label :class "icon-module__icon" :text "${icon}")
|
||||
(children)))
|
||||
|
||||
(defwidget metric [label value onchange]
|
||||
(box :orientation "h"
|
||||
:class "metric"
|
||||
:space-evenly false
|
||||
(box :class "label" label)
|
||||
(scale :min 0
|
||||
:max 101
|
||||
:active {onchange != ""}
|
||||
:value value
|
||||
:onchange onchange)))
|
||||
|
||||
(defpoll music
|
||||
:interval "1s"
|
||||
"scripts/get-music")
|
||||
|
||||
(defpoll music_status
|
||||
:interval "1s"
|
||||
"sp status")
|
||||
|
||||
(defpoll volume
|
||||
:interval "1s"
|
||||
"scripts/getvol")
|
||||
|
||||
(defwidget metric_extended [label value onchange]
|
||||
(box
|
||||
:orientation "h"
|
||||
:class "metric"
|
||||
:space-evenly false
|
||||
(box
|
||||
:class "label" label)
|
||||
(scale
|
||||
:min 0
|
||||
:max 256
|
||||
:active {onchange != ""}
|
||||
:value value
|
||||
:onchang
|
||||
:onchange onchange)))
|
||||
|
||||
(defpoll brightness
|
||||
:interval "1s"
|
||||
:class "brightness"
|
||||
"brightnessctl get")
|
||||
|
||||
;; "format-icons": ["", "", "", "", "", "", "", "", ""],
|
||||
|
||||
(defwidget battery []
|
||||
(icon-module
|
||||
:icon "${EWW_BATTERY.BAT0.status == "Charging" ? "" :
|
||||
EWW_BATTERY.BAT0.capacity > 90 ? "" :
|
||||
EWW_BATTERY.BAT0.capacity > 70 ? "" :
|
||||
EWW_BATTERY.BAT0.capacity > 40 ? "" :
|
||||
EWW_BATTERY.BAT0.capacity > 20 ? "" :
|
||||
""}"
|
||||
:class "battery ${EWW_BATTERY.BAT0.capacity > 30 ? "good" : EWW_BATTERY.BAT0.capacity > 10 ? "warning" : "critical"} ${EWW_BATTERY.BAT0.status}"
|
||||
(label
|
||||
:text "${EWW_BATTERY.BAT0.capacity}%")))
|
||||
|
||||
|
||||
(defpoll time :interval "1s"
|
||||
"date '+%H:%M:%S'")
|
||||
|
||||
(defpoll date :interval "10s"
|
||||
"date '+%d.%m.%Y'")
|
||||
|
||||
|
||||
(defpoll github_poll
|
||||
:initial ""
|
||||
:interval "1m" "sh ~/.config/eww/scripts/github")
|
||||
(defwidget github []
|
||||
(button
|
||||
:onclick "xdg-open https://github.com/notifications"
|
||||
(box
|
||||
(icon-module
|
||||
:class "github"
|
||||
:icon ""
|
||||
:visible {github_poll != ""})
|
||||
github_poll)))
|
||||
|
||||
|
||||
(defwidget cpu []
|
||||
(icon-module
|
||||
:icon ""
|
||||
:class "cpu ${EWW_CPU.avg > 90 ? "danger" : EWW_CPU.avg > 60 ? "warning" : ""}"
|
||||
(label
|
||||
:text "${round(EWW_CPU.avg, 0)}%")))
|
||||
|
||||
;; (defpoll net_poll
|
||||
;; :initial "..."
|
||||
;; :interval "10s" "sh ~/.config/eww/scripts/get-network")
|
||||
(defwidget network []
|
||||
(icon-module
|
||||
:icon ""
|
||||
:class "network ${EWW_NET.wlan0.NET_DOWN == 0 && EWW_NET.wlan0.NET_UP == 0 ? "disconnected" : ""}"
|
||||
(label
|
||||
:text "${EWW_NET.wlan0.NET_DOWN == 0 && EWW_NET.wlan0.NET_UP == 0 ? "Disconnected ⚠" : ""}")))
|
||||
|
||||
|
||||
|
||||
|
||||
;; "network": {
|
||||
;; "format-wifi": "{essid} ({signalStrength}%) ",
|
||||
;; "format-ethernet": "{ipaddr}/{cidr} ",
|
||||
;; "tooltip-format": "{ifname} via {gwaddr} ",
|
||||
;; "format-linked": "{ifname} (No IP) ",
|
||||
;; "format-disconnected": "",
|
||||
;; "format-alt": "{ifname}: {ipaddr}/{cidr}"
|
||||
;; },
|
||||
|
||||
|
||||
(defwindow bar
|
||||
:monitor 0
|
||||
:exclusive true
|
||||
:geometry (geometry
|
||||
:x "0%"
|
||||
:y "0%"
|
||||
:width "100%"
|
||||
:height "10px"
|
||||
:anchor "top center")
|
||||
:reserve (struts :side "top" :distance "4%")
|
||||
(bar))
|
||||
|
||||
|
||||
(defwindow bar-1
|
||||
:monitor 1
|
||||
:exclusive true
|
||||
:geometry (geometry
|
||||
:x "0%"
|
||||
:y "0%"
|
||||
:width "100%"
|
||||
:height "10px"
|
||||
:anchor "top center")
|
||||
:reserve (struts :side "top" :distance "4%")
|
||||
(bar))
|
||||
21
config/eww/scripts/change-active-workspace
Executable file
21
config/eww/scripts/change-active-workspace
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
function clamp {
|
||||
min=$1
|
||||
max=$2
|
||||
val=$3
|
||||
python -c "print(max($min, min($val, $max)))"
|
||||
}
|
||||
|
||||
direction=$1
|
||||
current=$2
|
||||
if test "$direction" = "down"
|
||||
then
|
||||
target=$(clamp 1 10 $(($current+1)))
|
||||
echo "jumping to $target"
|
||||
hyprctl dispatch workspace $target
|
||||
elif test "$direction" = "up"
|
||||
then
|
||||
target=$(clamp 1 10 $(($current-1)))
|
||||
echo "jumping to $target"
|
||||
hyprctl dispatch workspace $target
|
||||
fi
|
||||
8
config/eww/scripts/get-active-workspace
Executable file
8
config/eww/scripts/get-active-workspace
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
hyprctl monitors -j | jq '.[] | select(.focused) | .activeWorkspace.id'
|
||||
|
||||
socat -u UNIX-CONNECT:$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - |
|
||||
stdbuf -o0 awk -F '>>|,' -e '/^workspace>>/ {print $2}' -e '/^focusedmon>>/ {print $3}'
|
||||
|
||||
# socat -u UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - | stdbuf -o0 awk -F '>>|,' -e '/^workspace>>/ {print $2}' -e '/^focusedmon>>/ {print $3}'
|
||||
5
config/eww/scripts/get-music
Executable file
5
config/eww/scripts/get-music
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
title="$(sp metadata | rg title| cut -d'|' -f2)"
|
||||
artist="$(sp metadata | rg artist | cut -d'|' -f2)"
|
||||
echo "$artist" - "$title"
|
||||
5
config/eww/scripts/get-network
Executable file
5
config/eww/scripts/get-network
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
line=$(nmcli connection show | rg wlan0)
|
||||
echo $line
|
||||
|
||||
2
config/eww/scripts/get-window-title
Executable file
2
config/eww/scripts/get-window-title
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
socat -u UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - | stdbuf -o0 awk -F '>>|,' '/^activewindow>>/{print $3}'
|
||||
11
config/eww/scripts/get-workspaces
Executable file
11
config/eww/scripts/get-workspaces
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
spaces (){
|
||||
windows=$(hyprctl workspaces -j | jq 'map({id: .id}) | sort_by(.id)')
|
||||
echo $windows
|
||||
}
|
||||
|
||||
spaces
|
||||
socat -u UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - | while read -r line; do
|
||||
spaces
|
||||
done
|
||||
12
config/eww/scripts/getvol
Executable file
12
config/eww/scripts/getvol
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
if command -v pamixer &>/dev/null; then
|
||||
if [ true == $(pamixer --get-mute) ]; then
|
||||
echo 0
|
||||
exit
|
||||
else
|
||||
pamixer --get-volume
|
||||
fi
|
||||
else
|
||||
amixer -D pulse sget Master | awk -F '[^0-9]+' '/Left:/{print $3}'
|
||||
fi
|
||||
4
config/eww/scripts/github
Executable file
4
config/eww/scripts/github
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
notifications="$(gh api notifications 2> /dev/null | jq '. | length')"
|
||||
[ -z notifications ] && echo "" || echo "$notifications"
|
||||
277
config/fastfetch/config.conf
Normal file
277
config/fastfetch/config.conf
Normal file
@@ -0,0 +1,277 @@
|
||||
# Fastfetch configuration
|
||||
# Write every argument in different lines.
|
||||
# Direct arguments will overwrite the corresponding ones in this file.
|
||||
# Argument keys are not case sensitive.
|
||||
# Whitespaces are trimmed at the beginning and the end.
|
||||
# Empty lines or lines starting with # are ignored.
|
||||
|
||||
# This file was shipped with 1.3.3.
|
||||
# Use fastfetch --print-config > ~/.config/fastfetch/config.conf to overwrite this with the current defaults
|
||||
|
||||
# Below some often useful options are listed. Uncomment and modify them so they take affect.
|
||||
# Note that there are a lot more options than the ones listed here, take a look at "fastfetch --help".
|
||||
# Of course all of them can be made persistent here too.
|
||||
|
||||
# Config option:
|
||||
# Load additional config files.
|
||||
# Some are shipped with fastfetch, list them with "fastfetch --list-presets".
|
||||
# Must be a path to a config file or the name of a shipped preset.
|
||||
# The config file is completly loaded before continuing in the current file, so the placement of this option matters, as later options overwrite already set ones.
|
||||
# Can be used multiple times to load multiple config files / presets.
|
||||
#--load-config /path/to/config.txt
|
||||
|
||||
# Structure option:
|
||||
# Sets the modules to use and their order.
|
||||
# Must be a list of module names, separated by colons.
|
||||
# List available modules with "fastfetch --list-modules".
|
||||
# Get the default structure with "fastfetch --print-structure".
|
||||
# --structure Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Locale:Break:Colors
|
||||
--structure
|
||||
Title
|
||||
Separator
|
||||
OS
|
||||
Host
|
||||
Kernel
|
||||
Uptime
|
||||
Break
|
||||
Packages
|
||||
Break
|
||||
Memory
|
||||
Disk
|
||||
Battery
|
||||
Break
|
||||
DateTime
|
||||
Break
|
||||
Colors
|
||||
|
||||
# Multithreading option:
|
||||
# Sets if fastfetch should use multiple threads to detect the values.
|
||||
# Must be true or false.
|
||||
# Default is true.
|
||||
--multithreading true
|
||||
|
||||
# Slow operations option:
|
||||
# Sets if fastfetch is allowed to use known slow operations to detect more / better values.
|
||||
# Must be true or false.
|
||||
# Default is false.
|
||||
#--allow-slow-operations false
|
||||
|
||||
# Linewrap option:
|
||||
# Sets if fastfetch should disable linewrap during the run.
|
||||
# Must be true or false.
|
||||
# Default is true.
|
||||
#--disable-linewrap true
|
||||
|
||||
# Cursor option:
|
||||
# Sets if fastfetch should hide the console cursor during the run.
|
||||
# Must be true or false.
|
||||
# Default is true.
|
||||
--hide-cursor true
|
||||
|
||||
# Logo option:
|
||||
# Sets the logo to use.
|
||||
# List available logos with "fastfetch --list-logos".
|
||||
# Print available logos with "fastfetch --print-logos".
|
||||
# Must be the name of an available logo or a path to a text file containing a custom logo.
|
||||
# Default is the current distribution.
|
||||
#--logo arch
|
||||
|
||||
# Logo type option:
|
||||
# Sets the logo type to use.
|
||||
# Must be auto, builtin, file, raw, sixel or kitty.
|
||||
# Default is auto.
|
||||
--logo-type auto
|
||||
|
||||
# Logo width option:
|
||||
# Sets the width of the logos (in characters) if the logo is an image.
|
||||
# Must be a positive integer.
|
||||
# Default is 65.
|
||||
--logo-width 65
|
||||
|
||||
# Logo color options:
|
||||
# Overwrite a color in the logo. Also works for user provided logos.
|
||||
# In the user logo, they replace $[1-9]. Use $$ to print a single $ sign.
|
||||
# Must be linux console color codes or the name of a color.
|
||||
# Default is the one specified by the logo.
|
||||
# Use "fastfetch --help color" to learn more and see examples.
|
||||
# Valid index range is [1-9].
|
||||
# --logo-color-1 red
|
||||
# --logo-color-2 32
|
||||
# [...]
|
||||
# --logo-color-9 yellow
|
||||
|
||||
# Logo padding option:
|
||||
# Adds a padding to the left and the right side of the logo.
|
||||
# Must be a positive integer.
|
||||
# Default is 0.
|
||||
# --logo-padding 0
|
||||
|
||||
# Logo padding left option:
|
||||
# Adds a padding to the left side of the logo.
|
||||
# Must be a positive integer.
|
||||
# Default is 0.
|
||||
# --logo-padding-left 0
|
||||
|
||||
# Logo padding right option:
|
||||
# Adds a padding to the right side of the logo.
|
||||
# Must be a positive integer.
|
||||
# Default is 0.
|
||||
#--logo-padding-right 0
|
||||
|
||||
# Logo print remaining option:
|
||||
# Sets if the remaining logo should be printed, it is has more lines than modules to show.
|
||||
# Must be true or false.
|
||||
# Default is true.
|
||||
# --logo-print-remaining true
|
||||
|
||||
# Color option:
|
||||
# Sets the color of the keys.
|
||||
# Must be linux console color codes or the name of a color.
|
||||
# Default is the primary color of the logo.
|
||||
# Use "fastfetch --help color" to learn more and see examples.
|
||||
#--color magenta
|
||||
|
||||
# Separator option:
|
||||
# Sets the string placed between a key and its value.
|
||||
# Can be any string.
|
||||
# Default is ": ".
|
||||
--separator ": "
|
||||
|
||||
# Separator string option:
|
||||
# Sets the string printed by the "separator" module (usually between title and rest of output)
|
||||
# Must be any string. It is repated / cut to fit perfectly.
|
||||
# Default is "-"
|
||||
--separator-string -
|
||||
|
||||
# Public IP timeout option:
|
||||
# Sets the time to wait for the public ip server to respond.
|
||||
# Must be a positive integer.
|
||||
# Default is 0 (disabled).
|
||||
#--public-ip-timeout 0
|
||||
|
||||
# OS file option
|
||||
# Sets the path to the file containing the operating system information.
|
||||
# Should be a valid path to an existing file.
|
||||
# Note that you might need to run fastfetch with --recache once for it to take affect.
|
||||
# Default is /etc/os-release.
|
||||
#--os-file /etc/os-release
|
||||
|
||||
# Player name option
|
||||
# Sets the name of the player. This is also used in song detection
|
||||
# Must be the exact name of the player or a dbus address (e.g. org.mpris.MediaPlayer2.spotify)
|
||||
# Default is the first match starting with org.mpris.MediaPlayer2.
|
||||
--player-name spotify
|
||||
|
||||
# Key options:
|
||||
# Sets the displayed key of a module
|
||||
# Can be any string. Some of theme take an argument like a format string. See "fastfetch --help format" for help.
|
||||
# --os-key OS
|
||||
# --os-key OS
|
||||
# --os-key ""
|
||||
--os-key BTW I use
|
||||
# --host-key Host
|
||||
# --host-key ""
|
||||
--host-key Mainframe
|
||||
# --kernel-key Kernel
|
||||
# --kernel-key ""
|
||||
--kernel-key Penguin
|
||||
# --uptime-key Uptime
|
||||
--uptime-key Time without touching grass
|
||||
# --processes-key Processes
|
||||
# --packages-key Packages
|
||||
# --packages-key ""
|
||||
--packages-key Bloat amount
|
||||
# --shell-key Shell
|
||||
# --wm-key ""
|
||||
# --shell-key ""
|
||||
--shell-key Krab
|
||||
# --resolution-key Resolution {1}
|
||||
# --resolution-key Flex {1}
|
||||
# --de-key DE
|
||||
# --wm-key WM
|
||||
# --wm-theme-key WM Theme
|
||||
# --theme-key Theme
|
||||
# --icons-key Icons
|
||||
# --font-key Font
|
||||
# --cursor-key Cursor
|
||||
# --terminal-key Terminal
|
||||
# --terminal-key ""
|
||||
# --terminal-font-key Terminal Font
|
||||
# --terminal-font-key ""
|
||||
# --cpu-key CPU
|
||||
# --cpu-key ""
|
||||
--cpu-key Toaster
|
||||
# --cpu-usage-key CPU Usage
|
||||
# --gpu-key GPU {1}
|
||||
# --gpu-key ""
|
||||
--gpu-key Crypto Miner
|
||||
# --memory-key Memory
|
||||
--memory-key I forgot
|
||||
# --disk-key Disk ({1})
|
||||
--disk-key Floppy {1}
|
||||
# --battery-key Battery {1}
|
||||
--battery-key Juice
|
||||
# --locale-key Locale
|
||||
# --local-ip-key Local IP ({1})
|
||||
# --public-ip-key Public IP
|
||||
# --public-ip-key Doxxed
|
||||
# --public-ip-key AAA Server
|
||||
--player-key Media Player
|
||||
# --song-key Song
|
||||
# --song-key Earrape
|
||||
--datetime-key Spacetime
|
||||
|
||||
# Format options:
|
||||
# Sets the format string for module values.
|
||||
# For information on format strings, see "fastfetch --help format".
|
||||
# To see the parameter they take and their default value, see "fastfetch --help *-format", e.g. "fastfetch --help os-format".
|
||||
# An empty format string (As they are currently below) will behave as if it was not set.
|
||||
# --os-format
|
||||
# --host-format
|
||||
# --kernel-format
|
||||
# --uptime-format
|
||||
# --processes-format
|
||||
# --packages-format
|
||||
# --shell-format
|
||||
# --resolution-format
|
||||
# --de-format
|
||||
# --wm-format
|
||||
# --wm-theme-format
|
||||
# --theme-format
|
||||
# --icons-format
|
||||
# --font-format
|
||||
# --cursor-format
|
||||
# --terminal-format
|
||||
# --terminal-font-format
|
||||
# --cpu-format
|
||||
# --cpu-usage-format
|
||||
# --gpu-format
|
||||
# --memory-format
|
||||
# --disk-format
|
||||
# --battery-format
|
||||
# --locale-format
|
||||
# --local-ip-format
|
||||
# --public-ip-format
|
||||
# --player-format
|
||||
# --song-format
|
||||
# --datetime-format
|
||||
|
||||
# Library options:
|
||||
# Sets an user specific path to a library to load.
|
||||
# Must be a valid path to a library.
|
||||
#--lib-PCI /usr/lib/libpci.so
|
||||
#--lib-vulkan /usr/lib/libvulkan.so
|
||||
#--lib-wayland /usr/lib/libwayland-client.so
|
||||
#--lib-xcb-randr /usr/lib/libxcb-randr.so
|
||||
#--lib-xcb /usr/lib/libxcb.so
|
||||
#--lib-Xrandr /usr/lib/libXrandr.so
|
||||
#--lib-X11 /usr/lib/libX11.so
|
||||
#--lib-gio /usr/lib/libgio-2.0.so
|
||||
#--lib-DConf /usr/lib/libdconf.so
|
||||
#--lib-DBus /usr/lib/libdbus-1.so
|
||||
#--lib-XFConf /usr/lib/libxfconf-0.so
|
||||
#--lib-rpm /usr/lib/librpm.so
|
||||
#--lib-imagemagick /usr/lib/libMagickCore-7.Q16HDRI.so
|
||||
#--lib-z /usr/lib/libz.so
|
||||
|
||||
|
||||
19
config/fastfetch/config.jsonc
Normal file
19
config/fastfetch/config.jsonc
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"modules": [
|
||||
"title",
|
||||
"separator",
|
||||
"os",
|
||||
"host",
|
||||
"kernel",
|
||||
"uptime",
|
||||
"break",
|
||||
"packages",
|
||||
"break",
|
||||
"memory",
|
||||
"disk",
|
||||
"battery",
|
||||
"break",
|
||||
"colors"
|
||||
]
|
||||
}
|
||||
12
config/flameshot.ini
Normal file
12
config/flameshot.ini
Normal file
@@ -0,0 +1,12 @@
|
||||
[General]
|
||||
contrastOpacity=188
|
||||
drawColor=#ff0000
|
||||
drawThickness=3
|
||||
filenamePattern=%Y-%m-%d_%H-%M-%S
|
||||
saveAfterCopy=true
|
||||
savePath=/home/kristofers/Pictures/screenshots
|
||||
savePathFixed=false
|
||||
showMagnifier=true
|
||||
squareMagnifier=true
|
||||
uiColor=#ffffff
|
||||
uploadHistoryMax=25
|
||||
95
config/gitui/key_bindings.ron
Normal file
95
config/gitui/key_bindings.ron
Normal file
@@ -0,0 +1,95 @@
|
||||
// bit for modifiers
|
||||
// bits: 0 None
|
||||
// bits: 1 SHIFT
|
||||
// bits: 2 CONTROL
|
||||
//
|
||||
// NOTE:
|
||||
// If the default key layout is lower case,
|
||||
// and you want to use `Shift + q` to trigger the exit event,
|
||||
// the setting should like this `exit: Some(( code: Char('Q'), modifiers: ( bits: 1,),)),`
|
||||
// The Char should be upper case, and the shift modified bit should be set to 1.
|
||||
(
|
||||
tab_status: Some((code: Char('1'), modifiers: (bits: 0))),
|
||||
tab_log: Some((code: Char('2'), modifiers: (bits: 0))),
|
||||
tab_files: Some((code: Char('3'), modifiers: (bits: 0))),
|
||||
tab_stashing: Some((code: Char('4'), modifiers: (bits: 0))),
|
||||
tab_stashes: Some((code: Char('5'), modifiers: (bits: 0))),
|
||||
tab_toggle: Some((code: Char('L'), modifiers: (bits: 1))),
|
||||
tab_toggle_reverse: Some((code: Char('H'), modifiers: (bits: 1))),
|
||||
toggle_workarea: Some((code: Char('w'), modifiers: (bits: 0))),
|
||||
exit: None,
|
||||
quit: None,
|
||||
exit_popup: Some((code: Char('q'), modifiers: (bits: 0))),
|
||||
open_commit: Some((code: Char('c'), modifiers: (bits: 0))),
|
||||
open_commit_editor: Some((code: Char('e'), modifiers: (bits: 2))),
|
||||
open_help: Some((code: F(1), modifiers: (bits: 0))),
|
||||
open_options: Some((code: Char('o'), modifiers: (bits: 0))),
|
||||
move_left: Some((code: Char('h'), modifiers: (bits: 0))),
|
||||
move_right: Some((code: Char('l'), modifiers: (bits: 0))),
|
||||
tree_collapse_recursive: Some((code: Left, modifiers: (bits: 1))),
|
||||
tree_expand_recursive: Some((code: Right, modifiers: (bits: 1))),
|
||||
home: Some((code: Char('g'), modifiers: (bits: 0))),
|
||||
end: Some((code: Char('G'), modifiers: (bits: 0))),
|
||||
move_up: Some((code: Char('k'), modifiers: (bits: 0))),
|
||||
move_down: Some((code: Char('j'), modifiers: (bits: 0))),
|
||||
popup_up: Some((code: Char('p'), modifiers: (bits: 2))),
|
||||
popup_down: Some((code: Char('n'), modifiers: (bits: 2))),
|
||||
page_up: Some((code: Char('u'), modifiers: (bits: 2))),
|
||||
page_down: Some((code: Char('d'), modifiers: (bits: 2))),
|
||||
shift_up: Some((code: Up, modifiers: (bits: 1))),
|
||||
shift_down: Some((code: Down, modifiers: (bits: 1))),
|
||||
enter: Some((code: Enter, modifiers: (bits: 0))),
|
||||
blame: Some((code: Char('b'), modifiers: (bits: 0))),
|
||||
file_history: Some((code: Char('h'), modifiers: (bits: 2))),
|
||||
edit_file: Some((code: Char('e'), modifiers: (bits: 0))),
|
||||
status_stage_all: Some((code: Char('a'), modifiers: (bits: 0))),
|
||||
status_reset_item: Some((code: Char('U'), modifiers: (bits: 1))),
|
||||
diff_reset_lines: Some((code: Char('u'), modifiers: (bits: 0))),
|
||||
status_ignore_file: Some((code: Char('i'), modifiers: (bits: 0))),
|
||||
diff_stage_lines: Some((code: Char('s'), modifiers: (bits: 0))),
|
||||
stashing_save: Some((code: Char('w'), modifiers: (bits: 0))),
|
||||
stashing_toggle_untracked: Some((code: Char('u'), modifiers: (bits: 0))),
|
||||
stashing_toggle_index: Some((code: Char('m'), modifiers: (bits: 0))),
|
||||
stash_apply: Some((code: Char('a'), modifiers: (bits: 0))),
|
||||
stash_open: Some((code: Char('l'), modifiers: (bits: 0))),
|
||||
stash_drop: Some((code: Char('D'), modifiers: (bits: 1))),
|
||||
cmd_bar_toggle: Some((code: Char('.'), modifiers: (bits: 0))),
|
||||
log_tag_commit: Some((code: Char('t'), modifiers: (bits: 0))),
|
||||
log_mark_commit: Some((code: Char(' '), modifiers: (bits: 0))),
|
||||
log_checkout_commit: Some((code: Char('S'), modifiers: (bits: 1))),
|
||||
log_reset_comit: Some((code: Char('R'), modifiers: (bits: 1))),
|
||||
log_reword_comit: Some((code: Char('r'), modifiers: (bits: 0))),
|
||||
log_find: Some((code: Char('/'), modifiers: (bits: 0))),
|
||||
find_commit_sha: Some((code: Char('/'), modifiers: (bits: 0))),
|
||||
commit_amend: Some((code: Char('a'), modifiers: (bits: 2))),
|
||||
toggle_signoff: Some((code: Char('s'), modifiers: (bits: 2))),
|
||||
toggle_verify: Some((code: Char('v'), modifiers: (bits: 2))),
|
||||
copy: Some((code: Char('y'), modifiers: (bits: 0))),
|
||||
create_branch: Some((code: Char('c'), modifiers: (bits: 0))),
|
||||
rename_branch: Some((code: Char('r'), modifiers: (bits: 0))),
|
||||
select_branch: Some((code: Char('b'), modifiers: (bits: 0))),
|
||||
delete_branch: Some((code: Char('D'), modifiers: (bits: 1))),
|
||||
merge_branch: Some((code: Char('m'), modifiers: (bits: 0))),
|
||||
rebase_branch: Some((code: Char('R'), modifiers: (bits: 1))),
|
||||
compare_commits: Some((code: Char('C'), modifiers: (bits: 1))),
|
||||
tags: Some((code: Char('T'), modifiers: (bits: 1))),
|
||||
delete_tag: Some((code: Char('D'), modifiers: (bits: 1))),
|
||||
select_tag: Some((code: Char(' '), modifiers: (bits: 0))),
|
||||
push: Some((code: Char('P'), modifiers: (bits: 1))),
|
||||
force_push: None,
|
||||
undo_commit: Some((code: Char('U'), modifiers: (bits: 1))),
|
||||
fetch: Some((code: Char('F'), modifiers: (bits: 1))),
|
||||
pull: Some((code: Char('p'), modifiers: (bits: 0))),
|
||||
abort_merge: Some((code: Char('A'), modifiers: (bits: 1))),
|
||||
open_file_tree: Some((code: Char('F'), modifiers: (bits: 1))),
|
||||
file_find: Some((code: Char('/'), modifiers: (bits: 0))),
|
||||
branch_find: Some((code: Char('/'), modifiers: (bits: 0))),
|
||||
diff_hunk_next: Some((code: Char('n'), modifiers: (bits: 0))),
|
||||
diff_hunk_prev: Some((code: Char('p'), modifiers: (bits: 0))),
|
||||
stage_unstage_item: Some((code: Char(' '), modifiers: (bits: 0))),
|
||||
tag_annotate: Some((code: Char('a'), modifiers: (bits: 2))),
|
||||
view_submodules: Some((code: Char('S'), modifiers: (bits: 1))),
|
||||
view_submodule_parent: Some((code: Char('p'), modifiers: (bits: 0))),
|
||||
update_submodule: Some((code: Char('u'), modifiers: (bits: 0))),
|
||||
commit_history_next: Some((code: Char('n'), modifiers: (bits: 2))),
|
||||
)
|
||||
23
config/gitui/theme.ron
Normal file
23
config/gitui/theme.ron
Normal file
@@ -0,0 +1,23 @@
|
||||
(
|
||||
selected_tab: Reset,
|
||||
command_fg: White,
|
||||
selection_bg: Blue,
|
||||
selection_fg: Black,
|
||||
cmdbar_bg: Reset,
|
||||
cmdbar_extra_lines_bg: Reset,
|
||||
disabled_fg: DarkGray,
|
||||
diff_line_add: Green,
|
||||
diff_line_delete: Red,
|
||||
diff_file_added: LightGreen,
|
||||
diff_file_removed: LightRed,
|
||||
diff_file_moved: LightMagenta,
|
||||
diff_file_modified: Yellow,
|
||||
commit_hash: Magenta,
|
||||
commit_time: LightCyan,
|
||||
commit_author: Green,
|
||||
danger_fg: Red,
|
||||
push_gauge_bg: Reset,
|
||||
push_gauge_fg: Magenta,
|
||||
tag_fg: LightMagenta,
|
||||
branch_fg: LightYellow,
|
||||
)
|
||||
1
config/gtklock/config.ini
Normal file
1
config/gtklock/config.ini
Normal file
@@ -0,0 +1 @@
|
||||
modules=/usr/lib/gtklock/playerctl-module.so;/usr/lib/gtklock/powerbar-module.so;/usr/lib/gtklock/userinfo-module.so
|
||||
11
config/gtklock/style.css
Normal file
11
config/gtklock/style.css
Normal file
@@ -0,0 +1,11 @@
|
||||
window#HDMI-A-2 {
|
||||
background-image: url("/tmp/HDMI-A-2.png");
|
||||
}
|
||||
|
||||
window#DP-1 {
|
||||
background-image: url("/tmp/DP-1.png");
|
||||
}
|
||||
|
||||
window#eDP-1 {
|
||||
background-image: url("/tmp/eDP-1.png");
|
||||
}
|
||||
63
config/htoprc
Normal file
63
config/htoprc
Normal file
@@ -0,0 +1,63 @@
|
||||
# Beware! This file is rewritten by htop when settings are changed in the interface.
|
||||
# The parser is also very primitive, and not human-friendly.
|
||||
htop_version=3.3.0
|
||||
config_reader_min_version=3
|
||||
fields=0 48 17 18 38 39 40 2 46 47 49 1
|
||||
hide_kernel_threads=1
|
||||
hide_userland_threads=0
|
||||
hide_running_in_container=0
|
||||
shadow_other_users=0
|
||||
show_thread_names=0
|
||||
show_program_path=1
|
||||
highlight_base_name=0
|
||||
highlight_deleted_exe=1
|
||||
shadow_distribution_path_prefix=0
|
||||
highlight_megabytes=1
|
||||
highlight_threads=1
|
||||
highlight_changes=0
|
||||
highlight_changes_delay_secs=5
|
||||
find_comm_in_cmdline=1
|
||||
strip_exe_from_cmdline=1
|
||||
show_merged_command=0
|
||||
header_margin=1
|
||||
screen_tabs=1
|
||||
detailed_cpu_time=0
|
||||
cpu_count_from_one=0
|
||||
show_cpu_usage=1
|
||||
show_cpu_frequency=1
|
||||
show_cpu_temperature=1
|
||||
degree_fahrenheit=0
|
||||
update_process_names=0
|
||||
account_guest_in_cpu_meter=0
|
||||
color_scheme=0
|
||||
enable_mouse=0
|
||||
delay=15
|
||||
hide_function_bar=0
|
||||
header_layout=two_50_50
|
||||
column_meters_0=LeftCPUs Memory Swap
|
||||
column_meter_modes_0=1 1 1
|
||||
column_meters_1=RightCPUs Tasks LoadAverage Uptime
|
||||
column_meter_modes_1=1 2 2 2
|
||||
tree_view=0
|
||||
sort_key=46
|
||||
tree_sort_key=0
|
||||
sort_direction=-1
|
||||
tree_sort_direction=1
|
||||
tree_view_always_by_pid=0
|
||||
all_branches_collapsed=0
|
||||
screen:Main=PID USER PRIORITY NICE M_VIRT M_RESIDENT M_SHARE STATE PERCENT_CPU PERCENT_MEM TIME Command
|
||||
.sort_key=PERCENT_CPU
|
||||
.tree_sort_key=PID
|
||||
.tree_view_always_by_pid=0
|
||||
.tree_view=0
|
||||
.sort_direction=-1
|
||||
.tree_sort_direction=1
|
||||
.all_branches_collapsed=0
|
||||
screen:I/O=PID USER IO_PRIORITY IO_RATE IO_READ_RATE IO_WRITE_RATE PERCENT_SWAP_DELAY PERCENT_IO_DELAY Command
|
||||
.sort_key=IO_RATE
|
||||
.tree_sort_key=PID
|
||||
.tree_view_always_by_pid=0
|
||||
.tree_view=0
|
||||
.sort_direction=-1
|
||||
.tree_sort_direction=1
|
||||
.all_branches_collapsed=0
|
||||
262
config/hypr/hyprland.conf
Normal file
262
config/hypr/hyprland.conf
Normal file
@@ -0,0 +1,262 @@
|
||||
# This is an example Hyprland config file.
|
||||
#
|
||||
# Refer to the wiki for more information.
|
||||
|
||||
#
|
||||
# Please note not all available settings / options are set here.
|
||||
# For a full list, see the wiki
|
||||
#
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Monitors/
|
||||
monitor=eDP-1,2880x1800@60,auto,1.5
|
||||
#monitor=,preferred,auto-up,1
|
||||
monitor=DP-1,disable
|
||||
#monitor=HDMI-A-1,highres,auto-up,1,mirror,eDP-1
|
||||
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||
|
||||
# Execute your favorite apps at launch
|
||||
# exec-once = waybar & hyprpaper & firefox
|
||||
exec-once = pipewire & pipewire-pulse & wireplumber & eww daemon & eww open bar & nextcloud & /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 & xrdb "$XDG_CONFIG_HOME/x11/xresources" & spotifyd --no-daemon & syncthing & transmission-daemon & dunst & dbus-update-activation-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP DISPLAY XAUTHORITY
|
||||
exec-once=[workspace 1 silent] librewolf
|
||||
exec-once=[workspace 8 silent] discord & telegram-desktop
|
||||
exec-once=[workspace 9 silent] spotify
|
||||
|
||||
# Source a file (multi-file configs)
|
||||
# source = ~/.config/hypr/myColors.conf
|
||||
source=~/.config/hypr/rose-pine.conf
|
||||
|
||||
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
|
||||
input {
|
||||
kb_layout = lv
|
||||
kb_variant =
|
||||
kb_model =
|
||||
kb_options = caps:escape
|
||||
kb_rules =
|
||||
numlock_by_default = true
|
||||
repeat_rate = 50
|
||||
repeat_delay = 300
|
||||
|
||||
follow_mouse = 1
|
||||
|
||||
touchpad {
|
||||
natural_scroll = yes
|
||||
disable_while_typing = false
|
||||
}
|
||||
|
||||
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
||||
}
|
||||
|
||||
debug {
|
||||
disable_logs = false
|
||||
enable_stdout_logs = true
|
||||
}
|
||||
|
||||
general {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
|
||||
gaps_in = 5
|
||||
gaps_out = 10
|
||||
border_size = 2
|
||||
col.active_border = $rose
|
||||
col.inactive_border = $muted
|
||||
|
||||
layout = master
|
||||
}
|
||||
|
||||
plugin {
|
||||
split-monitor-workspaces {
|
||||
count = 10
|
||||
}
|
||||
}
|
||||
|
||||
decoration {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
|
||||
rounding = 5
|
||||
# blur = yes
|
||||
# blur_size = 4
|
||||
# blur_passes = 1
|
||||
# blur_new_optimizations = on
|
||||
|
||||
drop_shadow = yes
|
||||
shadow_range = 4
|
||||
shadow_render_power = 3
|
||||
col.shadow = $highlightMed
|
||||
}
|
||||
|
||||
animations {
|
||||
enabled = no
|
||||
|
||||
# Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for moreqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ctqt6ct
|
||||
|
||||
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
|
||||
|
||||
animation = windows, 1, 7, myBezier
|
||||
animation = windowsOut, 1, 7, default, popin 80%
|
||||
animation = border, 1, 10, default
|
||||
animation = fade, 1, 7, default
|
||||
animation = workspaces, 1, 6, default
|
||||
}
|
||||
|
||||
dwindle {
|
||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
||||
pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
||||
preserve_split = yes # you probably want this
|
||||
}
|
||||
|
||||
master {
|
||||
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
||||
new_status = master
|
||||
}
|
||||
|
||||
gestures {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
workspace_swipe = on
|
||||
}
|
||||
|
||||
# Example per-device config
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
|
||||
#device:epic mouse V1 {
|
||||
#sensitivity = -0.5
|
||||
#}
|
||||
|
||||
# Example windowrule v1
|
||||
windowrulev2 = fullscreen, class:mpv
|
||||
|
||||
windowrulev2 = opacity 0.95, class:thunderbird
|
||||
|
||||
windowrulev2 = workspace 8, class:discord
|
||||
windowrulev2 = opacity 0.95, class:discord
|
||||
windowrulev2 = workspace 8, class:Ripcord
|
||||
windowrulev2 = workspace 8, class:TelegramDesktop
|
||||
windowrulev2 = opacity 0.95, class:TelegramDesktop
|
||||
windowrulev2 = opacity 0.9, class:teams-for-linux
|
||||
windowrulev2 = workspace 8, class:Ferdium
|
||||
windowrulev2 = opacity 0.9, class:Ferdium
|
||||
|
||||
windowrulev2 = workspace 9, class:Spotify
|
||||
windowrulev2 = opacity 0.9, class:Spotify
|
||||
windowrulev2 = tile, class:Spotify
|
||||
|
||||
windowrulev2 = opacity 0.95, class:qbittorrent
|
||||
windowrulev2 = opacity 0.95, class:lutris
|
||||
windowrulev2 = opacity 0.95, class:pacfinder
|
||||
windowrulev2 = opacity 0.9, class:Bitwarden
|
||||
windowrulev2 = opacity 0.9, class:kdeconnect
|
||||
# windowrulev2 = workspace 8, class:^()$
|
||||
|
||||
# Example windowrule v2
|
||||
windowrulev2 = move 100%-250 100%-250, class:galculator
|
||||
windowrulev2 = size 250 250, class:galculator
|
||||
windowrulev2 = float, class:galculator
|
||||
|
||||
windowrulev2=float,title:^(flameshot)
|
||||
windowrulev2=move 0 0,title:^(flameshot)
|
||||
windowrulev2=suppressevent fullscreen,title:^(flameshot)
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||
$mainMod = SUPER
|
||||
|
||||
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
|
||||
bind = $mainMod, B ,exec, librewolf
|
||||
bind = $mainMod, Return, exec, alacritty
|
||||
bind = $mainMod SHIFT, Q, killactive
|
||||
# bind = $mainMod SHIFT CTRL, Q, exit
|
||||
bind = $mainMod, N, exec, alacritty -e lfrun
|
||||
bind = $mainMod CTRL, SPACE, togglefloating
|
||||
bind = $mainMod, P, exec, wofi --show drun -ib
|
||||
bind = $mainMod, F, fullscreen
|
||||
bind = $mainMod, M, bringactivetotop
|
||||
bind = $mainMod, A, pin
|
||||
#bind = $mainMod, O, split-changemonitor, +1
|
||||
|
||||
# Resize window
|
||||
bind = $mainMod, L, splitratio, 0.05
|
||||
bind = $mainMod, H, splitratio, -0.05
|
||||
|
||||
# Move focus with mainMod + arrow keys
|
||||
bind = $mainMod, K, cyclenext
|
||||
bind = $mainMod, J, cyclenext, prev
|
||||
|
||||
# Switch workspaces with mainMod + [0-9]
|
||||
bind = $mainMod, 1, workspace, 1
|
||||
bind = $mainMod, 2, workspace, 2
|
||||
bind = $mainMod, 3, workspace, 3
|
||||
bind = $mainMod, 4, workspace, 4
|
||||
bind = $mainMod, 5, workspace, 5
|
||||
bind = $mainMod, 6, workspace, 6
|
||||
bind = $mainMod, 7, workspace, 7
|
||||
bind = $mainMod, 8, workspace, 8
|
||||
bind = $mainMod, 9, workspace, 9
|
||||
bind = $mainMod, 0, workspace, 10
|
||||
#bind = $mainMod, 1, split-workspace, 1
|
||||
#bind = $mainMod, 2, split-workspace, 2
|
||||
#bind = $mainMod, 3, split-workspace, 3
|
||||
#bind = $mainMod, 4, split-workspace, 4
|
||||
#bind = $mainMod, 5, split-workspace, 5
|
||||
#bind = $mainMod, 6, split-workspace, 6
|
||||
#bind = $mainMod, 7, split-workspace, 7
|
||||
#bind = $mainMod, 8, split-workspace, 8
|
||||
#bind = $mainMod, 9, split-workspace, 9
|
||||
#bind = $mainMod, 0, split-workspace, 10
|
||||
#
|
||||
# Move active window to a workspace with mainMod + SHIFT + [0-9]
|
||||
bind = $mainMod SHIFT, 1, movetoworkspacesilent, 1
|
||||
bind = $mainMod SHIFT, 2, movetoworkspacesilent, 2
|
||||
bind = $mainMod SHIFT, 3, movetoworkspacesilent, 3
|
||||
bind = $mainMod SHIFT, 4, movetoworkspacesilent, 4
|
||||
bind = $mainMod SHIFT, 5, movetoworkspacesilent, 5
|
||||
bind = $mainMod SHIFT, 6, movetoworkspacesilent, 6
|
||||
bind = $mainMod SHIFT, 7, movetoworkspacesilent, 7
|
||||
bind = $mainMod SHIFT, 8, movetoworkspacesilent, 8
|
||||
bind = $mainMod SHIFT, 9, movetoworkspacesilent, 9
|
||||
bind = $mainMod SHIFT, 0, movetoworkspacesilent, 10
|
||||
#bind = $mainMod SHIFT, 1, split-movetoworkspace, 1
|
||||
#bind = $mainMod SHIFT, 2, split-movetoworkspace, 2
|
||||
#bind = $mainMod SHIFT, 3, split-movetoworkspace, 3
|
||||
#bind = $mainMod SHIFT, 4, split-movetoworkspace, 4
|
||||
#bind = $mainMod SHIFT, 5, split-movetoworkspace, 5
|
||||
#bind = $mainMod SHIFT, 6, split-movetoworkspace, 6
|
||||
#bind = $mainMod SHIFT, 7, split-movetoworkspace, 7
|
||||
#bind = $mainMod SHIFT, 8, split-movetoworkspace, 8
|
||||
#bind = $mainMod SHIFT, 9, split-movetoworkspace, 9
|
||||
#bind = $mainMod SHIFT, 0, split-movetoworkspace, 10
|
||||
|
||||
# Scroll through existing workspaces with mainMod + scroll
|
||||
bind = $mainMod, right, workspace, e+1
|
||||
bind = $mainMod, left, workspace, e-1
|
||||
|
||||
# Move/resize windows with mainMod + LMB/RMB and dragging
|
||||
bindm = $mainMod, mouse:272, movewindow
|
||||
bindm = $mainMod CTRL, mouse:272, resizewindow
|
||||
|
||||
bind = $mainMod SHIFT, J, movewindow, d
|
||||
bind = $mainMod SHIFT, K, movewindow, u
|
||||
bind = $mainMod SHIFT, L, movewindow, r
|
||||
bind = $mainMod SHIFT, H, movewindow, l
|
||||
|
||||
|
||||
# bind = $mainMod CTRL, P, exec, wayshot -f "$(HOME)/Pictures/screenshots/$(date + '%s.png')" -s "$(slurp -f '%x %y %w %y')" --stdout | wl-copy
|
||||
# bind = $mainMod CTRL, P, exec, wayshot -s "$(slurp -f '%x %y %w %y')" --stdout | wl-copy
|
||||
# bind = $mainMod, , exec, wayshot -f "$(HOME)/Pictures/screenshots/$(date + '%s.png')"
|
||||
bind = CTRL, PRINT, exec, hyprshot -m region
|
||||
bind = , PRINT, exec, hyprshot -m output
|
||||
bind = SHIFT, PRINT, exec, hyprshot -m window
|
||||
|
||||
bind = $mainMod ALT, P, exec, hyprpicker -a # colorpicker
|
||||
|
||||
# Control keybinds
|
||||
bindel = , XF86MonBrightnessUp, exec, doas brightnessctl set +2% # increase brightness by 2%
|
||||
bindel = , XF86MonBrightnessDown, exec, doas brightnessctl set 2%- # decrease brightness by 2%
|
||||
bindel = , XF86AudioRaiseVolume, exec, pulsemixer --change-volume +2 # increase volume by 2
|
||||
bindel = , XF86AudioLowerVolume, exec, pulsemixer --change-volume -2 # decrease volume by 2
|
||||
bindel = , XF86AudioMute, exec, pulsemixer --toggle-mute # mute volume
|
||||
bindel = , XF86AudioPlay, exec, playerctl -a play-pause # pause/play everything
|
||||
bindel = $mainMod, Space, exec, hyprlock
|
||||
|
||||
bindl = , switch:Lid Switch, exec, hyprlock
|
||||
88
config/hypr/hyprlock.conf
Normal file
88
config/hypr/hyprlock.conf
Normal file
@@ -0,0 +1,88 @@
|
||||
$font = JetBrainsMonoNF
|
||||
|
||||
$bg = rgb(1a1b26)
|
||||
$fg = rgb(c0caf5)
|
||||
$border_highlight = rgb(27a1b9)
|
||||
$error = rgb(db4b4b)
|
||||
$warning = rgb(e0af68)
|
||||
|
||||
background {
|
||||
monitor =
|
||||
path = screenshot
|
||||
color = $bg
|
||||
|
||||
blur_passes = 1
|
||||
blur_size = 10
|
||||
noise = 0.1
|
||||
contrast = 0.9
|
||||
brightness = 0.8
|
||||
vibrancy = 0.1696
|
||||
vibrancy_darkness = 0.0
|
||||
}
|
||||
|
||||
# TIME
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:1000] echo "<span foreground='##c0caf5'>$(date +"%H:%M:%S")</span>"
|
||||
color = $text
|
||||
font_size = 90
|
||||
font_family = $font
|
||||
position = -30, 0
|
||||
halign = right
|
||||
valign = top
|
||||
}
|
||||
|
||||
# DATE
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:43200000] echo "<span foreground='##c0caf5'>$(date +"%d.%m.%Y")</span>"
|
||||
color = $text
|
||||
font_size = 25
|
||||
font_family = $font
|
||||
position = -30, -150
|
||||
halign = right
|
||||
valign = top
|
||||
}
|
||||
|
||||
|
||||
image {
|
||||
monitor =
|
||||
path = ~/.local/share/profile
|
||||
size = 300
|
||||
border_color = $border_highlight
|
||||
|
||||
position = 0, 200
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
|
||||
input-field {
|
||||
monitor =
|
||||
size = 300, 60
|
||||
outline_thickness = 4
|
||||
dots_size = 0.2
|
||||
dots_spacing = 0.2
|
||||
dots_center = true
|
||||
dots_rounding = -1 # -1 default circle, -2 follow input-field rounding
|
||||
outer_color = $border_highlight
|
||||
inner_color = $fg
|
||||
font_color = $bg
|
||||
fade_on_empty = true
|
||||
fade_timeout = 1000 # Milliseconds before fade_on_empty is triggered.
|
||||
placeholder_text = <i>Input Password...</i> # Text rendered in the input box when it's empty.
|
||||
hide_input = false
|
||||
rounding = -1 # -1 means complete rounding (circle/oval)
|
||||
check_color = rgb(e0af68)
|
||||
fail_color = rgb(db4b4b) # if authentication failed, changes outer_color and fail message color
|
||||
fail_text = <i>$FAIL <b>($ATTEMPTS)</b></i> # can be set to empty
|
||||
fail_transition = 300 # transition time in ms between normal outer_color and fail_color
|
||||
capslock_color = -1
|
||||
numlock_color = -1
|
||||
bothlock_color = -1 # when both locks are active. -1 means don't change outer color (same for above)
|
||||
invert_numlock = false # change color if numlock is off
|
||||
swap_font_color = false
|
||||
|
||||
position = 0, -35
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
6
config/hypr/hyprpaper.conf
Normal file
6
config/hypr/hyprpaper.conf
Normal file
@@ -0,0 +1,6 @@
|
||||
ipc = off
|
||||
splash = true
|
||||
preload = ~/Pictures/wallpapers/Linux-Dynamic-Wallpapers/Firewatch2/Firewatch2-1.png
|
||||
preload = ~/Pictures/wallpapers/Linux-Dynamic-Wallpapers/LakesideDeerComplete/LakesideDeer-03.png
|
||||
|
||||
wallpaper = ,~/Pictures/wallpapers/Linux-Dynamic-Wallpapers/LakesideDeerComplete/LakesideDeer-03.png
|
||||
20
config/hypr/rose-pine.conf
Normal file
20
config/hypr/rose-pine.conf
Normal file
@@ -0,0 +1,20 @@
|
||||
# name: Rosé Pine
|
||||
# author: jishnurajendran
|
||||
# upstream: https://github.com/jishnurajendran/hyprland-rosepine/blob/main/rose-pine.conf
|
||||
# All natural pine, faux fur and a bit of soho vibes for the classy minimalist
|
||||
$base = 0xff191724
|
||||
$surface = 0xff1f1d2e
|
||||
$overlay = 0xff26233a
|
||||
$muted = 0xff6e6a86
|
||||
$subtle = 0xff908caa
|
||||
$text = 0xffe0def4
|
||||
$love = 0xffeb6f92
|
||||
$gold = 0xfff6c177
|
||||
$rose = 0xffebbcba
|
||||
$pine = 0xff31748f
|
||||
$foam = 0xff9ccfd8
|
||||
$iris = 0xffc4a7e7
|
||||
$highlightLow = 0xff21202e
|
||||
$highlightMed = 0xff403d52
|
||||
$highlightHigh = 0xff524f67
|
||||
|
||||
6
config/joshuto/bookmarks.toml
Normal file
6
config/joshuto/bookmarks.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
bookmark = [
|
||||
{ key = "r", path = "/" },
|
||||
{ key = "e", path = "/etc" },
|
||||
|
||||
{ key = "h", path = "~/" },
|
||||
]
|
||||
51
config/joshuto/joshuto.toml
Normal file
51
config/joshuto/joshuto.toml
Normal file
@@ -0,0 +1,51 @@
|
||||
numbered_command = false
|
||||
|
||||
use_trash = true
|
||||
watch_files = true
|
||||
xdg_open = false
|
||||
xdg_open_fork = false
|
||||
|
||||
|
||||
[display]
|
||||
# default, hsplit
|
||||
mode = "default"
|
||||
|
||||
automatically_count_files = false
|
||||
collapse_preview = true
|
||||
# ratios for parent view (optional), current view and preview
|
||||
column_ratio = [1, 4, 4]
|
||||
scroll_offset = 6
|
||||
show_borders = true
|
||||
show_hidden = false
|
||||
show_icons = true
|
||||
tilde_in_titlebar = true
|
||||
# none, absolute, relative
|
||||
line_number_style = "none"
|
||||
|
||||
# size, mtime, user, gourp, perm. can be combined with |.
|
||||
# `none` to disable, `all` to enable all
|
||||
# all and none can't be combined with other options
|
||||
linemode = "size"
|
||||
|
||||
[display.sort]
|
||||
# lexical, mtime, natural, size, ext
|
||||
sort_method = "natural"
|
||||
case_sensitive = false
|
||||
directories_first = true
|
||||
reverse = false
|
||||
|
||||
[preview]
|
||||
max_preview_size = 2097152 # 2MB
|
||||
preview_script = "~/.config/joshuto/preview_file.sh" # make sure it's marked as executable
|
||||
|
||||
[search]
|
||||
# insensitive, sensitive, smart
|
||||
string_case_sensitivity = "insensitive"
|
||||
# see above
|
||||
glob_case_sensitivity = "sensitive"
|
||||
# see above
|
||||
fzf_case_sensitivity = "insensitive"
|
||||
|
||||
[tab]
|
||||
# inherit, home, root
|
||||
home_page = "home"
|
||||
172
config/joshuto/keymap.toml
Normal file
172
config/joshuto/keymap.toml
Normal file
@@ -0,0 +1,172 @@
|
||||
[default_view]
|
||||
|
||||
keymap = [
|
||||
{ keys = ["escape"], command = "escape" },
|
||||
{ keys = ["ctrl+t"], command = "new_tab" },
|
||||
{ keys = ["alt+t"], command = "new_tab --cursor" },
|
||||
{ keys = ["T"], command = "new_tab --current" },
|
||||
{ keys = ["W"], command = "close_tab" },
|
||||
{ keys = ["ctrl+w"], command = "close_tab" },
|
||||
{ keys = ["q"], command = "close_tab" },
|
||||
{ keys = ["ctrl+c"], command = "quit" },
|
||||
{ keys = ["Q"], command = "quit --output-current-directory" },
|
||||
|
||||
{ keys = ["R"], command = "reload_dirlist" },
|
||||
{ keys = ["z", "h"], command = "toggle_hidden" },
|
||||
{ keys = ["ctrl+h"], command = "toggle_hidden" },
|
||||
{ keys = ["\t"], command = "tab_switch 1" },
|
||||
{ keys = ["backtab"], command = "tab_switch -1" },
|
||||
|
||||
{ keys = ["alt+1"], command = "tab_switch_index 1" },
|
||||
{ keys = ["alt+2"], command = "tab_switch_index 2" },
|
||||
{ keys = ["alt+3"], command = "tab_switch_index 3" },
|
||||
{ keys = ["alt+4"], command = "tab_switch_index 4" },
|
||||
{ keys = ["alt+5"], command = "tab_switch_index 5" },
|
||||
|
||||
{ keys = ["1"], command = "numbered_command 1" },
|
||||
{ keys = ["2"], command = "numbered_command 2" },
|
||||
{ keys = ["3"], command = "numbered_command 3" },
|
||||
{ keys = ["4"], command = "numbered_command 4" },
|
||||
{ keys = ["5"], command = "numbered_command 5" },
|
||||
{ keys = ["6"], command = "numbered_command 6" },
|
||||
{ keys = ["7"], command = "numbered_command 7" },
|
||||
{ keys = ["8"], command = "numbered_command 8" },
|
||||
{ keys = ["9"], command = "numbered_command 9" },
|
||||
|
||||
# arrow keys
|
||||
{ keys = ["arrow_up"], command = "cursor_move_up" },
|
||||
{ keys = ["arrow_down"], command = "cursor_move_down" },
|
||||
{ keys = ["arrow_left"], command = "cd .." },
|
||||
{ keys = ["arrow_right"], command = "open" },
|
||||
{ keys = ["\n"], command = "open" },
|
||||
{ keys = ["home"], command = "cursor_move_home" },
|
||||
{ keys = ["end"], command = "cursor_move_end" },
|
||||
{ keys = ["page_up"], command = "cursor_move_page_up" },
|
||||
{ keys = ["page_down"], command = "cursor_move_page_down" },
|
||||
{ keys = ["ctrl+u"], command = "cursor_move_page_up 0.5" },
|
||||
{ keys = ["ctrl+d"], command = "cursor_move_page_down 0.5" },
|
||||
{ keys = ["ctrl+b"], command = "cursor_move_page_up" },
|
||||
{ keys = ["ctrl+f"], command = "cursor_move_page_down" },
|
||||
|
||||
# vim-like keybindings
|
||||
{ keys = ["j"], command = "cursor_move_down" },
|
||||
{ keys = ["k"], command = "cursor_move_up" },
|
||||
{ keys = ["h"], command = "cd .." },
|
||||
{ keys = ["l"], command = "open" },
|
||||
{ keys = ["g", "g"], command = "cursor_move_home" },
|
||||
{ keys = ["G"], command = "cursor_move_end" },
|
||||
{ keys = ["r"], command = "open_with" },
|
||||
|
||||
{ keys = ["H"], command = "cursor_move_page_home" },
|
||||
{ keys = ["L"], command = "cursor_move_page_middle" },
|
||||
{ keys = ["M"], command = "cursor_move_page_end" },
|
||||
|
||||
{ keys = ["["], command = "parent_cursor_move_up" },
|
||||
{ keys = ["]"], command = "parent_cursor_move_down" },
|
||||
|
||||
{ keys = ["c", "d"], command = ":cd " },
|
||||
{ keys = ["d", "d"], command = "cut_files" },
|
||||
{ keys = ["y", "y"], command = "copy_files" },
|
||||
{ keys = ["y", "n"], command = "copy_filename" },
|
||||
{ keys = ["y", "."], command = "copy_filename_without_extension" },
|
||||
{ keys = ["y", "p"], command = "copy_filepath" },
|
||||
{ keys = ["y", "a"], command = "copy_filepath --all-selected=true" },
|
||||
{ keys = ["y", "d"], command = "copy_dirpath" },
|
||||
|
||||
{ keys = ["p", "l"], command = "symlink_files --relative=false" },
|
||||
{ keys = ["p", "L"], command = "symlink_files --relative=true" },
|
||||
|
||||
{ keys = ["delete"], command = "delete_files" },
|
||||
{ keys = ["d", "D"], command = "delete_files" },
|
||||
|
||||
{ keys = ["p", "p"], command = "paste_files" },
|
||||
{ keys = ["p", "o"], command = "paste_files --overwrite=true" },
|
||||
|
||||
{ keys = ["a"], command = "rename_append" },
|
||||
{ keys = ["A"], command = "rename_prepend" },
|
||||
|
||||
{ keys = ["f", "t"], command = ":touch " },
|
||||
|
||||
{ keys = [" "], command = "select --toggle=true" },
|
||||
{ keys = ["t"], command = "select --all=true --toggle=true" },
|
||||
{ keys = ["V"], command = "toggle_visual" },
|
||||
|
||||
{ keys = ["w"], command = "show_tasks --exit-key=w" },
|
||||
{ keys = ["b", "b"], command = "bulk_rename" },
|
||||
{ keys = ["="], command = "set_mode" },
|
||||
|
||||
{ keys = [":"], command = ":" },
|
||||
{ keys = [";"], command = ":" },
|
||||
|
||||
{ keys = ["'"], command = ":shell " },
|
||||
{ keys = ["m", "k"], command = ":mkdir " },
|
||||
{ keys = ["c", "w"], command = ":rename " },
|
||||
|
||||
{ keys = ["/"], command = ":search " },
|
||||
{ keys = ["|"], command = ":search_inc " },
|
||||
{ keys = ["\\"], command = ":search_glob " },
|
||||
{ keys = ["S"], command = "search_fzf" },
|
||||
{ keys = ["C"], command = "subdir_fzf" },
|
||||
|
||||
{ keys = ["n"], command = "search_next" },
|
||||
{ keys = ["N"], command = "search_prev" },
|
||||
|
||||
{ keys = ["s", "r"], command = "sort reverse" },
|
||||
{ keys = ["s", "l"], command = "sort lexical" },
|
||||
{ keys = ["s", "m"], command = "sort mtime" },
|
||||
{ keys = ["s", "n"], command = "sort natural" },
|
||||
{ keys = ["s", "s"], command = "sort size" },
|
||||
{ keys = ["s", "e"], command = "sort ext" },
|
||||
|
||||
{ keys = ["m", "s"], command = "linemode size" },
|
||||
{ keys = ["m", "m"], command = "linemode mtime" },
|
||||
{ keys = ["m", "M"], command = "linemode size | mtime" },
|
||||
{ keys = ["m", "u"], command = "linemode user" },
|
||||
{ keys = ["m", "U"], command = "linemode user | group" },
|
||||
{ keys = ["m", "p"], command = "linemode perm" },
|
||||
|
||||
{ keys = ["g", "r"], command = "cd /" },
|
||||
{ keys = ["g", "c"], command = "cd ~/.config" },
|
||||
{ keys = ["g", "d"], command = "cd ~/Downloads" },
|
||||
{ keys = ["g", "e"], command = "cd /etc" },
|
||||
{ keys = ["g", "h"], command = "cd ~/" },
|
||||
{ keys = ["?"], command = "help" },
|
||||
]
|
||||
|
||||
[task_view]
|
||||
|
||||
keymap = [
|
||||
# arrow keys
|
||||
{ keys = ["arrow_up"], command = "cursor_move_up" },
|
||||
{ keys = ["arrow_down"], command = "cursor_move_down" },
|
||||
{ keys = ["home"], command = "cursor_move_home" },
|
||||
{ keys = ["end"], command = "cursor_move_end" },
|
||||
|
||||
# vim-like keybindings
|
||||
{ keys = ["j"], command = "cursor_move_down" },
|
||||
{ keys = ["k"], command = "cursor_move_up" },
|
||||
{ keys = ["g", "g"], command = "cursor_move_home" },
|
||||
{ keys = ["G"], command = "cursor_move_end" },
|
||||
|
||||
{ keys = ["w"], command = "show_tasks" },
|
||||
{ keys = ["escape"], command = "show_tasks" },
|
||||
]
|
||||
|
||||
[help_view]
|
||||
|
||||
keymap = [
|
||||
# arrow keys
|
||||
{ keys = ["arrow_up"], command = "cursor_move_up" },
|
||||
{ keys = ["arrow_down"], command = "cursor_move_down" },
|
||||
{ keys = ["home"], command = "cursor_move_home" },
|
||||
{ keys = ["end"], command = "cursor_move_end" },
|
||||
|
||||
# vim-like keybindings
|
||||
{ keys = ["j"], command = "cursor_move_down" },
|
||||
{ keys = ["k"], command = "cursor_move_up" },
|
||||
{ keys = ["g", "g"], command = "cursor_move_home" },
|
||||
{ keys = ["G"], command = "cursor_move_end" },
|
||||
|
||||
{ keys = ["w"], command = "show_tasks" },
|
||||
{ keys = ["escape"], command = "show_tasks" },
|
||||
]
|
||||
229
config/joshuto/mimetype.toml
Normal file
229
config/joshuto/mimetype.toml
Normal file
@@ -0,0 +1,229 @@
|
||||
[class]
|
||||
audio_default = [
|
||||
{ command = "mpv", args = [
|
||||
"--",
|
||||
] },
|
||||
{ command = "mediainfo", confirm_exit = true },
|
||||
]
|
||||
|
||||
image_default = [
|
||||
{ command = "qimgv", args = [
|
||||
"--",
|
||||
], fork = true, silent = true },
|
||||
{ command = "krita", args = [
|
||||
"--",
|
||||
], fork = true, silent = true },
|
||||
{ command = "exiftool", confirm_exit = true },
|
||||
{ command = "swappy", args = [
|
||||
"-f",
|
||||
], fork = true },
|
||||
]
|
||||
|
||||
video_default = [
|
||||
{ command = "mpv", args = [
|
||||
"--",
|
||||
], fork = true, silent = true },
|
||||
{ command = "mediainfo", confirm_exit = true },
|
||||
{ command = "mpv", args = [
|
||||
"--mute",
|
||||
"on",
|
||||
"--",
|
||||
], fork = true, silent = true },
|
||||
]
|
||||
|
||||
text_default = [
|
||||
{ command = "micro" },
|
||||
{ command = "gedit", fork = true, silent = true },
|
||||
{ command = "bat", args = [
|
||||
"--paging=always",
|
||||
] },
|
||||
]
|
||||
|
||||
reader_default = [{ command = "evince", fork = true, silent = true }]
|
||||
|
||||
libreoffice_default = [{ command = "libreoffice", fork = true, silent = true }]
|
||||
|
||||
[extension]
|
||||
|
||||
## image formats
|
||||
avif.inherit = "image_default"
|
||||
bmp.inherit = "image_default"
|
||||
gif.inherit = "image_default"
|
||||
heic.inherit = "image_default"
|
||||
jpeg.inherit = "image_default"
|
||||
jpe.inherit = "image_default"
|
||||
jpg.inherit = "image_default"
|
||||
pgm.inherit = "image_default"
|
||||
png.inherit = "image_default"
|
||||
ppm.inherit = "image_default"
|
||||
webp.inherit = "image_default"
|
||||
|
||||
svg.app_list = [
|
||||
{ command = "inkview", fork = true, silent = true },
|
||||
{ command = "inkscape", fork = true, silent = true },
|
||||
]
|
||||
tiff.app_list = [
|
||||
{ command = "qimgv", fork = true, silent = true },
|
||||
{ command = "krita", fork = true, silent = true },
|
||||
]
|
||||
|
||||
## audio formats
|
||||
flac.inherit = "audio_default"
|
||||
m4a.inherit = "audio_default"
|
||||
mp3.inherit = "audio_default"
|
||||
ogg.inherit = "audio_default"
|
||||
wav.inherit = "audio_default"
|
||||
|
||||
## video formats
|
||||
avi.inherit = "video_default"
|
||||
av1.inherit = "video_default"
|
||||
flv.inherit = "video_default"
|
||||
mkv.inherit = "video_default"
|
||||
m4v.inherit = "video_default"
|
||||
mov.inherit = "video_default"
|
||||
mp4.inherit = "video_default"
|
||||
ts.inherit = "video_default"
|
||||
webm.inherit = "video_default"
|
||||
wmv.inherit = "video_default"
|
||||
|
||||
## text formats
|
||||
build.inherit = "text_default"
|
||||
c.inherit = "text_default"
|
||||
cmake.inherit = "text_default"
|
||||
conf.inherit = "text_default"
|
||||
cpp.inherit = "text_default"
|
||||
css.inherit = "text_default"
|
||||
csv.inherit = "text_default"
|
||||
cu.inherit = "text_default"
|
||||
ebuild.inherit = "text_default"
|
||||
eex.inherit = "text_default"
|
||||
env.inherit = "text_default"
|
||||
ex.inherit = "text_default"
|
||||
exs.inherit = "text_default"
|
||||
go.inherit = "text_default"
|
||||
h.inherit = "text_default"
|
||||
hpp.inherit = "text_default"
|
||||
hs.inherit = "text_default"
|
||||
html.inherit = "text_default"
|
||||
ini.inherit = "text_default"
|
||||
java.inherit = "text_default"
|
||||
js.inherit = "text_default"
|
||||
json.inherit = "text_default"
|
||||
kt.inherit = "text_default"
|
||||
lua.inherit = "text_default"
|
||||
log.inherit = "text_default"
|
||||
md.inherit = "text_default"
|
||||
micro.inherit = "text_default"
|
||||
ninja.inherit = "text_default"
|
||||
py.inherit = "text_default"
|
||||
rkt.inherit = "text_default"
|
||||
rs.inherit = "text_default"
|
||||
scss.inherit = "text_default"
|
||||
sh.inherit = "text_default"
|
||||
srt.inherit = "text_default"
|
||||
svelte.inherit = "text_default"
|
||||
toml.inherit = "text_default"
|
||||
tsx.inherit = "text_default"
|
||||
txt.inherit = "text_default"
|
||||
vim.inherit = "text_default"
|
||||
xml.inherit = "text_default"
|
||||
yaml.inherit = "text_default"
|
||||
yml.inherit = "text_default"
|
||||
|
||||
# archive formats
|
||||
7z.app_list = [
|
||||
{ command = "7z", args = [
|
||||
"x",
|
||||
], confirm_exit = true },
|
||||
{ command = "file-roller", fork = true, silent = true },
|
||||
]
|
||||
bz2.app_list = [
|
||||
{ command = "tar", args = [
|
||||
"-xvjf",
|
||||
], confirm_exit = true },
|
||||
{ command = "file-roller", fork = true, silent = true },
|
||||
]
|
||||
gz.app_list = [
|
||||
{ command = "tar", args = [
|
||||
"-xvzf",
|
||||
], confirm_exit = true },
|
||||
{ command = "file-roller", fork = true, silent = true },
|
||||
]
|
||||
tar.app_list = [
|
||||
{ command = "tar", args = [
|
||||
"-xvf",
|
||||
], confirm_exit = true },
|
||||
{ command = "file-roller", fork = true, silent = true },
|
||||
]
|
||||
tgz.app_list = [
|
||||
{ command = "tar", args = [
|
||||
"-xvzf",
|
||||
], confirm_exit = true },
|
||||
{ command = "file-roller", fork = true, silent = true },
|
||||
]
|
||||
rar.app_list = [
|
||||
{ command = "unrar", args = [
|
||||
"x",
|
||||
], confirm_exit = true },
|
||||
{ command = "file-roller", fork = true, silent = true },
|
||||
]
|
||||
xz.app_list = [
|
||||
{ command = "tar", args = [
|
||||
"-xvJf",
|
||||
], confirm_exit = true },
|
||||
{ command = "file-roller", fork = true, silent = true },
|
||||
]
|
||||
zip.app_list = [
|
||||
{ command = "unzip", confirm_exit = true },
|
||||
{ command = "file-roller", fork = true, silent = true },
|
||||
]
|
||||
|
||||
# misc formats
|
||||
aup.app_list = [{ command = "audacity", fork = true, silent = true }]
|
||||
|
||||
m3u.app_list = [
|
||||
{ command = "micro" },
|
||||
{ command = "mpv" },
|
||||
{ command = "gedit", fork = true, silent = true },
|
||||
{ command = "bat", confirm_exit = true },
|
||||
]
|
||||
|
||||
odt.inherit = "libreoffice_default"
|
||||
odf.inherit = "libreoffice_default"
|
||||
ods.inherit = "libreoffice_default"
|
||||
odp.inherit = "libreoffice_default"
|
||||
|
||||
doc.inherit = "libreoffice_default"
|
||||
docx.inherit = "libreoffice_default"
|
||||
xls.inherit = "libreoffice_default"
|
||||
xlsx.inherit = "libreoffice_default"
|
||||
ppt.inherit = "libreoffice_default"
|
||||
pptx.inherit = "libreoffice_default"
|
||||
|
||||
pdf.inherit = "reader_default"
|
||||
|
||||
kra.app_list = [{ command = "krita", fork = true, silent = true }]
|
||||
kdenlive.app_list = [{ command = "kdenlive", fork = true, silent = true }]
|
||||
|
||||
tex.app_list = [
|
||||
{ command = "micro" },
|
||||
{ command = "gedit", fork = true, silent = true },
|
||||
{ command = "bat", confirm_exit = true },
|
||||
{ command = "pdflatex" },
|
||||
]
|
||||
|
||||
torrent.app_list = [{ command = "transmission-gtk" }]
|
||||
|
||||
[mimetype]
|
||||
|
||||
# application/octet-stream
|
||||
[mimetype.application.subtype.octet-stream]
|
||||
inherit = "video_default"
|
||||
|
||||
# text/*
|
||||
[mimetype.text]
|
||||
inherit = "text_default"
|
||||
|
||||
# text/*
|
||||
[mimetype.video]
|
||||
inherit = "video_default"
|
||||
111
config/joshuto/theme.toml
Normal file
111
config/joshuto/theme.toml
Normal file
@@ -0,0 +1,111 @@
|
||||
##########################################
|
||||
## Tabs
|
||||
##########################################
|
||||
|
||||
# Inactive tabs
|
||||
[tabs.inactive]
|
||||
|
||||
# Active tabs
|
||||
[tabs.active]
|
||||
invert = true
|
||||
|
||||
##########################################
|
||||
## File List - Selections
|
||||
##########################################
|
||||
|
||||
# Selected files (standard selection)
|
||||
[selection]
|
||||
fg = "light_yellow"
|
||||
bold = true
|
||||
|
||||
# Files selected in current visual mode
|
||||
[visual_mode_selection]
|
||||
fg = "light_red"
|
||||
bold = true
|
||||
|
||||
[selection.prefix]
|
||||
prefix = " "
|
||||
size = 2
|
||||
|
||||
##########################################
|
||||
## File List - System File Types
|
||||
##########################################
|
||||
|
||||
# Basic style, used for regular files (and also device files and FIFOs)
|
||||
[regular]
|
||||
fg = "white"
|
||||
|
||||
# For directories
|
||||
[directory]
|
||||
fg = "light_blue"
|
||||
bold = true
|
||||
|
||||
# For symbolic links
|
||||
[link]
|
||||
fg = "cyan"
|
||||
bold = true
|
||||
|
||||
# For socket files
|
||||
[socket]
|
||||
fg = "light_magenta"
|
||||
bold = true
|
||||
|
||||
##########################################
|
||||
## File List - Exceptional Files
|
||||
##########################################
|
||||
|
||||
# Files marked as executable
|
||||
[executable]
|
||||
fg = "light_green"
|
||||
bold = true
|
||||
|
||||
# Invalid symbolic links (pointing to non-existing target)
|
||||
[link_invalid]
|
||||
fg = "red"
|
||||
bold = true
|
||||
|
||||
##########################################
|
||||
## File list - Override style by extension
|
||||
##########################################
|
||||
# This sections allows to override the basic
|
||||
# style with a specific style for the file's
|
||||
# extension.
|
||||
|
||||
[ext]
|
||||
|
||||
bmp.fg = "yellow"
|
||||
gif.fg = "yellow"
|
||||
heic.fg = "yellow"
|
||||
jpg.fg = "yellow"
|
||||
jpeg.fg = "yellow"
|
||||
pgm.fg = "yellow"
|
||||
png.fg = "yellow"
|
||||
ppm.fg = "yellow"
|
||||
svg.fg = "yellow"
|
||||
|
||||
wav.fg = "magenta"
|
||||
flac.fg = "magenta"
|
||||
mp3.fg = "magenta"
|
||||
amr.fg = "magenta"
|
||||
|
||||
avi.fg = "magenta"
|
||||
flv.fg = "magenta"
|
||||
m3u.fg = "magenta"
|
||||
m4a.fg = "magenta"
|
||||
m4v.fg = "magenta"
|
||||
mkv.fg = "magenta"
|
||||
mov.fg = "magenta"
|
||||
mp4.fg = "magenta"
|
||||
mpg.fg = "magenta"
|
||||
rmvb.fg = "magenta"
|
||||
webm.fg = "magenta"
|
||||
wmv.fg = "magenta"
|
||||
|
||||
7z.fg = "red"
|
||||
bz2.fg = "red"
|
||||
gz.fg = "red"
|
||||
rar.fg = "red"
|
||||
tar.fg = "red"
|
||||
tgz.fg = "red"
|
||||
xz.fg = "red"
|
||||
zip.fg = "red"
|
||||
4
config/lf/cleaner
Executable file
4
config/lf/cleaner
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
if [ -n "$FIFO_UEBERZUG" ]; then
|
||||
printf '{"action": "remove", "identifier": "PREVIEW"}\n' >"$FIFO_UEBERZUG"
|
||||
fi
|
||||
359
config/lf/icons
Normal file
359
config/lf/icons
Normal file
@@ -0,0 +1,359 @@
|
||||
# vim:ft=conf
|
||||
|
||||
# These examples require Nerd Fonts or a compatible font to be used.
|
||||
# See https://www.nerdfonts.com for more information.
|
||||
|
||||
# default values from lf (with matching order)
|
||||
# ln l # LINK
|
||||
# or l # ORPHAN
|
||||
# tw t # STICKY_OTHER_WRITABLE
|
||||
# ow d # OTHER_WRITABLE
|
||||
# st t # STICKY
|
||||
# di d # DIR
|
||||
# pi p # FIFO
|
||||
# so s # SOCK
|
||||
# bd b # BLK
|
||||
# cd c # CHR
|
||||
# su u # SETUID
|
||||
# sg g # SETGID
|
||||
# ex x # EXEC
|
||||
# fi - # FILE
|
||||
|
||||
# file types (with matching order)
|
||||
ln # LINK
|
||||
or # ORPHAN
|
||||
tw t # STICKY_OTHER_WRITABLE
|
||||
ow # OTHER_WRITABLE
|
||||
st t # STICKY
|
||||
di # DIR
|
||||
pi p # FIFO
|
||||
so s # SOCK
|
||||
bd b # BLK
|
||||
cd c # CHR
|
||||
su u # SETUID
|
||||
sg g # SETGID
|
||||
ex # EXEC
|
||||
fi # FILE
|
||||
|
||||
# file extensions (vim-devicons)
|
||||
*.styl
|
||||
*.sass
|
||||
*.scss
|
||||
*.htm
|
||||
*.html
|
||||
*.slim
|
||||
*.haml
|
||||
*.ejs
|
||||
*.css
|
||||
*.less
|
||||
*.md
|
||||
*.mdx
|
||||
*.markdown
|
||||
*.rmd
|
||||
*.json
|
||||
*.webmanifest
|
||||
*.js
|
||||
*.mjs
|
||||
*.jsx
|
||||
*.rb
|
||||
*.gemspec
|
||||
*.rake
|
||||
*.php
|
||||
*.py
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
*.coffee
|
||||
*.mustache
|
||||
*.hbs
|
||||
*.conf
|
||||
*.ini
|
||||
*.yml
|
||||
*.yaml
|
||||
*.toml
|
||||
*.bat
|
||||
*.mk
|
||||
*.jpg
|
||||
*.jpeg
|
||||
*.bmp
|
||||
*.png
|
||||
*.webp
|
||||
*.gif
|
||||
*.ico
|
||||
*.twig
|
||||
*.cpp
|
||||
*.c++
|
||||
*.cxx
|
||||
*.cc
|
||||
*.cp
|
||||
*.c
|
||||
*.cs
|
||||
*.h
|
||||
*.hh
|
||||
*.hpp
|
||||
*.hxx
|
||||
*.hs
|
||||
*.lhs
|
||||
*.nix
|
||||
*.lua
|
||||
*.java
|
||||
*.sh
|
||||
*.fish
|
||||
*.bash
|
||||
*.zsh
|
||||
*.ksh
|
||||
*.csh
|
||||
*.awk
|
||||
*.ps1
|
||||
*.ml λ
|
||||
*.mli λ
|
||||
*.diff
|
||||
*.db
|
||||
*.sql
|
||||
*.dump
|
||||
*.clj
|
||||
*.cljc
|
||||
*.cljs
|
||||
*.edn
|
||||
*.scala
|
||||
*.go
|
||||
*.dart
|
||||
*.xul
|
||||
*.sln
|
||||
*.suo
|
||||
*.pl
|
||||
*.pm
|
||||
*.t
|
||||
*.rss
|
||||
'*.f#'
|
||||
*.fsscript
|
||||
*.fsx
|
||||
*.fs
|
||||
*.fsi
|
||||
*.rs
|
||||
*.rlib
|
||||
*.d
|
||||
*.erl
|
||||
*.hrl
|
||||
*.ex
|
||||
*.exs
|
||||
*.eex
|
||||
*.leex
|
||||
*.heex
|
||||
*.vim
|
||||
*.ai
|
||||
*.psd
|
||||
*.psb
|
||||
*.ts
|
||||
*.tsx
|
||||
*.jl
|
||||
*.pp
|
||||
*.vue ﵂
|
||||
*.elm
|
||||
*.swift
|
||||
*.xcplayground
|
||||
*.tex ﭨ
|
||||
*.r ﳒ
|
||||
*.rproj 鉶
|
||||
*.sol ﲹ
|
||||
*.pem
|
||||
|
||||
# file names (vim-devicons) (case-insensitive not supported in lf)
|
||||
*gruntfile.coffee
|
||||
*gruntfile.js
|
||||
*gruntfile.ls
|
||||
*gulpfile.coffee
|
||||
*gulpfile.js
|
||||
*gulpfile.ls
|
||||
*mix.lock
|
||||
*dropbox
|
||||
*.ds_store
|
||||
*.gitconfig
|
||||
*.gitignore
|
||||
*.gitattributes
|
||||
*.gitlab-ci.yml
|
||||
*.bashrc
|
||||
*.zshrc
|
||||
*.zshenv
|
||||
*.zprofile
|
||||
*.vimrc
|
||||
*.gvimrc
|
||||
*_vimrc
|
||||
*_gvimrc
|
||||
*.bashprofile
|
||||
*favicon.ico
|
||||
*license
|
||||
*node_modules
|
||||
*react.jsx
|
||||
*procfile
|
||||
*dockerfile
|
||||
*docker-compose.yml
|
||||
*rakefile
|
||||
*config.ru
|
||||
*gemfile
|
||||
*makefile
|
||||
*cmakelists.txt
|
||||
*robots.txt ﮧ
|
||||
|
||||
# file names (case-sensitive adaptations)
|
||||
*Gruntfile.coffee
|
||||
*Gruntfile.js
|
||||
*Gruntfile.ls
|
||||
*Gulpfile.coffee
|
||||
*Gulpfile.js
|
||||
*Gulpfile.ls
|
||||
*Dropbox
|
||||
*.DS_Store
|
||||
*LICENSE
|
||||
*React.jsx
|
||||
*Procfile
|
||||
*Dockerfile
|
||||
*Docker-compose.yml
|
||||
*Rakefile
|
||||
*Gemfile
|
||||
*Makefile
|
||||
*CMakeLists.txt
|
||||
|
||||
# file patterns (vim-devicons) (patterns not supported in lf)
|
||||
# .*jquery.*\.js$
|
||||
# .*angular.*\.js$
|
||||
# .*backbone.*\.js$
|
||||
# .*require.*\.js$
|
||||
# .*materialize.*\.js$
|
||||
# .*materialize.*\.css$
|
||||
# .*mootools.*\.js$
|
||||
# .*vimrc.*
|
||||
# Vagrantfile$
|
||||
|
||||
# file patterns (file name adaptations)
|
||||
*jquery.min.js
|
||||
*angular.min.js
|
||||
*backbone.min.js
|
||||
*require.min.js
|
||||
*materialize.min.js
|
||||
*materialize.min.css
|
||||
*mootools.min.js
|
||||
*vimrc
|
||||
Vagrantfile
|
||||
|
||||
# archives or compressed (extensions from dircolors defaults)
|
||||
*.tar
|
||||
*.tgz
|
||||
*.arc
|
||||
*.arj
|
||||
*.taz
|
||||
*.lha
|
||||
*.lz4
|
||||
*.lzh
|
||||
*.lzma
|
||||
*.tlz
|
||||
*.txz
|
||||
*.tzo
|
||||
*.t7z
|
||||
*.zip
|
||||
*.z
|
||||
*.dz
|
||||
*.gz
|
||||
*.lrz
|
||||
*.lz
|
||||
*.lzo
|
||||
*.xz
|
||||
*.zst
|
||||
*.tzst
|
||||
*.bz2
|
||||
*.bz
|
||||
*.tbz
|
||||
*.tbz2
|
||||
*.tz
|
||||
*.deb
|
||||
*.rpm
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
*.sar
|
||||
*.rar
|
||||
*.alz
|
||||
*.ace
|
||||
*.zoo
|
||||
*.cpio
|
||||
*.7z
|
||||
*.rz
|
||||
*.cab
|
||||
*.wim
|
||||
*.swm
|
||||
*.dwm
|
||||
*.esd
|
||||
|
||||
# image formats (extensions from dircolors defaults)
|
||||
*.jpg
|
||||
*.jpeg
|
||||
*.mjpg
|
||||
*.mjpeg
|
||||
*.bmp
|
||||
*.pbm
|
||||
*.pgm
|
||||
*.ppm
|
||||
*.tga
|
||||
*.xbm
|
||||
*.xpm
|
||||
*.tif
|
||||
*.tiff
|
||||
*.png
|
||||
*.svg
|
||||
*.svgz
|
||||
*.pcx
|
||||
*.m2v
|
||||
*.ogm
|
||||
*.nuv
|
||||
*.rm
|
||||
*.rmvb
|
||||
*.flc
|
||||
*.fli
|
||||
*.gl
|
||||
*.dl
|
||||
*.xcf
|
||||
*.xwd
|
||||
*.cgm
|
||||
*.emf
|
||||
*.ogx
|
||||
|
||||
# video formats
|
||||
*.mkv
|
||||
*.asf
|
||||
*.yuv
|
||||
*.avi
|
||||
*.gif
|
||||
*.mpg
|
||||
*.mpeg
|
||||
*.qt
|
||||
*.mng
|
||||
*.ogv
|
||||
*.webm
|
||||
*.vob
|
||||
*.flv
|
||||
*.mov
|
||||
*.wmv
|
||||
*.mp4
|
||||
*.m4v
|
||||
*.mp4v
|
||||
|
||||
# audio formats (extensions from dircolors defaults)
|
||||
*.aac
|
||||
*.au
|
||||
*.flac
|
||||
*.m4a
|
||||
*.mid
|
||||
*.midi
|
||||
*.mka
|
||||
*.mp3
|
||||
*.mpc
|
||||
*.ogg
|
||||
*.ra
|
||||
*.wav
|
||||
*.oga
|
||||
*.opus
|
||||
*.spx
|
||||
*.xspf
|
||||
|
||||
# other formats
|
||||
*.pdf
|
||||
152
config/lf/lfrc
Executable file
152
config/lf/lfrc
Executable file
@@ -0,0 +1,152 @@
|
||||
#!/bin/sh
|
||||
# Basic Settings
|
||||
set autoquit true
|
||||
set cleaner "~/.config/lf/cleaner"
|
||||
set drawbox true
|
||||
set hidden true
|
||||
set hiddenfiles ".*:*.aux:*.log:*.bbl:*.bcf:*.blg:*.run.xml"
|
||||
set icons true
|
||||
set ifs "\n"
|
||||
set ignorecase true
|
||||
set info size
|
||||
set period 1
|
||||
set previewer "~/.config/lf/preview"
|
||||
set ratios 1:2:3
|
||||
set scrolloff 10
|
||||
set shellopts '-eu'
|
||||
|
||||
# Custom Functions
|
||||
|
||||
cmd trash ${{
|
||||
trash-put $f
|
||||
}}
|
||||
|
||||
cmd moveto ${{
|
||||
clear; tput cup $(($(tput lines)/3)); tput bold
|
||||
set -f
|
||||
clear; echo "Move to where?"
|
||||
dest="$(sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' $XDG_CONFIG_HOME/shell/bm-dirs | sk | sed 's|~|$HOME|')" &&
|
||||
for x in $fx; do
|
||||
eval mv -iv \"$x\" \"$dest\"
|
||||
done &&
|
||||
notify-send "🚚 File(s) moved." "File(s) moved to $dest."
|
||||
}}
|
||||
|
||||
|
||||
cmd copyto ${{
|
||||
clear; tput cup $(($(tput lines)/3)); tput bold
|
||||
set -f
|
||||
clear; echo "Copy to where?"
|
||||
dest="$(sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' $XDG_CONFIG_HOME/shell/bm-dirs | sk | sed 's|~|$HOME|')" &&
|
||||
for x in $fx; do
|
||||
eval cp -ivr \"$x\" \"$dest\"
|
||||
done &&
|
||||
notify-send "📋 File(s) copied." "File(s) copies to $dest."
|
||||
}}
|
||||
|
||||
|
||||
cmd open ${{
|
||||
case $(file --mime-type "$(readlink -f $f)" -b) in
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet) localc $fx ;;
|
||||
image/vnd.djvu|application/pdf|application/octet-stream|application/postscript) setsid -f zathura $fx >/dev/null 2>&1 ;;
|
||||
text/*|application/json|inode/x-empty|application/x-subrip) $EDITOR $fx ;;
|
||||
image/x-xcf) setsid -f gimp $f >/dev/null 2>&1 ;;
|
||||
image/svg+xml) display -- $f ;;
|
||||
image/*) rotdir $f | grep -i "\.\(png\|jpg\|jpeg\|gif\|webp\|tif\|ico\)\(_large\)*$" |
|
||||
setsid -f nsxiv -aio 2>/dev/null | while read -r file; do
|
||||
[ -z "$file" ] && continue
|
||||
lf -remote "send select \"$file\""
|
||||
lf -remote "send toggle"
|
||||
done &
|
||||
;;
|
||||
audio/*|video/x-ms-asf) mpv --audio-display=no $f ;;
|
||||
video/*) setsid -f mpv --speed=2 $f -quiet >/dev/null 2>&1 ;;
|
||||
application/pdf|application/vnd.djvu|application/epub*) setsid -f zathura $fx >/dev/null 2>&1 ;;
|
||||
application/pgp-encrypted) $EDITOR $fx ;;
|
||||
# application/vnd.openxmlformats-officedocument.wordprocessingml.document|application/vnd.oasis.opendocument.text) setsid -f lowriter $fx >/dev/null 2>&1 ;;
|
||||
# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet|application/octet-stream|application/vnd.oasis.opendocument.spreadsheet|application/vnd.oasis.opendocument.spreadsheet-template) setsid -f localc $fx >/dev/null 2>&1 ;;
|
||||
# application/vnd.openxmlformats-officedocument.presentationml.presentation|application/vnd.oasis.opendocument.presentation-template|application/vnd.oasis.opendocument.presentation|application/vnd.ms-powerpoint) setsid -f loimpress $fx >/dev/null 2>&1 ;;
|
||||
# application/vnd.oasis.opendocument.graphics|application/vnd.oasis.opendocument.graphics-template) setsid -f lodraw $fx >/dev/null 2>&1 ;;
|
||||
# application/vnd.oasis.opendocument.formula) setsid -f lomath $fx >/dev/null 2>&1 ;;
|
||||
# application/vnd.oasis.opendocument.database) setsid -f lobase $fx >/dev/null 2>&1 ;;
|
||||
*) for f in $fx; do setsid -f $OPENER $f >/dev/null 2>&1; done ;;
|
||||
esac
|
||||
}}
|
||||
|
||||
|
||||
cmd extract ${{
|
||||
clear; tput cup $(($(tput lines)/3)); tput bold
|
||||
set -f
|
||||
printf "%s\n\t" "$fx"
|
||||
printf "extract?[y/N]"
|
||||
read answer
|
||||
[ $answer = "y" ] && aunpack $fx
|
||||
}}
|
||||
|
||||
|
||||
cmd unarchive ${{
|
||||
case "$f" in
|
||||
*.zip) unzip "$f" ;;
|
||||
*.tar.gz) tar -xzvf "$f" ;;
|
||||
*.tar.bz2) tar -xjvf "$f" ;;
|
||||
*.tar) tar -xvf "$f" ;;
|
||||
*) echo "Unsupported format" ;
|
||||
esac
|
||||
}}
|
||||
|
||||
|
||||
cmd mkdir $mkdir -p "$(echo $* | tr ' ' '\ ')"
|
||||
cmd mkfile $touch "$(echo $* | tr ' ' '\ ')"
|
||||
cmd setbg "$1"
|
||||
|
||||
# Bindings
|
||||
# Remove some defaults
|
||||
map "'"
|
||||
map '"'
|
||||
map c
|
||||
map d
|
||||
map m
|
||||
map n
|
||||
map o
|
||||
map p
|
||||
|
||||
map au unarchive
|
||||
|
||||
# Basic Functions
|
||||
map . set hidden!
|
||||
map <c-f> $lf -remote "send $id select \"$(sk)\""
|
||||
map <c-h> set hidden!
|
||||
map <c-l> clear
|
||||
map <enter> open
|
||||
map <enter> shell
|
||||
map <f-2> rename
|
||||
map B $vidir # bulk rename
|
||||
map D delete
|
||||
map E extract
|
||||
map J $lf -remote "send $id cd $(sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' $XDG_CONFIG_HOME/shell/bm-dirs | sk)"
|
||||
map O $mimeopen --ask "$f"
|
||||
map P paste
|
||||
map Y $printf "%s" "$fx" | xclip -selection clipboard
|
||||
map bg $setbg $f
|
||||
map cp copyto
|
||||
map dd cut
|
||||
map e $nvim "$f"
|
||||
map md push :mkdir<space>
|
||||
map mf push :mkfile<space>
|
||||
map mv moveto
|
||||
map nN $spacefm -t "${PWD}" & disown >/dev/null 2>&1
|
||||
map nn $setsid -f $TERMINAL >/dev/null 2>&1
|
||||
map o &mimeopen "$f"
|
||||
|
||||
cmd ripdrag-all %ripdrag --all --and-exit $fx
|
||||
cmd ripdrag-individual %ripdrag --keep --target $fx
|
||||
cmd ripdrag-target %ripdrag --target
|
||||
|
||||
# ripdrag Mapping
|
||||
map da ripdrag-all
|
||||
map di ripdrag-individual
|
||||
#map dt ripdrag-target
|
||||
|
||||
|
||||
# Source Bookmarks
|
||||
source "~/.config/lf/shortcutrc"
|
||||
71
config/lf/preview
Normal file
71
config/lf/preview
Normal file
@@ -0,0 +1,71 @@
|
||||
#!/bin/sh
|
||||
|
||||
# File preview handler for lf.
|
||||
|
||||
set -C -f
|
||||
IFS="$(printf '%b_' '\n')"
|
||||
IFS="${IFS%_}"
|
||||
|
||||
# image() {
|
||||
# if [ -f "$1" ] && [ -n "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ] && command -V ueberzug >/dev/null 2>&1; then
|
||||
# printf '{"action": "add", "identifier": "PREVIEW", "x": "%s", "y": "%s", "width": "%s", "height": "%s", "scaler": "contain", "path": "%s"}\n' "$4" "$5" "$(($2 - 1))" "$(($3 - 1))" "$1" >"$FIFO_UEBERZUG"
|
||||
# echo "TRUE"
|
||||
# else
|
||||
# mediainfo "$6"
|
||||
# echo "FALSE"
|
||||
# fi
|
||||
# }
|
||||
|
||||
image() {
|
||||
if [ -n "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ]; then
|
||||
printf '{"action": "add", "identifier": "PREVIEW", "x": "%s", "y": "%s", "width": "%s", "height": "%s", "scaler": "contain", "path": "%s"}\n' "$4" "$5" "$(($2 - 1))" "$(($3 - 1))" "$1" >"$FIFO_UEBERZUG"
|
||||
exit 1
|
||||
else
|
||||
chafa "$1" -s "$4x"
|
||||
fi
|
||||
}
|
||||
|
||||
# Note that the cache file name is a function of file information, meaning if
|
||||
# an image appears in multiple places across the machine, it will not have to
|
||||
# be regenerated once seen.
|
||||
|
||||
case "$(file --dereference --brief --mime-type -- "$1")" in
|
||||
image/svg* | application/illustrator)
|
||||
CACHE="$XDG_CACHE_HOME/lf/thumb.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | sha256sum | cut -d' ' -f1)"
|
||||
[ ! -f "$CACHE.jpg" ] &&
|
||||
convert "$1" "$CACHE.jpg"
|
||||
image "$CACHE.jpg" "$2" "$3" "$4" "$5"
|
||||
;;
|
||||
image/*) image "$1" "$2" "$3" "$4" "$5" "$1" ;;
|
||||
text/html) lynx -width="$4" -display_charset=utf-8 -dump "$1" ;;
|
||||
text/troff) man ./ "$1" | col -b ;;
|
||||
text/markdown) glow -s dark "$1" ;;
|
||||
text/* | */xml | application/json) bat --style=plain --terminal-width "$(($4 - 2))" -f "$1" ;;
|
||||
audio/* | application/octet-stream) mediainfo "$1" || exit 1 ;;
|
||||
video/*)
|
||||
CACHE="$XDG_CACHE_HOME/lf/thumb.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | sha256sum | cut -d' ' -f1)"
|
||||
[ ! -f "$CACHE" ] && ffmpegthumbnailer -i "$1" -o "$CACHE" -s 0
|
||||
image "$CACHE" "$2" "$3" "$4" "$5" "$1"
|
||||
;;
|
||||
*/pdf)
|
||||
CACHE="$XDG_CACHE_HOME/lf/thumb.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | sha256sum | cut -d' ' -f1)"
|
||||
[ ! -f "$CACHE.jpg" ] && pdftoppm -jpeg -f 1 -singlefile "$1" "$CACHE"
|
||||
image "$CACHE.jpg" "$2" "$3" "$4" "$5" "$1"
|
||||
;;
|
||||
*/epub+zip | */mobi*)
|
||||
CACHE="$XDG_CACHE_HOME/lf/thumb.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | sha256sum | cut -d' ' -f1)"
|
||||
[ ! -f "$CACHE.jpg" ] && gnome-epub-thumbnailer "$1" "$CACHE.jpg"
|
||||
image "$CACHE.jpg" "$2" "$3" "$4" "$5" "$1"
|
||||
;;
|
||||
application/*zip) atool --list -- "$1" ;;
|
||||
application/pgp-encrypted) gpg -d -- "$1" ;;
|
||||
application/x-bittorrent) transmission-show "$1" ;;
|
||||
application/x-iso*) iso-info "$1" ;;
|
||||
*msword) catdoc "$1" ;;
|
||||
*openxmlformats-officedocument.wordprocessingml.document) docx2txt "$1" - ;;
|
||||
*opendocument*) odt2txt "$1" ;;
|
||||
*ms-excel | *openxmlformats-officedocument.spreadsheetml.sheet)
|
||||
ssconvert --export-type=Gnumeric_stf:stf_csv "$1" "fd://1" | bat --language=csv
|
||||
;;
|
||||
esac
|
||||
exit 1
|
||||
11
config/lf/shortcutrc
Normal file
11
config/lf/shortcutrc
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
map gD cd ~/Documents
|
||||
map gc cd ~/.config
|
||||
map gd cd ~/Downloads
|
||||
map gl cd ~/.local
|
||||
map gn cd ~/Nextcloud
|
||||
map gp cd ~/Pictures
|
||||
map gr cd ~/repos
|
||||
map gu cd ~/vimwiki/university/2nd-semester/
|
||||
map gv cd ~/Videos
|
||||
map gw cd ~/vimwiki
|
||||
40
config/mimeapps.list
Normal file
40
config/mimeapps.list
Normal file
@@ -0,0 +1,40 @@
|
||||
[Default Applications]
|
||||
|
||||
# xdg-open will use these settings to determine how to open filetypes.
|
||||
# These .desktop entries can also be seen and changed in ~/.local/share/applications/
|
||||
|
||||
application/octet-stream=mpv.desktop
|
||||
application/pdf=pdf.desktop;
|
||||
application/postscript=pdf.desktop;
|
||||
application/rss+xml=rss.desktop
|
||||
application/x-bittorrent=torrent.desktop;
|
||||
audio/mpeg=video.desktop;
|
||||
image/gif=img.desktop;
|
||||
image/gif=img.desktop;
|
||||
image/heic=img.desktop
|
||||
image/heif=img.desktop;
|
||||
image/jpeg=img.desktop;
|
||||
image/jpeg=img.desktop;
|
||||
image/jpg=img.desktop;
|
||||
image/png=img.desktop;
|
||||
image/png=img.desktop;
|
||||
image/svg+xml=org.inkscape.Inkscape.desktop;
|
||||
image/webp=img.desktop;
|
||||
image/x-canon-cr2=img.desktop;
|
||||
inode/directory=file.desktop
|
||||
inode/directory=spacefm.desktop
|
||||
text/html=text.desktop;
|
||||
text/markdown=text.desktop;
|
||||
text/plain=text.desktop;
|
||||
text/plain=text.desktop;
|
||||
text/x-shellscript=text.desktop;
|
||||
video/mp4=video.desktop;
|
||||
video/mpeg=video.desktop;
|
||||
video/ts=video.desktop;
|
||||
video/x-matroska=video.desktop
|
||||
x-scheme-handler/about=librewolf.desktop;
|
||||
x-scheme-handler/http=librewolf.desktop;
|
||||
x-scheme-handler/https=librewolf.desktop;
|
||||
x-scheme-handler/lbry=lbry.desktop
|
||||
x-scheme-handler/magnet=torrent.desktop;
|
||||
x-scheme-handler/mailto=mail.desktop;
|
||||
11
config/mpv/input.conf
Normal file
11
config/mpv/input.conf
Normal file
@@ -0,0 +1,11 @@
|
||||
l seek 5
|
||||
h seek -5
|
||||
L seek 10
|
||||
H seek -10
|
||||
j seek -60
|
||||
k seek 60
|
||||
J seek -90
|
||||
K seek 90
|
||||
S cycle sub
|
||||
WHEEL_UP seek 5
|
||||
WHEEL_DOWN seek -5
|
||||
1
config/mpv/mpv.conf
Normal file
1
config/mpv/mpv.conf
Normal file
@@ -0,0 +1 @@
|
||||
speed=2
|
||||
21
config/nsxiv/exec/image-info
Executable file
21
config/nsxiv/exec/image-info
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Example for $XDG_CONFIG_HOME/nsxiv/exec/image-info
|
||||
# Called by nsxiv(1) whenever an image gets loaded.
|
||||
# The output is displayed in nsxiv's status bar.
|
||||
# Arguments:
|
||||
# $1: path to image file (as provided by the user)
|
||||
# $2: image width
|
||||
# $3: image height
|
||||
# $4: fully resolved path to the image file
|
||||
|
||||
s=" " # field separator
|
||||
|
||||
exec 2>/dev/null
|
||||
|
||||
filename=$(basename -- "$1")
|
||||
filesize=$(du -Hh -- "$1" | cut -f 1)
|
||||
geometry="${2}x${3}"
|
||||
|
||||
echo "${filesize}${s}${geometry}${s}${filename}"
|
||||
|
||||
40
config/nsxiv/exec/key-handler
Executable file
40
config/nsxiv/exec/key-handler
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Example for $XDG_CONFIG_HOME/nsxiv/exec/key-handler
|
||||
# Called by nsxiv(1) after the external prefix key (C-x by default) is pressed.
|
||||
# The next key combo is passed as its first argument. Passed via stdin are the
|
||||
# images to act upon: all marked images, if in thumbnail mode and at least one
|
||||
# image has been marked, otherwise the current image. nsxiv(1) will block until
|
||||
# the handler terminates. It then checks which images have been modified and
|
||||
# reloads them.
|
||||
|
||||
# By default nsxiv(1) will send one image per-line to stdin, however when using
|
||||
# -0 the image list will be NULL separated and the enviornment variable
|
||||
# "$NSXIV_USING_NULL" will be set to 1.
|
||||
|
||||
# The key combo argument has the following form: "[C-][M-][S-]KEY",
|
||||
# where C/M/S indicate Ctrl/Meta(Alt)/Shift modifier states and KEY is the X
|
||||
# keysym as listed in /usr/include/X11/keysymdef.h without the "XK_" prefix.
|
||||
# If KEY has an uppercase equivalent, S-KEY is resolved into it. For instance,
|
||||
# K replaces S-k and Scedilla replaces S-scedilla, but S-Delete is sent as-is.
|
||||
|
||||
rotate() {
|
||||
degree="$1"
|
||||
tr '\n' '\0' | xargs -0 realpath | sort | uniq | while read file; do
|
||||
case "$(file -b -i "$file")" in
|
||||
image/jpeg*) jpegtran -rotate "$degree" -copy all -outfile "$file" "$file" ;;
|
||||
*) mogrify -rotate "$degree" "$file" ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
"C-x") xclip -in -filter | tr '\n' ' ' | xclip -in -selection clipboard ;;
|
||||
"C-c") while read file; do xclip -selection clipboard -target image/png "$file"; done ;;
|
||||
"C-e") while read file; do urxvt -bg "#444" -fg "#eee" -sl 0 -title "$file" -e sh -c "exiv2 pr -q -pa '$file' | less" & done ;;
|
||||
"C-g") tr '\n' '\0' | xargs -0 gimp & ;;
|
||||
"C-r") while read file; do rawtherapee "$file" & done ;;
|
||||
"C-comma") rotate 270 ;;
|
||||
"C-period") rotate 90 ;;
|
||||
"C-slash") rotate 180 ;;
|
||||
esac
|
||||
32
config/nsxiv/exec/nsxiv-url
Executable file
32
config/nsxiv/exec/nsxiv-url
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
cache_dir="${TMPDIR:-/tmp}/nsxiv"
|
||||
|
||||
die() {
|
||||
[ -n "$1" ] && printf '%s\n' "$*" >&2;
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
rm -f -- "$cache_dir"/*
|
||||
}
|
||||
|
||||
get_image() (
|
||||
cd "$cache_dir" && curl -sSLO "$1"
|
||||
)
|
||||
|
||||
### main ###
|
||||
|
||||
[ -z "$1" ] && die "No arguments given"
|
||||
trap cleanup EXIT
|
||||
[ -d "$cache_dir" ] || mkdir -p -- "$cache_dir" || die
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
*://*.*) get_image "$1" ;;
|
||||
*) echo "Invalid url: $1" >&2 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
[ "$(find "$cache_dir" -type f -print | wc -l)" -ne 0 ] &&
|
||||
nsxiv -p "$cache_dir"
|
||||
20
config/nsxiv/exec/thumb-info
Executable file
20
config/nsxiv/exec/thumb-info
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Example for $XDG_CONFIG_HOME/nsxiv/exec/thumb-info
|
||||
# Called by nsxiv(1) whenever the selected thumbnail changes.
|
||||
# The output is displayed in nsxiv's status bar.
|
||||
# Arguments:
|
||||
# $1: path to image file (as provided by the user)
|
||||
# $2: empty
|
||||
# $3: empty
|
||||
# $4: fully resolved path to the image file
|
||||
|
||||
s=" " # field separator
|
||||
|
||||
exec 2>/dev/null
|
||||
|
||||
filename=$(basename -- "$4")
|
||||
filesize=$(du -Hh -- "$4" | cut -f 1)
|
||||
|
||||
echo "${filesize}${s}${filename}"
|
||||
|
||||
27
config/nsxiv/exec/win-title
Executable file
27
config/nsxiv/exec/win-title
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Example for $XDG_CONFIG_HOME/nsxiv/exec/win-title
|
||||
# Called by nsxiv(1) whenever any of the relevant information changes.
|
||||
# The output is set as nsxiv's window title.
|
||||
#
|
||||
# Arguments, "Optional" arguments might be empty:
|
||||
# $1: resolved absolute path of the current file
|
||||
# $2: current file number
|
||||
# $3: total file number
|
||||
# $4: image width (Optional: Disabled on thumbnails mode)
|
||||
# $5: image height (Optional: Disabled on thumbnails mode)
|
||||
# $6: current zoom (Optional: Disabled on thumbnails mode)
|
||||
#
|
||||
# The term file is used rather than image as nsxiv does not
|
||||
# precheck that the input files are valid images. Total file
|
||||
# count may be different from the actual count of valid images.
|
||||
|
||||
exec 2>/dev/null
|
||||
|
||||
filename="${1##*/}"
|
||||
|
||||
if [ -n "$4" ]; then # image mode
|
||||
printf "%s" "nsxiv - ${filename} | ${4}x${5} ${6}% [${2}/${3}]"
|
||||
else
|
||||
printf "%s" "nsxiv - ${filename} [${2}/${3}]"
|
||||
fi
|
||||
22
config/paru.conf
Normal file
22
config/paru.conf
Normal file
@@ -0,0 +1,22 @@
|
||||
# GENERAL OPTIONS
|
||||
#
|
||||
[options]
|
||||
PgpFetch
|
||||
Devel
|
||||
Provides
|
||||
DevelSuffixes = -git -cvs -snv -bzr -darcs -always -hg
|
||||
UpgradeMenu
|
||||
#BottomUp
|
||||
#RemoveMake
|
||||
#SudoLoop
|
||||
#UseAsk
|
||||
#CombineUpgrade
|
||||
#ClearAfter
|
||||
#NewsOnUpgrade
|
||||
|
||||
#
|
||||
# Binary OPTIONS
|
||||
#
|
||||
[bin]
|
||||
FileManager = yazi
|
||||
Sudo = /bin/doas
|
||||
446
config/picom.conf
Normal file
446
config/picom.conf
Normal file
@@ -0,0 +1,446 @@
|
||||
#################################
|
||||
# Shadows #
|
||||
#################################
|
||||
|
||||
|
||||
# Enabled client-side shadows on windows. Note desktop windows
|
||||
# (windows with '_NET_WM_WINDOW_TYPE_DESKTOP') never get shadow,
|
||||
# unless explicitly requested using the wintypes option.
|
||||
#
|
||||
# shadow = false
|
||||
shadow = true;
|
||||
|
||||
# The blur radius for shadows, in pixels. (defaults to 12)
|
||||
# shadow-radius = 12
|
||||
shadow-radius = 7;
|
||||
|
||||
# The opacity of shadows. (0.0 - 1.0, defaults to 0.75)
|
||||
# shadow-opacity = .75
|
||||
|
||||
# The left offset for shadows, in pixels. (defaults to -15)
|
||||
# shadow-offset-x = -15
|
||||
shadow-offset-x = -7;
|
||||
|
||||
# The top offset for shadows, in pixels. (defaults to -15)
|
||||
# shadow-offset-y = -15
|
||||
shadow-offset-y = -7;
|
||||
|
||||
# Avoid drawing shadows on dock/panel windows. This option is deprecated,
|
||||
# you should use the *wintypes* option in your config file instead.
|
||||
#
|
||||
# no-dock-shadow = false
|
||||
|
||||
# Don't draw shadows on drag-and-drop windows. This option is deprecated,
|
||||
# you should use the *wintypes* option in your config file instead.
|
||||
#
|
||||
# no-dnd-shadow = false
|
||||
|
||||
# Red color value of shadow (0.0 - 1.0, defaults to 0).
|
||||
# shadow-red = 0
|
||||
|
||||
# Green color value of shadow (0.0 - 1.0, defaults to 0).
|
||||
# shadow-green = 0
|
||||
|
||||
# Blue color value of shadow (0.0 - 1.0, defaults to 0).
|
||||
# shadow-blue = 0
|
||||
|
||||
# Do not paint shadows on shaped windows. Note shaped windows
|
||||
# here means windows setting its shape through X Shape extension.
|
||||
# Those using ARGB background is beyond our control.
|
||||
# Deprecated, use
|
||||
# shadow-exclude = 'bounding_shaped'
|
||||
# or
|
||||
# shadow-exclude = 'bounding_shaped && !rounded_corners'
|
||||
# instead.
|
||||
#
|
||||
# shadow-ignore-shaped = ''
|
||||
|
||||
# Specify a list of conditions of windows that should have no shadow.
|
||||
#
|
||||
# examples:
|
||||
# shadow-exclude = "n:e:Notification";
|
||||
#
|
||||
# shadow-exclude = []
|
||||
shadow-exclude = [
|
||||
"name = 'Notification'",
|
||||
"class_g = 'Conky'",
|
||||
"class_g ?= 'Notify-osd'",
|
||||
"class_g = 'Cairo-clock'",
|
||||
"_GTK_FRAME_EXTENTS@:c"
|
||||
];
|
||||
|
||||
# Specify a X geometry that describes the region in which shadow should not
|
||||
# be painted in, such as a dock window region. Use
|
||||
# shadow-exclude-reg = "x10+0+0"
|
||||
# for example, if the 10 pixels on the bottom of the screen should not have shadows painted on.
|
||||
#
|
||||
# shadow-exclude-reg = ""
|
||||
|
||||
# Crop shadow of a window fully on a particular Xinerama screen to the screen.
|
||||
# xinerama-shadow-crop = false
|
||||
|
||||
|
||||
#################################
|
||||
# Fading #
|
||||
#################################
|
||||
|
||||
|
||||
# Fade windows in/out when opening/closing and when opacity changes,
|
||||
# unless no-fading-openclose is used.
|
||||
# fading = false
|
||||
fading = false
|
||||
|
||||
# Opacity change between steps while fading in. (0.01 - 1.0, defaults to 0.028)
|
||||
# fade-in-step = 0.028
|
||||
fade-in-step = 0.1;
|
||||
|
||||
# Opacity change between steps while fading out. (0.01 - 1.0, defaults to 0.03)
|
||||
# fade-out-step = 0.03
|
||||
fade-out-step = 0.05;
|
||||
|
||||
# The time between steps in fade step, in milliseconds. (> 0, defaults to 10)
|
||||
# fade-delta = 10
|
||||
|
||||
# Specify a list of conditions of windows that should not be faded.
|
||||
# fade-exclude = []
|
||||
|
||||
# Do not fade on window open/close.
|
||||
# no-fading-openclose = true
|
||||
|
||||
# Do not fade destroyed ARGB windows with WM frame. Workaround of bugs in Openbox, Fluxbox, etc.
|
||||
# no-fading-destroyed-argb = false
|
||||
|
||||
|
||||
#################################
|
||||
# Transparency / Opacity #
|
||||
#################################
|
||||
|
||||
|
||||
# Opacity of inactive windows. (0.1 - 1.0, defaults to 1.0)
|
||||
# inactive-opacity = 1
|
||||
# inactive-opacity = 0.8;
|
||||
|
||||
# Opacity of window titlebars and borders. (0.1 - 1.0, disabled by default)
|
||||
frame-opacity = 1.0
|
||||
# frame-opacity = 0.7;
|
||||
|
||||
# Default opacity for dropdown menus and popup menus. (0.0 - 1.0, defaults to 1.0)
|
||||
# menu-opacity = 1.0
|
||||
|
||||
# Let inactive opacity set by -i override the '_NET_WM_OPACITY' values of windows.
|
||||
# inactive-opacity-override = true
|
||||
inactive-opacity-override = false;
|
||||
|
||||
# Default opacity for active windows. (0.0 - 1.0, defaults to 1.0)
|
||||
# active-opacity = 1.0
|
||||
|
||||
# Dim inactive windows. (0.0 - 1.0, defaults to 0.0)
|
||||
# inactive-dim = 0.0
|
||||
|
||||
# Specify a list of conditions of windows that should always be considered focused.
|
||||
# focus-exclude = []
|
||||
focus-exclude = [ "class_g = 'Cairo-clock'" ];
|
||||
|
||||
# Use fixed inactive dim value, instead of adjusting according to window opacity.
|
||||
# inactive-dim-fixed = 1.0
|
||||
|
||||
# Specify a list of opacity rules, in the format `PERCENT:PATTERN`,
|
||||
# like `50:name *= "Firefox"`. picom-trans is recommended over this.
|
||||
# Note we don't make any guarantee about possible conflicts with other
|
||||
# programs that set '_NET_WM_WINDOW_OPACITY' on frame or client windows.
|
||||
# example:
|
||||
# opacity-rule = [ "80:class_g = 'URxvt'" ];
|
||||
#
|
||||
# opacity-rule = []
|
||||
|
||||
|
||||
#################################
|
||||
# Background-Blurring #
|
||||
#################################
|
||||
|
||||
|
||||
# Parameters for background blurring, see the *BLUR* section for more information.
|
||||
# blur-method =
|
||||
# blur-size = 12
|
||||
#
|
||||
# blur-deviation = false
|
||||
|
||||
# Blur background of semi-transparent / ARGB windows.
|
||||
# Bad in performance, with driver-dependent behavior.
|
||||
# The name of the switch may change without prior notifications.
|
||||
#
|
||||
# blur-background = false
|
||||
|
||||
# Blur background of windows when the window frame is not opaque.
|
||||
# Implies:
|
||||
# blur-background
|
||||
# Bad in performance, with driver-dependent behavior. The name may change.
|
||||
#
|
||||
# blur-background-frame = false
|
||||
|
||||
|
||||
# Use fixed blur strength rather than adjusting according to window opacity.
|
||||
# blur-background-fixed = false
|
||||
|
||||
|
||||
# Specify the blur convolution kernel, with the following format:
|
||||
# example:
|
||||
# blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
|
||||
#
|
||||
# blur-kern = ''
|
||||
blur-kern = "3x3box";
|
||||
|
||||
|
||||
# Exclude conditions for background blur.
|
||||
# blur-background-exclude = []
|
||||
blur-background-exclude = [
|
||||
"window_type = 'dock'",
|
||||
"window_type = 'desktop'",
|
||||
"_GTK_FRAME_EXTENTS@:c"
|
||||
];
|
||||
|
||||
#################################
|
||||
# General Settings #
|
||||
#################################
|
||||
|
||||
# Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers.
|
||||
# daemon = false
|
||||
|
||||
# Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`.
|
||||
# `xrender` is the default one.
|
||||
#
|
||||
backend = "glx";
|
||||
#backend = "xrender";
|
||||
|
||||
# Enable/disable VSync.
|
||||
# vsync = false
|
||||
vsync = true;
|
||||
|
||||
# Enable remote control via D-Bus. See the *D-BUS API* section below for more details.
|
||||
# dbus = false
|
||||
|
||||
# Try to detect WM windows (a non-override-redirect window with no
|
||||
# child that has 'WM_STATE') and mark them as active.
|
||||
#
|
||||
# mark-wmwin-focused = false
|
||||
mark-wmwin-focused = true;
|
||||
|
||||
# Mark override-redirect windows that doesn't have a child window with 'WM_STATE' focused.
|
||||
# mark-ovredir-focused = false
|
||||
mark-ovredir-focused = true;
|
||||
|
||||
# Try to detect windows with rounded corners and don't consider them
|
||||
# shaped windows. The accuracy is not very high, unfortunately.
|
||||
#
|
||||
# detect-rounded-corners = false
|
||||
detect-rounded-corners = true;
|
||||
|
||||
# Detect '_NET_WM_OPACITY' on client windows, useful for window managers
|
||||
# not passing '_NET_WM_OPACITY' of client windows to frame windows.
|
||||
#
|
||||
# detect-client-opacity = false
|
||||
detect-client-opacity = true;
|
||||
|
||||
# Specify refresh rate of the screen. If not specified or 0, picom will
|
||||
# try detecting this with X RandR extension.
|
||||
#
|
||||
|
||||
# Limit picom to repaint at most once every 1 / 'refresh_rate' second to
|
||||
# boost performance. This should not be used with
|
||||
# vsync drm/opengl/opengl-oml
|
||||
# as they essentially does sw-opti's job already,
|
||||
# unless you wish to specify a lower refresh rate than the actual value.
|
||||
#
|
||||
# sw-opti =
|
||||
|
||||
# Use EWMH '_NET_ACTIVE_WINDOW' to determine currently focused window,
|
||||
# rather than listening to 'FocusIn'/'FocusOut' event. Might have more accuracy,
|
||||
# provided that the WM supports it.
|
||||
#
|
||||
# use-ewmh-active-win = false
|
||||
|
||||
# Unredirect all windows if a full-screen opaque window is detected,
|
||||
# to maximize performance for full-screen windows. Known to cause flickering
|
||||
# when redirecting/unredirecting windows.
|
||||
#
|
||||
# unredir-if-possible = false
|
||||
|
||||
# Delay before unredirecting the window, in milliseconds. Defaults to 0.
|
||||
# unredir-if-possible-delay = 0
|
||||
|
||||
# Conditions of windows that shouldn't be considered full-screen for unredirecting screen.
|
||||
# unredir-if-possible-exclude = []
|
||||
|
||||
# Use 'WM_TRANSIENT_FOR' to group windows, and consider windows
|
||||
# in the same group focused at the same time.
|
||||
#
|
||||
# detect-transient = false
|
||||
detect-transient = true
|
||||
|
||||
# Use 'WM_CLIENT_LEADER' to group windows, and consider windows in the same
|
||||
# group focused at the same time. 'WM_TRANSIENT_FOR' has higher priority if
|
||||
# detect-transient is enabled, too.
|
||||
#
|
||||
# detect-client-leader = false
|
||||
detect-client-leader = true
|
||||
|
||||
# Resize damaged region by a specific number of pixels.
|
||||
# A positive value enlarges it while a negative one shrinks it.
|
||||
# If the value is positive, those additional pixels will not be actually painted
|
||||
# to screen, only used in blur calculation, and such. (Due to technical limitations,
|
||||
# with use-damage, those pixels will still be incorrectly painted to screen.)
|
||||
# Primarily used to fix the line corruption issues of blur,
|
||||
# in which case you should use the blur radius value here
|
||||
# (e.g. with a 3x3 kernel, you should use `--resize-damage 1`,
|
||||
# with a 5x5 one you use `--resize-damage 2`, and so on).
|
||||
# May or may not work with *--glx-no-stencil*. Shrinking doesn't function correctly.
|
||||
#
|
||||
# resize-damage = 1
|
||||
|
||||
# Specify a list of conditions of windows that should be painted with inverted color.
|
||||
# Resource-hogging, and is not well tested.
|
||||
#
|
||||
# invert-color-include = []
|
||||
|
||||
# GLX backend: Avoid using stencil buffer, useful if you don't have a stencil buffer.
|
||||
# Might cause incorrect opacity when rendering transparent content (but never
|
||||
# practically happened) and may not work with blur-background.
|
||||
# My tests show a 15% performance boost. Recommended.
|
||||
#
|
||||
# glx-no-stencil = false
|
||||
|
||||
# GLX backend: Avoid rebinding pixmap on window damage.
|
||||
# Probably could improve performance on rapid window content changes,
|
||||
# but is known to break things on some drivers (LLVMpipe, xf86-video-intel, etc.).
|
||||
# Recommended if it works.
|
||||
#
|
||||
# glx-no-rebind-pixmap = false
|
||||
|
||||
# Disable the use of damage information.
|
||||
# This cause the whole screen to be redrawn everytime, instead of the part of the screen
|
||||
# has actually changed. Potentially degrades the performance, but might fix some artifacts.
|
||||
# The opposing option is use-damage
|
||||
#
|
||||
# no-use-damage = false
|
||||
use-damage = true
|
||||
|
||||
# Use X Sync fence to sync clients' draw calls, to make sure all draw
|
||||
# calls are finished before picom starts drawing. Needed on nvidia-drivers
|
||||
# with GLX backend for some users.
|
||||
#
|
||||
# xrender-sync-fence = false
|
||||
|
||||
# GLX backend: Use specified GLSL fragment shader for rendering window contents.
|
||||
# See `compton-default-fshader-win.glsl` and `compton-fake-transparency-fshader-win.glsl`
|
||||
# in the source tree for examples.
|
||||
#
|
||||
# glx-fshader-win = ''
|
||||
|
||||
# Force all windows to be painted with blending. Useful if you
|
||||
# have a glx-fshader-win that could turn opaque pixels transparent.
|
||||
#
|
||||
# force-win-blend = false
|
||||
|
||||
# Do not use EWMH to detect fullscreen windows.
|
||||
# Reverts to checking if a window is fullscreen based only on its size and coordinates.
|
||||
#
|
||||
# no-ewmh-fullscreen = false
|
||||
|
||||
# Dimming bright windows so their brightness doesn't exceed this set value.
|
||||
# Brightness of a window is estimated by averaging all pixels in the window,
|
||||
# so this could comes with a performance hit.
|
||||
# Setting this to 1.0 disables this behaviour. Requires --use-damage to be disabled. (default: 1.0)
|
||||
#
|
||||
# max-brightness = 1.0
|
||||
|
||||
# Make transparent windows clip other windows like non-transparent windows do,
|
||||
# instead of blending on top of them.
|
||||
#
|
||||
# transparent-clipping = false
|
||||
|
||||
# Set the log level. Possible values are:
|
||||
# "trace", "debug", "info", "warn", "error"
|
||||
# in increasing level of importance. Case doesn't matter.
|
||||
# If using the "TRACE" log level, it's better to log into a file
|
||||
# using *--log-file*, since it can generate a huge stream of logs.
|
||||
#
|
||||
# log-level = "debug"
|
||||
log-level = "warn";
|
||||
|
||||
# Set the log file.
|
||||
# If *--log-file* is never specified, logs will be written to stderr.
|
||||
# Otherwise, logs will to written to the given file, though some of the early
|
||||
# logs might still be written to the stderr.
|
||||
# When setting this option from the config file, it is recommended to use an absolute path.
|
||||
#
|
||||
# log-file = '/path/to/your/log/file'
|
||||
|
||||
# Show all X errors (for debugging)
|
||||
# show-all-xerrors = false
|
||||
|
||||
# Write process ID to a file.
|
||||
# write-pid-path = '/path/to/your/log/file'
|
||||
|
||||
# Window type settings
|
||||
#
|
||||
# 'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard:
|
||||
# "unknown", "desktop", "dock", "toolbar", "menu", "utility",
|
||||
# "splash", "dialog", "normal", "dropdown_menu", "popup_menu",
|
||||
# "tooltip", "notification", "combo", and "dnd".
|
||||
#
|
||||
# Following per window-type options are available: ::
|
||||
#
|
||||
# fade, shadow:::
|
||||
# Controls window-type-specific shadow and fade settings.
|
||||
#
|
||||
# opacity:::
|
||||
# Controls default opacity of the window type.
|
||||
#
|
||||
# focus:::
|
||||
# Controls whether the window of this type is to be always considered focused.
|
||||
# (By default, all window types except "normal" and "dialog" has this on.)
|
||||
#
|
||||
# full-shadow:::
|
||||
# Controls whether shadow is drawn under the parts of the window that you
|
||||
# normally won't be able to see. Useful when the window has parts of it
|
||||
# transparent, and you want shadows in those areas.
|
||||
#
|
||||
# redir-ignore:::
|
||||
# Controls whether this type of windows should cause screen to become
|
||||
# redirected again after been unredirected. If you have unredir-if-possible
|
||||
# set, and doesn't want certain window to cause unnecessary screen redirection,
|
||||
# you can set this to `true`.
|
||||
#
|
||||
wintypes:
|
||||
{
|
||||
tooltip = { fade = true; shadow = true; opacity = 1.0; focus = true; full-shadow = false; };
|
||||
dock = { shadow = false; }
|
||||
dnd = { shadow = false; }
|
||||
popup_menu = { opacity = 1.0; }
|
||||
dropdown_menu = { opacity = 1.0; }
|
||||
};
|
||||
|
||||
# Opacity
|
||||
opacity-rule = [
|
||||
"90:class_g = 'Bitwarden'",
|
||||
"90:class_g = 'Lutris'",
|
||||
"90:class_g = 'Pacfinder'",
|
||||
"90:class_g = 'Spotify'",
|
||||
"90:class_g = 'kdeconnect.app'",
|
||||
"90:class_g = 'obsidian'",
|
||||
"95:class_g = 'Ferdium'",
|
||||
"95:class_g = 'Ripcord'",
|
||||
"95:class_g = 'TelegramDesktop'",
|
||||
"95:class_g = 'KotatogramDesktop'",
|
||||
"95:class_g = 'Thunderbird'",
|
||||
"95:class_g = 'VSCodium'",
|
||||
"95:class_g = 'discord'",
|
||||
"95:class_g = 'qBittorrent'",
|
||||
]
|
||||
|
||||
|
||||
|
||||
# Blur
|
||||
blur-background = true;
|
||||
blur-method = "dual_kawase";
|
||||
blur-strength = 4;
|
||||
19
config/rustmission.toml
Normal file
19
config/rustmission.toml
Normal file
@@ -0,0 +1,19 @@
|
||||
[general]
|
||||
# Whether to hide empty columns or not
|
||||
auto_hide = false
|
||||
|
||||
# Possible values: Red, Green, Blue, Yellow, Magenta, Cyan.
|
||||
# Use prefix "Light" for a brighter color.
|
||||
# It can also be a hex, e.g. "#3cb371"
|
||||
accent_color = "LightMagenta"
|
||||
|
||||
# If enabled, shows various keybindings throughout the program at the cost of a
|
||||
# little bit cluttered interface.
|
||||
beginner_mode = true
|
||||
|
||||
[connection]
|
||||
url = "http://localhost:9091/transmission/rpc" # REQUIRED!
|
||||
|
||||
# If you need username and password to authenticate:
|
||||
# username = "CHANGE_ME"
|
||||
# password = "CHANGE_ME"
|
||||
60
config/shell/aliasrc
Normal file
60
config/shell/aliasrc
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Use neovim for vim if present
|
||||
[ -x "$(command -v nvim)" ] && vimdiff="nvim -d"
|
||||
|
||||
# Vervosity and settings that you pretty much just always are going to wand
|
||||
alias \
|
||||
bc="bc -ql" \
|
||||
cp="cp -vi" \
|
||||
df="df -h" \
|
||||
mkdir="mkdir -pv" \
|
||||
mv="mv -iv" \
|
||||
nsxiv="nsxiv -a" \
|
||||
rm="rm -vI" \
|
||||
wget="wget --hsts-file=$XDG_DATA_HOME/wget-hsts" \
|
||||
keychain="keychain --dir $XDG_RUNTIME_DIR/keychain"
|
||||
|
||||
# Colorize commands when possible
|
||||
alias \
|
||||
diff="diff --color=auto" \
|
||||
grep="rg --color=auto" \
|
||||
ip="ip -color=auto" \
|
||||
less="moar" \
|
||||
ls="eza -a --icons --group-directories-first"
|
||||
|
||||
# These common commands ate just too long! Abbreviate them
|
||||
alias \
|
||||
battery="acpi" \
|
||||
code="vscodium" \
|
||||
day="redshift -PO 6500" \
|
||||
dv="doasedit" \
|
||||
e="$EDITOR" \
|
||||
fetch="fastfetch" \
|
||||
g="git" \
|
||||
gP="git push" \
|
||||
ga="git add" \
|
||||
gc="git commit" \
|
||||
gd="git diff" \
|
||||
gp="git pull" \
|
||||
gs="git status" \
|
||||
j="joshutoub" \
|
||||
lf="lfub" \
|
||||
lg="lazygit" \
|
||||
lock="swaylock" \
|
||||
night="redshift -PO 4500" \
|
||||
py="python" \
|
||||
sv="rsv" \
|
||||
v="$EDITOR" \
|
||||
weather="curl wttr.in/" \
|
||||
wg-down="wg-quick down wg0" \
|
||||
wg-up="wg-quick up wg0" \
|
||||
ww="$EDITOR ~/neorg/" \
|
||||
yarn="yarn --use-yarnrc $XDG_CONFIG_HOME/yarn/config" \
|
||||
yy="yazi"
|
||||
|
||||
# doas not required for some system commands
|
||||
for command in mount umount rsv sv pacman updatedb su shutdown poweroff reboot zzz systemctl wg wg-quick; do
|
||||
alias "$command=doas $command"
|
||||
done
|
||||
unset command
|
||||
14
config/shell/bm-dirs
Normal file
14
config/shell/bm-dirs
Normal file
@@ -0,0 +1,14 @@
|
||||
# You can add comments to these files with #
|
||||
cac ${XDG_CACHE_HOME:-$HOME/.cache}
|
||||
cf ${XDG_CONFIG_HOME:-$HOME/.config}
|
||||
D ${XDG_DOWNLOAD_DIR:-$HOME/Downloads}
|
||||
d ${XDG_DOCUMENTS_DIR:-$HOME/Documents}
|
||||
dt ${XDG_DATA_HOME:-$HOME/.local/share}
|
||||
rr $HOME/.local/src
|
||||
h $HOME
|
||||
m ${XDG_MUSIC_DIR:-$HOME/Music}
|
||||
mn /mnt
|
||||
pp ${XDG_PICTURES_DIR:-$HOME/Pictures}
|
||||
sc $HOME/.local/bin
|
||||
src $HOME/.local/src
|
||||
vv ${XDG_VIDEOS_DIR:-$HOME/Videos}
|
||||
18
config/shell/bm-files
Normal file
18
config/shell/bm-files
Normal file
@@ -0,0 +1,18 @@
|
||||
# These files automatically update when edited/saved in vim:
|
||||
|
||||
# keys filename description
|
||||
bf ${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-files # This file, a list of bookmarked files
|
||||
bd ${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs # A list of bookmarked directories similar to this file
|
||||
cfx ${XDG_CONFIG_HOME:-$HOME/.config}/x11/xresources # Colors, themes and variables for X11
|
||||
cfb ~/.local/src/dwmblocks/config.h # dwmblocks: the status bar for dwm
|
||||
|
||||
|
||||
# These do not update automatically, but on the next new instance of a program:
|
||||
|
||||
cfv ${XDG_CONFIG_HOME:-$HOME/.config}/nvim/init.lua # neovim config
|
||||
cfz $ZDOTDIR/.zshrc # zsh (shell) config
|
||||
cfa ${XDG_CONFIG_HOME:-$HOME/.config}/shell/aliasrc # aliases used by zsh (and potentially other shells)
|
||||
cfp ${XDG_CONFIG_HOME:-$HOME/.config}/shell/profile # profile file for login settings for zsh
|
||||
cfl ${XDG_CONFIG_HOME:-$HOME/.config}/lf/lfrc # lf (file browser) config
|
||||
cfL ${XDG_CONFIG_HOME:-$HOME/.config}/lf/preview # lf's preview file
|
||||
cfX ${XDG_CONFIG_HOME:-$HOME/.config}/nsxiv/exec/key-handler # nsxiv (image viewer) key/script handler
|
||||
112
config/shell/env
Normal file
112
config/shell/env
Normal file
@@ -0,0 +1,112 @@
|
||||
#!/bin/zsh
|
||||
typeset -U PATH path
|
||||
|
||||
|
||||
# profile file. Runs on login. Environmental variables are set here.
|
||||
|
||||
# If you don't plan on reverting to bash, you can remove the link in ~/.profile
|
||||
# to clean up.
|
||||
|
||||
# Adds `~/.local/bin` to $PATH
|
||||
export PATH="$PATH:${$(find ~/.local/bin -type d -printf %p:)%%:}"
|
||||
export PATH="$PATH:~/.spicetify"
|
||||
|
||||
# Disable files
|
||||
export LESSHISTFILE=-
|
||||
export $(dbus-launch)
|
||||
|
||||
unsetopt PROMPT_SP
|
||||
|
||||
|
||||
# Default Apps
|
||||
export BROWSER="floorp"
|
||||
export EDITOR="nvim"
|
||||
export IMAGE="nsxiv"
|
||||
export READER="zathura"
|
||||
export TERMINAL="alacritty"
|
||||
export VIDEO="mpv"
|
||||
export VISUAL="$EDITOR"
|
||||
export WM="awesome"
|
||||
|
||||
|
||||
# $HOME Clean-up
|
||||
export XDG_CACHE_HOME="$HOME/.cache"
|
||||
export XDG_CONFIG_HOME="$HOME/.config"
|
||||
export XDG_DATA_HOME="$HOME/.local/share"
|
||||
export XDG_RUNTIME_DIR="$HOME/.cache/xdgr"
|
||||
export XDG_STATE_HOME="$HOME/.local/share"
|
||||
|
||||
export HYPRSHOT_DIR="$HOME/Pictures/screenshots"
|
||||
|
||||
|
||||
export ANDROID_HOME="$XDG_CONFIG_HOME/android"
|
||||
export ANDROID_SDK_HOME="$XDG_CONFIG_HOME/android"
|
||||
export ANDROID_USER_HOME="$XDG_DATA_HOME/android"
|
||||
export ANSIBLE_CONFIG="$XDG_CONFIG_HOME/ansible/ansible.cfg"
|
||||
export CARGO_HOME="$XDG_DATA_HOME/cargo"
|
||||
export CUDA_CACHE_PATH="$XDG_CACHE_HOME/nv"
|
||||
export DOCKER_CONFIG="$XDG_CONFIG_HOME/docker"
|
||||
export ELECTRUMDIR="$XDG_DATA_HOME/electrum"
|
||||
export GNUPGHOME="$XDG_DATA_HOME/gnupg"
|
||||
export GOPATH="$XDG_DATA_HOME/go"
|
||||
export GRADLE_USER_HOME="$XDG_DATA_HOME/gradle"
|
||||
export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc"
|
||||
export HISTFILE="$XDG_CONFIG_HOME/zsh/history"
|
||||
export HISTFILE="$XDG_DATA_HOME/history"
|
||||
export HISTFILE="$XDG_STATE_HOME/bash/history"
|
||||
export INPUTRC="$XDG_CONFIG_HOME/shell/inputrc"
|
||||
export IPYTHONDIR="$XDG_CONFIG_HOME/ipython"
|
||||
export KERAS_HOME="$XDG_DATA_HOME/keras"
|
||||
export KODI_DATA="$XDG_DATA_HOME/kodi"
|
||||
export MBSYNCRC="$XDG_CONFIG_HOME/mbsync/config"
|
||||
export MYPY_CACHE_DIR="$XDG_CACHE_HOME/mypy"
|
||||
export MYSQL_HISTFILE="$XDG_DATA_HOME/mysql_history"
|
||||
export NODE_REPL_HISTORY="$XDG_DATA_HOME/node_repl_history"
|
||||
export NOTMUCH_CONFIG="$XDG_CONFIG_HOME/notmuch-config"
|
||||
export NPM_CONFIG_USERCONFIG="$XDG_CACHE_HOME/npm/npmrc"
|
||||
export PARALLEL_HOME="$XDG_CONFIG_HOME/parallel"
|
||||
export PASSWORD_STORE_DIR="$XDG_DATA_HOME/password-store"
|
||||
export PYENV_ROOT="$XDG_DATA_HOME/pyenv"
|
||||
export PYTHONSTARTUP="$HOME/python/pythonrc"
|
||||
export REDISCLI_HISTFILE="$XDG_DATA_HOME/redis/rediscli_history"
|
||||
export RUSTUP_HOME="$XDG_DATA_HOME/rustup"
|
||||
export RYE_HOME="$XDG_DATA_HOME/rye"
|
||||
export SSB_HOME="$XDG_DATA_HOME/zoom"
|
||||
export STARSHIP_CONFIG="$XDG_CONFIG_HOME/starship/starship.toml"
|
||||
export TEXMFVAR="$XDG_CACHE_HOME/texlive/texmf-var"
|
||||
export TMUX_TMPDIR="$XDG_RUNTIME_DIR"
|
||||
export UNISON="$XDG_DATA_HOME/unison"
|
||||
export W3M_DIR="$XDG_DATA_HOME/w3m"
|
||||
export WEECHAT_HOME="$XDG_CONFIG_HOME/weechat"
|
||||
export WGETRC="$XDG_CONFIG_HOME/wget/wgetrc"
|
||||
export WINEPREFIX="$XDG_DATA_HOME/wineprefixes/default"
|
||||
export XAUTHORITY="$XDG_RUNTIME_DIR/Xauthority"
|
||||
export XCURSOR_PATH="/usr/share/icons:$XDG_DATA_HOME/icons"
|
||||
export XINITRC="$XDG_CONFIG_HOME/x11/xinitrc"
|
||||
export ZDOTDIR="$XDG_CONFIG_HOME/zsh"
|
||||
export _JAVA_OPTIONS="-Djava.util.prefs.userRoot=${XDG_CONFIG_HOME}/java - Djavafx.cachedir=${XDG_CACHE_HOME}/openjfx"
|
||||
export _JAVA_OPTIONS=-Djava.util.prefs.userRoot="$XDG_CONFIG_HOME/java"
|
||||
|
||||
# Other program settings
|
||||
export AWT_TOOLKIT="MToolkit wmname LG3D" # May have to install wmname
|
||||
export DICS="/usr/share/stardict/dic/"
|
||||
export FZF_DEFAULT_OPTS="--layout=reverse --height 40%"
|
||||
export LESS=-R
|
||||
export LESSOPEN="| /usr/bin/highlight -O ansi %s 2>/dev/null"
|
||||
export LESS_TERMCAP_mb="$(printf '%b' '[1;31m')"
|
||||
export LESS_TERMCAP_md="$(printf '%b' '[1;36m')"
|
||||
export LESS_TERMCAP_me="$(printf '%b' '[0m')"
|
||||
export LESS_TERMCAP_se="$(printf '%b' '[0m')"
|
||||
export LESS_TERMCAP_so="$(printf '%b' '[01;44;33m')"
|
||||
export LESS_TERMCAP_ue="$(printf '%b' '[0m')"
|
||||
export LESS_TERMCAP_us="$(printf '%b' '[1;32m')"
|
||||
export MOZ_USE_XINPUT2="1" # Mozilla smooth scrolling/touchpads.
|
||||
# export QT_QPA_PLATFORMTHEME="gtk2" # Have QT use gtk2 theme.
|
||||
# export QT_QPA_PLATFORMTHEME="gtk3" # Have QT use gtk3 theme.
|
||||
export QT_QPA_PLATFORMTHEME="qt5ct"
|
||||
export QT_SCREEN_SCALE_FACTORS="1;1"
|
||||
export SUDO_ASKPASS="$HOME/.local/bin/dmenupass"
|
||||
export _JAVA_AWT_WM_NONREPARENTING=1 # Fix for Java applications in dwm
|
||||
. "$XDG_DATA_HOME/cargo/env"
|
||||
. "$XDG_DATA_HOME/rye/env"
|
||||
|
||||
BIN
config/spicetify/Backup/login.spa
Executable file
BIN
config/spicetify/Backup/login.spa
Executable file
Binary file not shown.
BIN
config/spicetify/Backup/xpui.spa
Executable file
BIN
config/spicetify/Backup/xpui.spa
Executable file
Binary file not shown.
99
config/spicetify/CustomApps/eternal-jukebox/README.md
Normal file
99
config/spicetify/CustomApps/eternal-jukebox/README.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# The Eternal Jukebox
|
||||
|
||||
For when your favorite song just isn't long enough.
|
||||
|
||||

|
||||
|
||||
A rewrite of the [Infinite / Eternal Jukebox](https://eternalbox.dev/jukebox_index.html) for Spicetify.
|
||||
It finds pathways through similar segments of the song and plays a never-ending and ever changing version of the song.
|
||||
|
||||
> **Warning**
|
||||
> The custom app is still in **beta**.
|
||||
> See [known issues](#known-issues) and [upcoming features](#upcoming-features).
|
||||
|
||||
|
||||
## Auto Installation (Linux)
|
||||
```
|
||||
sh <(curl -s https://raw.githubusercontent.com/Pithaya/spicetify-apps/main/custom-apps/eternal-jukebox/src/install.sh)
|
||||
|
||||
```
|
||||
|
||||
## Manual Installation
|
||||
|
||||
1. Run `spicetify config-dir` to open the spicetify folder.
|
||||
2. Go to the `CustomApps` folder.
|
||||
3. Create a `eternal-jukebox` folder.
|
||||
4. Download the custom app files as a zip from [here](https://github.com/Pithaya/spicetify-apps-dist/archive/refs/heads/dist/eternal-jukebox.zip).
|
||||
5. Extract the zip and put the files inside the folder you created in step 3.
|
||||
|
||||
Then, run the following commands:
|
||||
|
||||
```sh
|
||||
spicetify config custom_apps eternal-jukebox
|
||||
spicetify apply
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
A new "infinity" button allows you to enable and disable the jukebox. As long as the jukebox is enabled, the current song will play endlessly.
|
||||
|
||||

|
||||
|
||||
Changing the current song will automatically play it through the jukebox.
|
||||
|
||||

|
||||
|
||||
The custom app allows you to see a visualization of the jukebox's progress through the song.
|
||||
|
||||

|
||||
|
||||
The circle is made out of the different beats of the song. Branches, or edges are the path linking similar beats together.
|
||||
|
||||
Holding the `SHIFT` key allows you to keep repeating a part of the song by "jumping" through edges linking the same beats.
|
||||
|
||||
Clicking on a beat will seek to that part of the song.
|
||||
|
||||
Below the graph you will find some stats about the current song:
|
||||
|
||||
- **Total beats**: How many beats were played.
|
||||
- **Current branch change**: The current percentage of chance to follow an edge when playing a beat.
|
||||
- **Listen time**: How long you've been listening to the song.
|
||||
|
||||
### Settings
|
||||
|
||||
The settings button on the top right allows you to tune the jukebox.
|
||||
|
||||

|
||||
|
||||
- **Branch similarity threshold**: The maximum allowed "distance" between two branches. The higher it is, the more branches will be generated.
|
||||
- **Branch probability range**: The minimum and maximum percentage of chance to use a branch each beat. The chance will start at the minimum value, and will increase by the **Branch probability ramp-up speed** value for every beat where it is not branching, until it reaches the maximum value.
|
||||
- **Branch probability ramp-up speed**: How fast the **Branch probability chance** value should increase.
|
||||
- **Loop extension optimization**: If checked, will try to add the longest backward branch it can at the last branching beat.
|
||||
- **Allow only reverse branches**: If checked, will only add branches going back in the song.
|
||||
- **Allow only long branches**: If checked, will only add long branches. A branch is considered long if it covers at least a fifth of the song's length.
|
||||
- **Remove sequential branches**: If checked, will remove consecutive branches of the same length.
|
||||
|
||||
The reset button can be used to reset the settings to the default values.
|
||||
|
||||
## Known issues
|
||||
|
||||
- Audio lag when jumping between parts of the song
|
||||
- Jukebox "freezing" and getting out of sync
|
||||
- Songs getting stuck in short loops due to issues with the graph generation
|
||||
|
||||
## Upcoming features
|
||||
|
||||
- More graph interactivity
|
||||
|
||||
## Uninstall
|
||||
|
||||
1. Run `spicetify config-dir` to open the spicetify folder
|
||||
2. Go to the `CustomApps` folder
|
||||
3. Delete the `eternal-jukebox` folder
|
||||
|
||||
Then, run the following commands:
|
||||
|
||||
```sh
|
||||
spicetify config custom_apps eternal-jukebox-
|
||||
spicetify apply
|
||||
```
|
||||
1
config/spicetify/CustomApps/eternal-jukebox/extension.js
Normal file
1
config/spicetify/CustomApps/eternal-jukebox/extension.js
Normal file
File diff suppressed because one or more lines are too long
12
config/spicetify/CustomApps/eternal-jukebox/index.js
Normal file
12
config/spicetify/CustomApps/eternal-jukebox/index.js
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Eternal Jukebox",
|
||||
"icon": "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n style=\"stroke-width: 2px !important;\"\n>\n <path d=\"M18.178 8c5.096 0 5.096 8 0 8-5.095 0-7.133-8-12.739-8-4.585 0-4.585 8 0 8 5.606 0 7.644-8 12.74-8z\"></path>\n</svg>",
|
||||
"active-icon": "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n style=\"stroke-width: 2px !important;\"\n>\n <path d=\"M18.178 8c5.096 0 5.096 8 0 8-5.095 0-7.133-8-12.739-8-4.585 0-4.585 8 0 8 5.606 0 7.644-8 12.74-8z\"></path>\n</svg>",
|
||||
"subfiles": [],
|
||||
"subfiles_extension": [
|
||||
"extension.js"
|
||||
]
|
||||
}
|
||||
BIN
config/spicetify/CustomApps/eternal-jukebox/preview.png
Normal file
BIN
config/spicetify/CustomApps/eternal-jukebox/preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 242 KiB |
1
config/spicetify/CustomApps/eternal-jukebox/style.css
Normal file
1
config/spicetify/CustomApps/eternal-jukebox/style.css
Normal file
File diff suppressed because one or more lines are too long
1
config/spicetify/CustomApps/history-in-sidebar/.gitattributes
vendored
Normal file
1
config/spicetify/CustomApps/history-in-sidebar/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
dist/* linguist-vendored
|
||||
147
config/spicetify/CustomApps/history-in-sidebar/.gitignore
vendored
Normal file
147
config/spicetify/CustomApps/history-in-sidebar/.gitignore
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/node
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=node
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# build-local directory
|
||||
dist/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
### Node Patch ###
|
||||
# Serverless Webpack directories
|
||||
.webpack/
|
||||
|
||||
# Optional stylelint cache
|
||||
|
||||
# SvelteKit build / generate output
|
||||
.svelte-kit
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/node
|
||||
27
config/spicetify/CustomApps/history-in-sidebar/README.md
Normal file
27
config/spicetify/CustomApps/history-in-sidebar/README.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# History in Sidebar
|
||||
|
||||
Adds a shortcut for the "Recently Played" screen to the sidebar.
|
||||
|
||||
Saves one full click!
|
||||
|
||||
> If you like it, please consider starring it on GitHub 🌟
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/Bergbok/Spicetify-Creations/assets/66174189/ded310d5-374a-4238-98b1-bd2fad737604"/></img>
|
||||
</p>
|
||||
|
||||
## Installation
|
||||
|
||||
1. Install Spicetify ([guide](https://spicetify.app/docs/advanced-usage/installation))
|
||||
2. Download it from [here](https://github.com/Bergbok/Spicetify-Creations/archive/refs/heads/dist/history-in-sidebar.zip)
|
||||
3. Run `spicetify config-dir` in a terminal
|
||||
4. Extract the zip into the CustomApps folder
|
||||
5. Rename the extracted folder to `history-in-sidebar`
|
||||
6. Run `spicetify config custom_apps history-in-sidebar`
|
||||
7. Run `spicetify apply`
|
||||
|
||||
> If you get stuck check out [Spicetify's official guide](https://spicetify.app/docs/advanced-usage/custom-apps/).
|
||||
|
||||
## License
|
||||
|
||||
This repository is licensed under the [MIT License](https://github.com/Bergbok/Spicetify-Creations/blob/main/LICENSE).
|
||||
1934
config/spicetify/CustomApps/history-in-sidebar/package-lock.json
generated
Normal file
1934
config/spicetify/CustomApps/history-in-sidebar/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
17
config/spicetify/CustomApps/history-in-sidebar/package.json
Normal file
17
config/spicetify/CustomApps/history-in-sidebar/package.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "history-in-sidebar",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "spicetify-creator",
|
||||
"build-local": "spicetify-creator --out=dist --minify",
|
||||
"watch": "spicetify-creator --watch"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.24",
|
||||
"@types/react": "^18.2.63",
|
||||
"@types/react-dom": "^18.2.19",
|
||||
"spicetify-creator": "^1.0.17"
|
||||
}
|
||||
}
|
||||
BIN
config/spicetify/CustomApps/history-in-sidebar/preview.png
Normal file
BIN
config/spicetify/CustomApps/history-in-sidebar/preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
13
config/spicetify/CustomApps/history-in-sidebar/src/app.tsx
Normal file
13
config/spicetify/CustomApps/history-in-sidebar/src/app.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import React from 'react'
|
||||
|
||||
class App extends React.Component {
|
||||
componentDidMount() {
|
||||
Spicetify.Platform.History.push('/history');
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24" id="history">
|
||||
<path d="M21.001 12a9 9 0 0 0-9-9 1 1 0 1 1 0-2c6.075 0 11 4.925 11 11s-4.925 11-11 11-11-4.925-11-11a1 1 0 1 1 2 0 9 9 0 1 0 18 0zM7.58 4.422a1.25 1.25 0 1 1-1.25-2.165 1.25 1.25 0 0 1 1.25 2.165z"></path>
|
||||
<path d="M11.034 6a1 1 0 0 1 2 0v5H16a1 1 0 1 1 0 2h-4.966V6zM2.67 8.083a1.25 1.25 0 1 0 1.25-2.165 1.25 1.25 0 0 0-1.25 2.165z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 458 B |
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"displayName": "History",
|
||||
"nameId": "history-in-sidebar",
|
||||
"icon": "assets/icon.svg",
|
||||
"activeIcon": "assets/icon.svg"
|
||||
}
|
||||
14
config/spicetify/CustomApps/history-in-sidebar/tsconfig.json
Normal file
14
config/spicetify/CustomApps/history-in-sidebar/tsconfig.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"jsx": "react",
|
||||
"module": "commonjs",
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "dist",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["./src/**/*", "../../libs/shared/src/types/**/*"]
|
||||
}
|
||||
156
config/spicetify/CustomApps/library/collection_wrapper.js
Normal file
156
config/spicetify/CustomApps/library/collection_wrapper.js
Normal file
@@ -0,0 +1,156 @@
|
||||
(async function() {
|
||||
while (!Spicetify.React || !Spicetify.ReactDOM) {
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
}
|
||||
"use strict";
|
||||
var library = (() => {
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/extensions/collection_wrapper.tsx
|
||||
var collection_wrapper_exports = {};
|
||||
__export(collection_wrapper_exports, {
|
||||
default: () => collection_wrapper_default
|
||||
});
|
||||
|
||||
// node_modules/uuid/dist/esm-browser/rng.js
|
||||
var getRandomValues;
|
||||
var rnds8 = new Uint8Array(16);
|
||||
function rng() {
|
||||
if (!getRandomValues) {
|
||||
getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
|
||||
if (!getRandomValues) {
|
||||
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
||||
}
|
||||
}
|
||||
return getRandomValues(rnds8);
|
||||
}
|
||||
|
||||
// node_modules/uuid/dist/esm-browser/stringify.js
|
||||
var byteToHex = [];
|
||||
for (let i = 0; i < 256; ++i) {
|
||||
byteToHex.push((i + 256).toString(16).slice(1));
|
||||
}
|
||||
function unsafeStringify(arr, offset = 0) {
|
||||
return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
|
||||
}
|
||||
|
||||
// node_modules/uuid/dist/esm-browser/native.js
|
||||
var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
||||
var native_default = {
|
||||
randomUUID
|
||||
};
|
||||
|
||||
// node_modules/uuid/dist/esm-browser/v4.js
|
||||
function v4(options, buf, offset) {
|
||||
if (native_default.randomUUID && !buf && !options) {
|
||||
return native_default.randomUUID();
|
||||
}
|
||||
options = options || {};
|
||||
const rnds = options.random || (options.rng || rng)();
|
||||
rnds[6] = rnds[6] & 15 | 64;
|
||||
rnds[8] = rnds[8] & 63 | 128;
|
||||
if (buf) {
|
||||
offset = offset || 0;
|
||||
for (let i = 0; i < 16; ++i) {
|
||||
buf[offset + i] = rnds[i];
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
return unsafeStringify(rnds);
|
||||
}
|
||||
var v4_default = v4;
|
||||
|
||||
// src/extensions/collection_wrapper.tsx
|
||||
var CollectionWrapper = class {
|
||||
constructor() {
|
||||
this.getCollections = () => {
|
||||
return this._collections;
|
||||
};
|
||||
this.createCollection = (name) => {
|
||||
const collection = {
|
||||
id: v4_default(),
|
||||
name,
|
||||
items: []
|
||||
};
|
||||
this._collections.push(collection);
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection Created");
|
||||
return collection;
|
||||
};
|
||||
this.deleteCollection = (collectionID) => {
|
||||
this._collections = this._collections.filter((collection) => collection.id !== collectionID);
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection Deleted");
|
||||
};
|
||||
this.getCollection = (collectionID) => {
|
||||
return this._collections.find((collection) => collection.id === collectionID);
|
||||
};
|
||||
this.renameCollection = (collectionID, name) => {
|
||||
const collection = this.getCollection(collectionID);
|
||||
if (!collection)
|
||||
throw new Error("Collection is not defined");
|
||||
collection.name = name;
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection Renamed");
|
||||
};
|
||||
this.addToCollection = (collectionID, albumURI) => {
|
||||
const collection = this.getCollection(collectionID);
|
||||
if (!collection)
|
||||
throw new Error("Collection is not defined");
|
||||
Spicetify.GraphQL.Request(Spicetify.GraphQL.Definitions.getAlbum, {
|
||||
uri: albumURI,
|
||||
locale: "en",
|
||||
offset: 0,
|
||||
limit: 1
|
||||
}).then((res) => {
|
||||
var _a, _b, _c, _d, _e, _f, _g;
|
||||
const data = res.data.albumUnion;
|
||||
const albumItem = {
|
||||
uri: data.uri,
|
||||
name: data.name,
|
||||
artist: (_d = (_c = (_b = (_a = data.artists) == null ? void 0 : _a.items) == null ? void 0 : _b[0]) == null ? void 0 : _c.profile) == null ? void 0 : _d.name,
|
||||
image: ((_g = (_f = (_e = data.coverArt) == null ? void 0 : _e.sources) == null ? void 0 : _f[0]) == null ? void 0 : _g.url) || ""
|
||||
};
|
||||
collection.items.push(albumItem);
|
||||
this.saveCollections();
|
||||
});
|
||||
Spicetify.showNotification("Item Added to Collection");
|
||||
};
|
||||
this.removeFromCollection = (collectionID, albumURI) => {
|
||||
const collection = this.getCollection(collectionID);
|
||||
if (!collection)
|
||||
throw new Error("Collection is not defined");
|
||||
collection.items = collection.items.filter((album) => album.uri !== albumURI);
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Item Removed from Collection");
|
||||
};
|
||||
this.getCollectionForItem = (albumURI) => {
|
||||
return this._collections.filter((collection) => collection.items.some((item) => item.uri === albumURI));
|
||||
};
|
||||
this.saveCollections = () => {
|
||||
localStorage.setItem("library:collections", JSON.stringify(this._collections));
|
||||
};
|
||||
this._collections = JSON.parse(localStorage.getItem("library:collections") || "[]");
|
||||
}
|
||||
};
|
||||
var collection_wrapper_default = CollectionWrapper;
|
||||
return __toCommonJS(collection_wrapper_exports);
|
||||
})();
|
||||
|
||||
})();
|
||||
300
config/spicetify/CustomApps/library/collections_wrapper.js
Normal file
300
config/spicetify/CustomApps/library/collections_wrapper.js
Normal file
@@ -0,0 +1,300 @@
|
||||
(async function() {
|
||||
while (!Spicetify.React || !Spicetify.ReactDOM) {
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
}
|
||||
"use strict";
|
||||
var library = (() => {
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var __publicField = (obj, key, value) => {
|
||||
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
||||
return value;
|
||||
};
|
||||
|
||||
// src/extensions/collections_wrapper.ts
|
||||
var collections_wrapper_exports = {};
|
||||
__export(collections_wrapper_exports, {
|
||||
default: () => collections_wrapper_default
|
||||
});
|
||||
|
||||
// ../node_modules/uuid/dist/esm-browser/rng.js
|
||||
var getRandomValues;
|
||||
var rnds8 = new Uint8Array(16);
|
||||
function rng() {
|
||||
if (!getRandomValues) {
|
||||
getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
|
||||
if (!getRandomValues) {
|
||||
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
||||
}
|
||||
}
|
||||
return getRandomValues(rnds8);
|
||||
}
|
||||
|
||||
// ../node_modules/uuid/dist/esm-browser/stringify.js
|
||||
var byteToHex = [];
|
||||
for (let i = 0; i < 256; ++i) {
|
||||
byteToHex.push((i + 256).toString(16).slice(1));
|
||||
}
|
||||
function unsafeStringify(arr, offset = 0) {
|
||||
return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
|
||||
}
|
||||
|
||||
// ../node_modules/uuid/dist/esm-browser/native.js
|
||||
var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
||||
var native_default = {
|
||||
randomUUID
|
||||
};
|
||||
|
||||
// ../node_modules/uuid/dist/esm-browser/v4.js
|
||||
function v4(options, buf, offset) {
|
||||
if (native_default.randomUUID && !buf && !options) {
|
||||
return native_default.randomUUID();
|
||||
}
|
||||
options = options || {};
|
||||
const rnds = options.random || (options.rng || rng)();
|
||||
rnds[6] = rnds[6] & 15 | 64;
|
||||
rnds[8] = rnds[8] & 63 | 128;
|
||||
if (buf) {
|
||||
offset = offset || 0;
|
||||
for (let i = 0; i < 16; ++i) {
|
||||
buf[offset + i] = rnds[i];
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
return unsafeStringify(rnds);
|
||||
}
|
||||
var v4_default = v4;
|
||||
|
||||
// src/extensions/collections_wrapper.ts
|
||||
var _CollectionsWrapper = class extends EventTarget {
|
||||
_collections;
|
||||
constructor() {
|
||||
super();
|
||||
this._collections = JSON.parse(localStorage.getItem("library:collections") || "[]");
|
||||
}
|
||||
saveCollections() {
|
||||
localStorage.setItem("library:collections", JSON.stringify(this._collections));
|
||||
this.dispatchEvent(new CustomEvent("update", { detail: this._collections }));
|
||||
}
|
||||
getCollection(uri) {
|
||||
return this._collections.find((collection) => collection.uri === uri);
|
||||
}
|
||||
async getCollectionContents(uri) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
throw new Error("Collection not found");
|
||||
const items = this._collections.filter((collection2) => collection2.parentCollection === uri);
|
||||
const albums = await Spicetify.Platform.LibraryAPI.getContents({
|
||||
filters: ["0"],
|
||||
offset: 0,
|
||||
limit: 9999
|
||||
});
|
||||
items.push(...albums.items.filter((album) => collection.items.includes(album.uri)));
|
||||
return items;
|
||||
}
|
||||
async getContents(props) {
|
||||
const { collectionUri, offset, limit, textFilter } = props;
|
||||
let items = collectionUri ? await this.getCollectionContents(collectionUri) : this._collections;
|
||||
const openedCollectionName = collectionUri ? this.getCollection(collectionUri)?.name : void 0;
|
||||
if (textFilter) {
|
||||
const regex = new RegExp(`\\b${textFilter}`, "i");
|
||||
items = items.filter((collection) => regex.test(collection.name));
|
||||
}
|
||||
items = items.slice(offset, offset + limit);
|
||||
return { items, totalLength: this._collections.length, offset, openedCollectionName };
|
||||
}
|
||||
async cleanCollections() {
|
||||
for (const collection of this._collections) {
|
||||
const boolArray = await Spicetify.Platform.LibraryAPI.contains(...collection.items);
|
||||
if (boolArray.includes(false)) {
|
||||
collection.items = collection.items.filter((_, i) => boolArray[i]);
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Album removed from collection");
|
||||
this.syncCollection(collection.uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
async syncCollection(uri) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
const { PlaylistAPI } = Spicetify.Platform;
|
||||
if (!collection.syncedPlaylistUri)
|
||||
return;
|
||||
const playlist = await PlaylistAPI.getPlaylist(collection.syncedPlaylistUri);
|
||||
const playlistTracks = playlist.contents.items.filter((t) => t.type === "track").map((t) => t.uri);
|
||||
const collectionTracks = await this.getTracklist(uri);
|
||||
const wanted = collectionTracks.filter((track) => !playlistTracks.includes(track));
|
||||
const unwanted = playlistTracks.filter((track) => !collectionTracks.includes(track)).map((uri2) => ({ uri: uri2, uid: [] }));
|
||||
if (wanted.length)
|
||||
await PlaylistAPI.add(collection.syncedPlaylistUri, wanted, { before: "end" });
|
||||
if (unwanted.length)
|
||||
await PlaylistAPI.remove(collection.syncedPlaylistUri, unwanted);
|
||||
}
|
||||
unsyncCollection(uri) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
collection.syncedPlaylistUri = void 0;
|
||||
this.saveCollections();
|
||||
}
|
||||
async getTracklist(collectionUri) {
|
||||
const collection = this.getCollection(collectionUri);
|
||||
if (!collection)
|
||||
return [];
|
||||
return Promise.all(
|
||||
collection.items.map(async (uri) => {
|
||||
const album = await Spicetify.Platform.LibraryAPI.getAlbum(uri);
|
||||
return album.items.map((t) => t.uri);
|
||||
})
|
||||
).then((tracks) => tracks.flat());
|
||||
}
|
||||
async convertToPlaylist(uri) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
const { Platform, showNotification } = Spicetify;
|
||||
const { RootlistAPI, PlaylistAPI } = Platform;
|
||||
if (collection.syncedPlaylistUri) {
|
||||
showNotification("Synced Playlist already exists", true);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const playlistUri = await RootlistAPI.createPlaylist(collection.name, { before: "start" });
|
||||
const items = await this.getTracklist(uri);
|
||||
await PlaylistAPI.add(playlistUri, items, { before: "start" });
|
||||
collection.syncedPlaylistUri = playlistUri;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
showNotification("Failed to create playlist", true);
|
||||
}
|
||||
}
|
||||
async createCollectionFromDiscog(artistUri) {
|
||||
const [raw, info] = await Promise.all([
|
||||
Spicetify.GraphQL.Request(Spicetify.GraphQL.Definitions.queryArtistDiscographyAlbums, {
|
||||
uri: artistUri,
|
||||
offset: 0,
|
||||
limit: 50
|
||||
}),
|
||||
Spicetify.GraphQL.Request(Spicetify.GraphQL.Definitions.queryArtistOverview, {
|
||||
uri: artistUri,
|
||||
locale: Spicetify.Locale.getLocale(),
|
||||
includePrerelease: false
|
||||
})
|
||||
]);
|
||||
const items = raw?.data?.artistUnion.discography.albums?.items;
|
||||
const name = info?.data?.artistUnion.profile.name;
|
||||
const image = info?.data?.artistUnion.visuals.avatarImage?.sources?.[0]?.url;
|
||||
if (!name || !items?.length) {
|
||||
Spicetify.showNotification("Artist not found or has no albums");
|
||||
return;
|
||||
}
|
||||
const collectionUri = this.createCollection(`${name} Albums`);
|
||||
if (image)
|
||||
this.setCollectionImage(collectionUri, image);
|
||||
for (const album of items) {
|
||||
this.addAlbumToCollection(collectionUri, album.releases.items[0].uri);
|
||||
}
|
||||
}
|
||||
createCollection(name, parentCollection = "") {
|
||||
const id = v4_default();
|
||||
this._collections.push({
|
||||
type: "collection",
|
||||
uri: id,
|
||||
name,
|
||||
items: [],
|
||||
addedAt: new Date(),
|
||||
lastPlayedAt: new Date(),
|
||||
parentCollection
|
||||
});
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection created");
|
||||
return id;
|
||||
}
|
||||
deleteCollection(uri) {
|
||||
this._collections = this._collections.filter((collection) => collection.uri !== uri);
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection deleted");
|
||||
}
|
||||
deleteCollectionAndAlbums(uri) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
for (const album of collection.items) {
|
||||
Spicetify.Platform.LibraryAPI.remove({ uris: [album] });
|
||||
}
|
||||
this.deleteCollection(uri);
|
||||
}
|
||||
async addAlbumToCollection(collectionUri, albumUri) {
|
||||
const collection = this.getCollection(collectionUri);
|
||||
if (!collection)
|
||||
return;
|
||||
await Spicetify.Platform.LibraryAPI.add({ uris: [albumUri] });
|
||||
collection.items.push(albumUri);
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Album added to collection");
|
||||
this.syncCollection(collectionUri);
|
||||
}
|
||||
removeAlbumFromCollection(collectionUri, albumUri) {
|
||||
const collection = this.getCollection(collectionUri);
|
||||
if (!collection)
|
||||
return;
|
||||
collection.items = collection.items.filter((item) => item !== albumUri);
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Album removed from collection");
|
||||
this.syncCollection(collectionUri);
|
||||
}
|
||||
getCollectionsWithAlbum(albumUri) {
|
||||
return this._collections.filter((collection) => {
|
||||
return collection.items.some((item) => item === albumUri);
|
||||
});
|
||||
}
|
||||
renameCollection(uri, name) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
collection.name = name;
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection renamed");
|
||||
}
|
||||
setCollectionImage(uri, url) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
collection.image = url;
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection image set");
|
||||
}
|
||||
removeCollectionImage(uri) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
collection.image = void 0;
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection image removed");
|
||||
}
|
||||
};
|
||||
var CollectionsWrapper = _CollectionsWrapper;
|
||||
__publicField(CollectionsWrapper, "INSTANCE", new _CollectionsWrapper());
|
||||
window.CollectionsWrapper = CollectionsWrapper.INSTANCE;
|
||||
var collections_wrapper_default = CollectionsWrapper;
|
||||
return __toCommonJS(collections_wrapper_exports);
|
||||
})();
|
||||
|
||||
})();
|
||||
280
config/spicetify/CustomApps/library/config_loader.js
Normal file
280
config/spicetify/CustomApps/library/config_loader.js
Normal file
@@ -0,0 +1,280 @@
|
||||
(async function() {
|
||||
while (!Spicetify.React || !Spicetify.ReactDOM) {
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
}
|
||||
"use strict";
|
||||
var library = (() => {
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
||||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
||||
var __spreadValues = (a, b) => {
|
||||
for (var prop in b || (b = {}))
|
||||
if (__hasOwnProp.call(b, prop))
|
||||
__defNormalProp(a, prop, b[prop]);
|
||||
if (__getOwnPropSymbols)
|
||||
for (var prop of __getOwnPropSymbols(b)) {
|
||||
if (__propIsEnum.call(b, prop))
|
||||
__defNormalProp(a, prop, b[prop]);
|
||||
}
|
||||
return a;
|
||||
};
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
};
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// external-global-plugin:react
|
||||
var require_react = __commonJS({
|
||||
"external-global-plugin:react"(exports, module) {
|
||||
module.exports = Spicetify.React;
|
||||
}
|
||||
});
|
||||
|
||||
// src/extensions/config_loader.tsx
|
||||
var config_loader_exports = {};
|
||||
__export(config_loader_exports, {
|
||||
default: () => config_loader_default
|
||||
});
|
||||
|
||||
// src/components/settings_modal.tsx
|
||||
var import_react = __toESM(require_react());
|
||||
var TextInput = (props) => {
|
||||
const textId = `text-input:${props.storageKey}`;
|
||||
return /* @__PURE__ */ import_react.default.createElement("label", {
|
||||
className: "text-input-wrapper"
|
||||
}, /* @__PURE__ */ import_react.default.createElement("input", {
|
||||
className: "text-input",
|
||||
type: "text",
|
||||
value: props.value || "",
|
||||
"data-storage-key": props.storageKey,
|
||||
placeholder: props.placeholder,
|
||||
id: textId,
|
||||
title: `Text input for ${props.storageKey}`,
|
||||
onChange: props.onChange
|
||||
}));
|
||||
};
|
||||
var Dropdown = (props) => {
|
||||
const dropdownId = `dropdown:${props.storageKey}`;
|
||||
return /* @__PURE__ */ import_react.default.createElement("label", {
|
||||
className: "dropdown-wrapper"
|
||||
}, /* @__PURE__ */ import_react.default.createElement("select", {
|
||||
className: "dropdown-input",
|
||||
value: props.value,
|
||||
"data-storage-key": props.storageKey,
|
||||
id: dropdownId,
|
||||
title: `Dropdown for ${props.storageKey}`,
|
||||
onChange: props.onChange
|
||||
}, props.options.map((option, index) => /* @__PURE__ */ import_react.default.createElement("option", {
|
||||
key: index,
|
||||
value: option
|
||||
}, option))));
|
||||
};
|
||||
var TooltipIcon = () => {
|
||||
return /* @__PURE__ */ import_react.default.createElement("svg", {
|
||||
role: "img",
|
||||
height: "16",
|
||||
width: "16",
|
||||
className: "Svg-sc-ytk21e-0 uPxdw nW1RKQOkzcJcX6aDCZB4",
|
||||
viewBox: "0 0 16 16"
|
||||
}, /* @__PURE__ */ import_react.default.createElement("path", {
|
||||
d: "M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8z"
|
||||
}), /* @__PURE__ */ import_react.default.createElement("path", {
|
||||
d: "M7.25 12.026v-1.5h1.5v1.5h-1.5zm.884-7.096A1.125 1.125 0 007.06 6.39l-1.431.448a2.625 2.625 0 115.13-.784c0 .54-.156 1.015-.503 1.488-.3.408-.7.652-.973.818l-.112.068c-.185.116-.26.203-.302.283-.046.087-.097.245-.097.57h-1.5c0-.47.072-.898.274-1.277.206-.385.507-.645.827-.846l.147-.092c.285-.177.413-.257.526-.41.169-.23.213-.397.213-.602 0-.622-.503-1.125-1.125-1.125z"
|
||||
}));
|
||||
};
|
||||
var ConfigRow = (props) => {
|
||||
console.log(props);
|
||||
const enabled = !!props.modalConfig[props.storageKey];
|
||||
const value = props.modalConfig[props.storageKey];
|
||||
const updateItem = (storageKey, state) => {
|
||||
props.modalConfig[storageKey] = state;
|
||||
console.debug(`toggling ${storageKey} to ${state}`);
|
||||
localStorage.setItem(`library:config:${storageKey}`, String(state));
|
||||
props.updateConfig(props.modalConfig);
|
||||
};
|
||||
const settingsToggleChange = (newValue, storageKey) => {
|
||||
updateItem(storageKey, newValue);
|
||||
if (props.callback)
|
||||
props.callback(newValue);
|
||||
};
|
||||
const settingsTextChange = (event) => {
|
||||
console.log("yoohoo");
|
||||
updateItem(event.target.dataset.storageKey, event.target.value);
|
||||
console.log(props.callback);
|
||||
if (props.callback)
|
||||
props.callback(event.target.value);
|
||||
};
|
||||
const settingsDropdownChange = (event) => {
|
||||
updateItem(event.target.dataset.storageKey, event.target.value);
|
||||
if (props.callback)
|
||||
props.callback(event.target.value);
|
||||
};
|
||||
const element = () => {
|
||||
switch (props.type) {
|
||||
case "dropdown":
|
||||
return /* @__PURE__ */ import_react.default.createElement(Dropdown, {
|
||||
name: props.name,
|
||||
storageKey: props.storageKey,
|
||||
value,
|
||||
options: props.options || [],
|
||||
onChange: settingsDropdownChange
|
||||
});
|
||||
case "text":
|
||||
return /* @__PURE__ */ import_react.default.createElement(TextInput, {
|
||||
name: props.name,
|
||||
storageKey: props.storageKey,
|
||||
value,
|
||||
placeholder: props.placeholder,
|
||||
onChange: settingsTextChange
|
||||
});
|
||||
default:
|
||||
return /* @__PURE__ */ import_react.default.createElement(Spicetify.ReactComponent.Toggle, {
|
||||
id: `toggle:${props.storageKey}`,
|
||||
value: enabled,
|
||||
onSelected: (newValue) => {
|
||||
settingsToggleChange(newValue, props.storageKey);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
return /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
className: "setting-row"
|
||||
}, /* @__PURE__ */ import_react.default.createElement("label", {
|
||||
className: "col description"
|
||||
}, props.name, props.desc && /* @__PURE__ */ import_react.default.createElement(Spicetify.ReactComponent.TooltipWrapper, {
|
||||
label: /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
dangerouslySetInnerHTML: { __html: props.desc }
|
||||
}),
|
||||
renderInline: true,
|
||||
showDelay: 10,
|
||||
placement: "top",
|
||||
labelClassName: "tooltip",
|
||||
disabled: false
|
||||
}, /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
className: "tooltip-icon"
|
||||
}, /* @__PURE__ */ import_react.default.createElement(TooltipIcon, null)))), /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
className: "col action"
|
||||
}, element()));
|
||||
};
|
||||
var SettingsModal = ({ CONFIG, settings, updateAppConfig }) => {
|
||||
const [modalConfig, setModalConfig] = import_react.default.useState(__spreadValues({}, CONFIG));
|
||||
const updateConfig = (CONFIG2) => {
|
||||
updateAppConfig(__spreadValues({}, CONFIG2));
|
||||
setModalConfig(__spreadValues({}, CONFIG2));
|
||||
};
|
||||
const configRows = settings.map((setting, index) => {
|
||||
console.log(setting);
|
||||
if (setting.sectionHeader) {
|
||||
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, index != 0 ? /* @__PURE__ */ import_react.default.createElement("br", null) : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null), /* @__PURE__ */ import_react.default.createElement("h2", {
|
||||
className: "section-header"
|
||||
}, setting.sectionHeader), /* @__PURE__ */ import_react.default.createElement(ConfigRow, {
|
||||
name: setting.name,
|
||||
storageKey: setting.key,
|
||||
type: setting.type,
|
||||
options: setting.options,
|
||||
placeholder: setting.placeholder,
|
||||
desc: setting.desc,
|
||||
modalConfig,
|
||||
updateConfig,
|
||||
callback: setting.callback
|
||||
}));
|
||||
}
|
||||
return /* @__PURE__ */ import_react.default.createElement(ConfigRow, {
|
||||
name: setting.name,
|
||||
storageKey: setting.key,
|
||||
type: setting.type,
|
||||
options: setting.options,
|
||||
placeholder: setting.placeholder,
|
||||
desc: setting.desc,
|
||||
modalConfig,
|
||||
updateConfig,
|
||||
callback: setting.callback
|
||||
});
|
||||
});
|
||||
return /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
id: "stats-config-container"
|
||||
}, configRows);
|
||||
};
|
||||
var settings_modal_default = SettingsModal;
|
||||
|
||||
// src/extensions/config_loader.tsx
|
||||
var import_react2 = __toESM(require_react());
|
||||
var getLocalStorageDataFromKey = (key, fallback) => {
|
||||
const data = localStorage.getItem(key);
|
||||
if (data) {
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
} catch (err) {
|
||||
return data;
|
||||
}
|
||||
} else {
|
||||
return fallback;
|
||||
}
|
||||
};
|
||||
(function wait() {
|
||||
const { LocalStorageAPI } = Spicetify == null ? void 0 : Spicetify.Platform;
|
||||
if (!LocalStorageAPI) {
|
||||
setTimeout(wait, 100);
|
||||
return;
|
||||
}
|
||||
})();
|
||||
async function loadConfig(configSettings) {
|
||||
const { PopupModal } = Spicetify;
|
||||
await new Promise((resolve) => {
|
||||
(function checkPopupModal() {
|
||||
if (PopupModal) {
|
||||
resolve(void 0);
|
||||
} else {
|
||||
setTimeout(checkPopupModal, 100);
|
||||
}
|
||||
})();
|
||||
});
|
||||
const settingsArray = configSettings.map((setting) => {
|
||||
return { [setting.key]: getLocalStorageDataFromKey(`library:config:${setting.key}`, setting.def) };
|
||||
});
|
||||
let CONFIG = window.CONFIG = Object.assign({}, ...settingsArray);
|
||||
const updateConfig = (config) => {
|
||||
window.CONFIG = __spreadValues({}, config);
|
||||
console.log("updated config", config);
|
||||
};
|
||||
const launchModal = window.launchModal = () => {
|
||||
console.log(settingsArray);
|
||||
PopupModal.display({
|
||||
title: "Library Settings",
|
||||
content: /* @__PURE__ */ import_react2.default.createElement(settings_modal_default, {
|
||||
CONFIG,
|
||||
settings: configSettings,
|
||||
updateAppConfig: updateConfig
|
||||
}),
|
||||
isLarge: true
|
||||
});
|
||||
};
|
||||
return { CONFIG, launchModal };
|
||||
}
|
||||
var config_loader_default = loadConfig;
|
||||
return __toCommonJS(config_loader_exports);
|
||||
})();
|
||||
|
||||
})();
|
||||
269
config/spicetify/CustomApps/library/config_wrapper.js
Normal file
269
config/spicetify/CustomApps/library/config_wrapper.js
Normal file
@@ -0,0 +1,269 @@
|
||||
(async function() {
|
||||
while (!Spicetify.React || !Spicetify.ReactDOM) {
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
}
|
||||
"use strict";
|
||||
var library = (() => {
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
||||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
||||
var __spreadValues = (a, b) => {
|
||||
for (var prop in b || (b = {}))
|
||||
if (__hasOwnProp.call(b, prop))
|
||||
__defNormalProp(a, prop, b[prop]);
|
||||
if (__getOwnPropSymbols)
|
||||
for (var prop of __getOwnPropSymbols(b)) {
|
||||
if (__propIsEnum.call(b, prop))
|
||||
__defNormalProp(a, prop, b[prop]);
|
||||
}
|
||||
return a;
|
||||
};
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
};
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// external-global-plugin:react
|
||||
var require_react = __commonJS({
|
||||
"external-global-plugin:react"(exports, module) {
|
||||
module.exports = Spicetify.React;
|
||||
}
|
||||
});
|
||||
|
||||
// src/extensions/config_wrapper.tsx
|
||||
var config_wrapper_exports = {};
|
||||
__export(config_wrapper_exports, {
|
||||
default: () => config_wrapper_default
|
||||
});
|
||||
var import_react2 = __toESM(require_react());
|
||||
|
||||
// src/components/config/config_modal.tsx
|
||||
var import_react = __toESM(require_react());
|
||||
var TextInput = (props) => {
|
||||
const handleTextChange = (event) => {
|
||||
props.callback(event.target.value);
|
||||
};
|
||||
return /* @__PURE__ */ import_react.default.createElement("label", {
|
||||
className: "text-input-wrapper"
|
||||
}, /* @__PURE__ */ import_react.default.createElement("input", {
|
||||
className: "text-input",
|
||||
type: "text",
|
||||
value: props.value || "",
|
||||
"data-storage-key": props.storageKey,
|
||||
placeholder: props.placeholder,
|
||||
id: `text-input:${props.storageKey}`,
|
||||
title: `Text input for ${props.storageKey}`,
|
||||
onChange: handleTextChange
|
||||
}));
|
||||
};
|
||||
var Dropdown = (props) => {
|
||||
const handleDropdownChange = (event) => {
|
||||
props.callback(event.target.value);
|
||||
};
|
||||
return /* @__PURE__ */ import_react.default.createElement("label", {
|
||||
className: "dropdown-wrapper"
|
||||
}, /* @__PURE__ */ import_react.default.createElement("select", {
|
||||
className: "dropdown-input",
|
||||
value: props.value,
|
||||
"data-storage-key": props.storageKey,
|
||||
id: `dropdown:${props.storageKey}`,
|
||||
title: `Dropdown for ${props.storageKey}`,
|
||||
onChange: handleDropdownChange
|
||||
}, props.options.map((option, index) => /* @__PURE__ */ import_react.default.createElement("option", {
|
||||
key: index,
|
||||
value: option
|
||||
}, option))));
|
||||
};
|
||||
var ToggleInput = (props) => {
|
||||
const { Toggle } = Spicetify.ReactComponent;
|
||||
const handleToggleChange = (newValue) => {
|
||||
props.callback(newValue);
|
||||
};
|
||||
return /* @__PURE__ */ import_react.default.createElement(Toggle, {
|
||||
id: `toggle:${props.storageKey}`,
|
||||
value: props.value,
|
||||
onSelected: (newValue) => handleToggleChange(newValue)
|
||||
});
|
||||
};
|
||||
var SliderInput = (props) => {
|
||||
const { Slider } = Spicetify.ReactComponent;
|
||||
const handleSliderChange = (newValue) => {
|
||||
const calculatedValue = props.min + newValue * (props.max - props.min);
|
||||
props.callback(calculatedValue);
|
||||
};
|
||||
const value = (props.value - props.min) / (props.max - props.min);
|
||||
return /* @__PURE__ */ import_react.default.createElement(Slider, {
|
||||
id: `slider:${props.storageKey}`,
|
||||
value,
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.1,
|
||||
onDragMove: (newValue) => handleSliderChange(newValue),
|
||||
onDragStart: () => {
|
||||
},
|
||||
onDragEnd: () => {
|
||||
}
|
||||
});
|
||||
};
|
||||
var TooltipIcon = () => {
|
||||
return /* @__PURE__ */ import_react.default.createElement("svg", {
|
||||
role: "img",
|
||||
height: "16",
|
||||
width: "16",
|
||||
className: "Svg-sc-ytk21e-0 uPxdw nW1RKQOkzcJcX6aDCZB4",
|
||||
viewBox: "0 0 16 16"
|
||||
}, /* @__PURE__ */ import_react.default.createElement("path", {
|
||||
d: "M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8z"
|
||||
}), /* @__PURE__ */ import_react.default.createElement("path", {
|
||||
d: "M7.25 12.026v-1.5h1.5v1.5h-1.5zm.884-7.096A1.125 1.125 0 007.06 6.39l-1.431.448a2.625 2.625 0 115.13-.784c0 .54-.156 1.015-.503 1.488-.3.408-.7.652-.973.818l-.112.068c-.185.116-.26.203-.302.283-.046.087-.097.245-.097.57h-1.5c0-.47.072-.898.274-1.277.206-.385.507-.645.827-.846l.147-.092c.285-.177.413-.257.526-.41.169-.23.213-.397.213-.602 0-.622-.503-1.125-1.125-1.125z"
|
||||
}));
|
||||
};
|
||||
var ConfigRow = (props) => {
|
||||
return /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
className: "setting-row"
|
||||
}, /* @__PURE__ */ import_react.default.createElement("label", {
|
||||
className: "col description"
|
||||
}, props.name, props.desc && /* @__PURE__ */ import_react.default.createElement(Spicetify.ReactComponent.TooltipWrapper, {
|
||||
label: /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
dangerouslySetInnerHTML: { __html: props.desc }
|
||||
}),
|
||||
renderInline: true,
|
||||
showDelay: 10,
|
||||
placement: "top",
|
||||
labelClassName: "tooltip",
|
||||
disabled: false
|
||||
}, /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
className: "tooltip-icon"
|
||||
}, /* @__PURE__ */ import_react.default.createElement(TooltipIcon, null)))), /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
className: "col action"
|
||||
}, props.children));
|
||||
};
|
||||
var ConfigModal = (props) => {
|
||||
const { config, structure, updateAppConfig } = props;
|
||||
const [modalConfig, setModalConfig] = import_react.default.useState(__spreadValues({}, config));
|
||||
const modalRows = structure.map((modalRow, index) => {
|
||||
const key = modalRow.key;
|
||||
const currentValue = modalConfig[key];
|
||||
const updateItem = (state) => {
|
||||
console.debug(`toggling ${key} to ${state}`);
|
||||
localStorage.setItem(`library:config:${key}`, String(state));
|
||||
if (modalRow.callback)
|
||||
modalRow.callback(state);
|
||||
const newConfig = __spreadValues({}, modalConfig);
|
||||
newConfig[key] = state;
|
||||
updateAppConfig(newConfig);
|
||||
setModalConfig(newConfig);
|
||||
};
|
||||
const header = modalRow.sectionHeader;
|
||||
const element = () => {
|
||||
switch (modalRow.type) {
|
||||
case "toggle":
|
||||
return /* @__PURE__ */ import_react.default.createElement(ToggleInput, {
|
||||
storageKey: key,
|
||||
value: currentValue,
|
||||
callback: updateItem
|
||||
});
|
||||
case "text":
|
||||
return /* @__PURE__ */ import_react.default.createElement(TextInput, {
|
||||
storageKey: key,
|
||||
value: currentValue,
|
||||
callback: updateItem
|
||||
});
|
||||
case "dropdown":
|
||||
return /* @__PURE__ */ import_react.default.createElement(Dropdown, {
|
||||
storageKey: key,
|
||||
value: currentValue,
|
||||
options: modalRow.options,
|
||||
callback: updateItem
|
||||
});
|
||||
case "slider":
|
||||
return /* @__PURE__ */ import_react.default.createElement(SliderInput, {
|
||||
storageKey: key,
|
||||
value: currentValue,
|
||||
min: modalRow.min,
|
||||
max: modalRow.max,
|
||||
step: modalRow.step,
|
||||
callback: updateItem
|
||||
});
|
||||
}
|
||||
};
|
||||
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, header && index !== 0 && /* @__PURE__ */ import_react.default.createElement("br", null), header && /* @__PURE__ */ import_react.default.createElement("h2", {
|
||||
className: "section-header"
|
||||
}, modalRow.sectionHeader), /* @__PURE__ */ import_react.default.createElement(ConfigRow, {
|
||||
name: modalRow.name,
|
||||
desc: modalRow.desc
|
||||
}, element()));
|
||||
});
|
||||
return /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
id: "library-config-container"
|
||||
}, modalRows);
|
||||
};
|
||||
var config_modal_default = ConfigModal;
|
||||
|
||||
// src/extensions/config_wrapper.tsx
|
||||
var _ConfigWrapper = class {
|
||||
constructor(modalStructure) {
|
||||
const config = modalStructure.map((modalStructureRow) => {
|
||||
var _a;
|
||||
const value = _ConfigWrapper.getLocalStorageDataFromKey(`library:config:${modalStructureRow.key}`, modalStructureRow.def);
|
||||
(_a = modalStructureRow.callback) == null ? void 0 : _a.call(modalStructureRow, value);
|
||||
return { [modalStructureRow.key]: value };
|
||||
});
|
||||
this.Config = Object.assign({}, ...config);
|
||||
this.launchModal = (callback) => {
|
||||
const updateConfig = (config2) => {
|
||||
this.Config = __spreadValues({}, config2);
|
||||
callback == null ? void 0 : callback(config2);
|
||||
};
|
||||
Spicetify.PopupModal.display({
|
||||
title: "Library Settings",
|
||||
content: /* @__PURE__ */ import_react2.default.createElement(config_modal_default, {
|
||||
config: this.Config,
|
||||
structure: modalStructure,
|
||||
updateAppConfig: updateConfig
|
||||
}),
|
||||
isLarge: true
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
var ConfigWrapper = _ConfigWrapper;
|
||||
ConfigWrapper.getLocalStorageDataFromKey = (key, fallback) => {
|
||||
const data = localStorage.getItem(key);
|
||||
if (data) {
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
} catch (err) {
|
||||
return data;
|
||||
}
|
||||
} else {
|
||||
return fallback;
|
||||
}
|
||||
};
|
||||
var config_wrapper_default = ConfigWrapper;
|
||||
return __toCommonJS(config_wrapper_exports);
|
||||
})();
|
||||
|
||||
})();
|
||||
19
config/spicetify/CustomApps/library/context_menu_handler.js
Normal file
19
config/spicetify/CustomApps/library/context_menu_handler.js
Normal file
@@ -0,0 +1,19 @@
|
||||
(async function() {
|
||||
while (!Spicetify.React || !Spicetify.ReactDOM) {
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
}
|
||||
"use strict";
|
||||
var library = (() => {
|
||||
// src/extensions/context_menu_handler.tsx
|
||||
var observer = new MutationObserver((mutations) => {
|
||||
mutations.forEach((mutation) => {
|
||||
if (mutation.addedNodes.length) {
|
||||
const node = mutation.addedNodes[0];
|
||||
console.log(node);
|
||||
}
|
||||
});
|
||||
});
|
||||
observer.observe(document.body, { childList: true, subtree: false });
|
||||
})();
|
||||
|
||||
})();
|
||||
983
config/spicetify/CustomApps/library/extension.js
Normal file
983
config/spicetify/CustomApps/library/extension.js
Normal file
@@ -0,0 +1,983 @@
|
||||
(async function() {
|
||||
while (!Spicetify.React || !Spicetify.ReactDOM) {
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
}
|
||||
"use strict";
|
||||
var library = (() => {
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __publicField = (obj, key, value) => {
|
||||
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
||||
return value;
|
||||
};
|
||||
|
||||
// external-global-plugin:react
|
||||
var require_react = __commonJS({
|
||||
"external-global-plugin:react"(exports, module) {
|
||||
module.exports = Spicetify.React;
|
||||
}
|
||||
});
|
||||
|
||||
// external-global-plugin:react-dom
|
||||
var require_react_dom = __commonJS({
|
||||
"external-global-plugin:react-dom"(exports, module) {
|
||||
module.exports = Spicetify.ReactDOM;
|
||||
}
|
||||
});
|
||||
|
||||
// ../shared/config/config_wrapper.tsx
|
||||
var import_react2 = __toESM(require_react());
|
||||
|
||||
// ../shared/config/config_modal.tsx
|
||||
var import_react = __toESM(require_react());
|
||||
var TextInput = (props) => {
|
||||
const handleTextChange = (event) => {
|
||||
props.callback(event.target.value);
|
||||
};
|
||||
return /* @__PURE__ */ import_react.default.createElement("label", {
|
||||
className: "text-input-wrapper"
|
||||
}, /* @__PURE__ */ import_react.default.createElement("input", {
|
||||
className: "text-input",
|
||||
type: "text",
|
||||
value: props.value || "",
|
||||
"data-storage-key": props.storageKey,
|
||||
placeholder: props.placeholder,
|
||||
id: `text-input:${props.storageKey}`,
|
||||
title: `Text input for ${props.storageKey}`,
|
||||
onChange: handleTextChange
|
||||
}));
|
||||
};
|
||||
var Dropdown = (props) => {
|
||||
const handleDropdownChange = (event) => {
|
||||
props.callback(event.target.value);
|
||||
};
|
||||
return /* @__PURE__ */ import_react.default.createElement("label", {
|
||||
className: "dropdown-wrapper"
|
||||
}, /* @__PURE__ */ import_react.default.createElement("select", {
|
||||
className: "dropdown-input",
|
||||
value: props.value,
|
||||
"data-storage-key": props.storageKey,
|
||||
id: `dropdown:${props.storageKey}`,
|
||||
title: `Dropdown for ${props.storageKey}`,
|
||||
onChange: handleDropdownChange
|
||||
}, props.options.map((option, index) => /* @__PURE__ */ import_react.default.createElement("option", {
|
||||
key: index,
|
||||
value: option
|
||||
}, option))));
|
||||
};
|
||||
var ToggleInput = (props) => {
|
||||
const { Toggle } = Spicetify.ReactComponent;
|
||||
const handleToggleChange = (newValue) => {
|
||||
props.callback(newValue);
|
||||
};
|
||||
return /* @__PURE__ */ import_react.default.createElement(Toggle, {
|
||||
id: `toggle:${props.storageKey}`,
|
||||
value: props.value,
|
||||
onSelected: (newValue) => handleToggleChange(newValue)
|
||||
});
|
||||
};
|
||||
var SliderInput = (props) => {
|
||||
const { Slider } = Spicetify.ReactComponent;
|
||||
const handleSliderChange = (newValue) => {
|
||||
const calculatedValue = props.min + newValue * (props.max - props.min);
|
||||
props.callback(calculatedValue);
|
||||
};
|
||||
const value = (props.value - props.min) / (props.max - props.min);
|
||||
return /* @__PURE__ */ import_react.default.createElement(Slider, {
|
||||
id: `slider:${props.storageKey}`,
|
||||
value,
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.1,
|
||||
onDragMove: (newValue) => handleSliderChange(newValue),
|
||||
onDragStart: () => {
|
||||
},
|
||||
onDragEnd: () => {
|
||||
}
|
||||
});
|
||||
};
|
||||
var TooltipIcon = () => {
|
||||
return /* @__PURE__ */ import_react.default.createElement("svg", {
|
||||
role: "img",
|
||||
height: "16",
|
||||
width: "16",
|
||||
className: "Svg-sc-ytk21e-0 uPxdw nW1RKQOkzcJcX6aDCZB4",
|
||||
viewBox: "0 0 16 16"
|
||||
}, /* @__PURE__ */ import_react.default.createElement("path", {
|
||||
d: "M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8z"
|
||||
}), /* @__PURE__ */ import_react.default.createElement("path", {
|
||||
d: "M7.25 12.026v-1.5h1.5v1.5h-1.5zm.884-7.096A1.125 1.125 0 007.06 6.39l-1.431.448a2.625 2.625 0 115.13-.784c0 .54-.156 1.015-.503 1.488-.3.408-.7.652-.973.818l-.112.068c-.185.116-.26.203-.302.283-.046.087-.097.245-.097.57h-1.5c0-.47.072-.898.274-1.277.206-.385.507-.645.827-.846l.147-.092c.285-.177.413-.257.526-.41.169-.23.213-.397.213-.602 0-.622-.503-1.125-1.125-1.125z"
|
||||
}));
|
||||
};
|
||||
var ConfigRow = (props) => {
|
||||
return /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
className: "setting-row"
|
||||
}, /* @__PURE__ */ import_react.default.createElement("label", {
|
||||
className: "col description"
|
||||
}, props.name, props.desc && /* @__PURE__ */ import_react.default.createElement(Spicetify.ReactComponent.TooltipWrapper, {
|
||||
label: /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
dangerouslySetInnerHTML: { __html: props.desc }
|
||||
}),
|
||||
renderInline: true,
|
||||
showDelay: 10,
|
||||
placement: "top",
|
||||
labelClassName: "tooltip",
|
||||
disabled: false
|
||||
}, /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
className: "tooltip-icon"
|
||||
}, /* @__PURE__ */ import_react.default.createElement(TooltipIcon, null)))), /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
className: "col action"
|
||||
}, props.children));
|
||||
};
|
||||
var ConfigModal = (props) => {
|
||||
const { config, structure, appKey, updateAppConfig } = props;
|
||||
const [modalConfig, setModalConfig] = import_react.default.useState({ ...config });
|
||||
const modalRows = structure.map((modalRow, index) => {
|
||||
const key = modalRow.key;
|
||||
const currentValue = modalConfig[key];
|
||||
const updateItem = (state) => {
|
||||
console.debug(`toggling ${key} to ${state}`);
|
||||
localStorage.setItem(`${appKey}:config:${key}`, String(state));
|
||||
if (modalRow.callback)
|
||||
modalRow.callback(state);
|
||||
const newConfig = { ...modalConfig };
|
||||
newConfig[key] = state;
|
||||
updateAppConfig(newConfig);
|
||||
setModalConfig(newConfig);
|
||||
};
|
||||
const header = modalRow.sectionHeader;
|
||||
const element = () => {
|
||||
switch (modalRow.type) {
|
||||
case "toggle":
|
||||
return /* @__PURE__ */ import_react.default.createElement(ToggleInput, {
|
||||
storageKey: key,
|
||||
value: currentValue,
|
||||
callback: updateItem
|
||||
});
|
||||
case "text":
|
||||
return /* @__PURE__ */ import_react.default.createElement(TextInput, {
|
||||
storageKey: key,
|
||||
value: currentValue,
|
||||
callback: updateItem
|
||||
});
|
||||
case "dropdown":
|
||||
return /* @__PURE__ */ import_react.default.createElement(Dropdown, {
|
||||
storageKey: key,
|
||||
value: currentValue,
|
||||
options: modalRow.options,
|
||||
callback: updateItem
|
||||
});
|
||||
case "slider":
|
||||
return /* @__PURE__ */ import_react.default.createElement(SliderInput, {
|
||||
storageKey: key,
|
||||
value: currentValue,
|
||||
min: modalRow.min,
|
||||
max: modalRow.max,
|
||||
step: modalRow.step,
|
||||
callback: updateItem
|
||||
});
|
||||
}
|
||||
};
|
||||
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, header && index !== 0 && /* @__PURE__ */ import_react.default.createElement("br", null), header && /* @__PURE__ */ import_react.default.createElement("h2", {
|
||||
className: "section-header"
|
||||
}, modalRow.sectionHeader), /* @__PURE__ */ import_react.default.createElement(ConfigRow, {
|
||||
name: modalRow.name,
|
||||
desc: modalRow.desc
|
||||
}, element()));
|
||||
});
|
||||
return /* @__PURE__ */ import_react.default.createElement("div", {
|
||||
className: "config-container"
|
||||
}, modalRows);
|
||||
};
|
||||
var config_modal_default = ConfigModal;
|
||||
|
||||
// ../shared/config/config_wrapper.tsx
|
||||
var _ConfigWrapper = class {
|
||||
Config;
|
||||
launchModal;
|
||||
constructor(modalStructure, key) {
|
||||
const config = modalStructure.map((modalStructureRow) => {
|
||||
const value = _ConfigWrapper.getLocalStorageDataFromKey(
|
||||
`${key}:config:${modalStructureRow.key}`,
|
||||
modalStructureRow.def
|
||||
);
|
||||
modalStructureRow.callback?.(value);
|
||||
return { [modalStructureRow.key]: value };
|
||||
});
|
||||
this.Config = Object.assign({}, ...config);
|
||||
this.launchModal = (callback) => {
|
||||
const updateConfig = (config2) => {
|
||||
this.Config = { ...config2 };
|
||||
callback?.(config2);
|
||||
};
|
||||
Spicetify.PopupModal.display({
|
||||
title: `${key.charAt(0).toUpperCase() + key.slice(1)} Settings`,
|
||||
content: /* @__PURE__ */ import_react2.default.createElement(config_modal_default, {
|
||||
config: this.Config,
|
||||
structure: modalStructure,
|
||||
appKey: key,
|
||||
updateAppConfig: updateConfig
|
||||
}),
|
||||
isLarge: true
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
var ConfigWrapper = _ConfigWrapper;
|
||||
__publicField(ConfigWrapper, "getLocalStorageDataFromKey", (key, fallback) => {
|
||||
const data = localStorage.getItem(key);
|
||||
if (data) {
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
} catch (err) {
|
||||
return data;
|
||||
}
|
||||
} else {
|
||||
return fallback;
|
||||
}
|
||||
});
|
||||
var config_wrapper_default = ConfigWrapper;
|
||||
|
||||
// src/extensions/extension.tsx
|
||||
var import_react10 = __toESM(require_react());
|
||||
var import_react_dom = __toESM(require_react_dom());
|
||||
|
||||
// src/components/toggle_filters.tsx
|
||||
var import_react3 = __toESM(require_react());
|
||||
var UpIcon = () => {
|
||||
const { IconComponent } = Spicetify.ReactComponent;
|
||||
return /* @__PURE__ */ import_react3.default.createElement(IconComponent, {
|
||||
semanticColor: "textSubdued",
|
||||
dangerouslySetInnerHTML: {
|
||||
__html: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M.998 8.81A.749.749 0 0 1 .47 7.53L7.99 0l7.522 7.53a.75.75 0 1 1-1.06 1.06L8.74 2.87v12.38a.75.75 0 1 1-1.498 0V2.87L1.528 8.59a.751.751 0 0 1-.53.22z"></path></svg>'
|
||||
},
|
||||
iconSize: 16
|
||||
});
|
||||
};
|
||||
var DownIcon = () => {
|
||||
const { IconComponent } = Spicetify.ReactComponent;
|
||||
return /* @__PURE__ */ import_react3.default.createElement(IconComponent, {
|
||||
semanticColor: "textSubdued",
|
||||
dangerouslySetInnerHTML: {
|
||||
__html: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M.998 7.19A.749.749 0 0 0 .47 8.47L7.99 16l7.522-7.53a.75.75 0 1 0-1.06-1.06L8.74 13.13V.75a.75.75 0 1 0-1.498 0v12.38L1.528 7.41a.749.749 0 0 0-.53-.22z"></path></svg>'
|
||||
},
|
||||
iconSize: 16
|
||||
});
|
||||
};
|
||||
var ToggleFiltersButton = () => {
|
||||
const [direction, setDirection] = import_react3.default.useState(
|
||||
document.body.classList.contains("show-ylx-filters") ? "up" : "down"
|
||||
);
|
||||
const { ButtonTertiary } = Spicetify.ReactComponent;
|
||||
const toggleDirection = () => {
|
||||
if (direction === "down") {
|
||||
document.body.classList.add("show-ylx-filters");
|
||||
setDirection("up");
|
||||
} else {
|
||||
setDirection("down");
|
||||
document.body.classList.remove("show-ylx-filters");
|
||||
}
|
||||
};
|
||||
const Icon = direction === "down" ? DownIcon : UpIcon;
|
||||
return /* @__PURE__ */ import_react3.default.createElement(ButtonTertiary, {
|
||||
buttonSize: "sm",
|
||||
"aria-label": "Show Filters",
|
||||
iconOnly: Icon,
|
||||
onClick: toggleDirection
|
||||
});
|
||||
};
|
||||
var toggle_filters_default = ToggleFiltersButton;
|
||||
|
||||
// src/components/collapse_button.tsx
|
||||
var import_react4 = __toESM(require_react());
|
||||
var collapseLibrary = () => {
|
||||
Spicetify.Platform.LocalStorageAPI.setItem("ylx-sidebar-state", 1);
|
||||
};
|
||||
var CollapseIcon = () => {
|
||||
const { IconComponent } = Spicetify.ReactComponent;
|
||||
return /* @__PURE__ */ import_react4.default.createElement(IconComponent, {
|
||||
semanticColor: "textSubdued",
|
||||
dangerouslySetInnerHTML: {
|
||||
__html: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M8.81 1A.749.749 0 0 0 7.53.47L0 7.99l7.53 7.521a.75.75 0 0 0 1.234-.815.75.75 0 0 0-.174-.243L2.87 8.74h12.38a.75.75 0 1 0 0-1.498H2.87l5.72-5.713c.14-.14.22-.331.22-.53z"></path></svg>'
|
||||
},
|
||||
iconSize: 16
|
||||
});
|
||||
};
|
||||
var CollapseButton = () => {
|
||||
const { ButtonTertiary } = Spicetify.ReactComponent;
|
||||
return /* @__PURE__ */ import_react4.default.createElement(ButtonTertiary, {
|
||||
buttonSize: "sm",
|
||||
"aria-label": "Show Filters",
|
||||
iconOnly: CollapseIcon,
|
||||
onClick: collapseLibrary
|
||||
});
|
||||
};
|
||||
var collapse_button_default = CollapseButton;
|
||||
|
||||
// src/components/album_menu_item.tsx
|
||||
var import_react8 = __toESM(require_react());
|
||||
|
||||
// src/components/leading_icon.tsx
|
||||
var import_react5 = __toESM(require_react());
|
||||
var LeadingIcon = ({ path }) => {
|
||||
return /* @__PURE__ */ import_react5.default.createElement(Spicetify.ReactComponent.IconComponent, {
|
||||
semanticColor: "textSubdued",
|
||||
dangerouslySetInnerHTML: {
|
||||
__html: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">${path}</svg>`
|
||||
},
|
||||
iconSize: 16
|
||||
});
|
||||
};
|
||||
var leading_icon_default = LeadingIcon;
|
||||
|
||||
// src/components/text_input_dialog.tsx
|
||||
var import_react6 = __toESM(require_react());
|
||||
var TextInputDialog = (props) => {
|
||||
const { def, placeholder, onSave } = props;
|
||||
const [value, setValue] = import_react6.default.useState(def || "");
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
Spicetify.PopupModal.hide();
|
||||
onSave(value);
|
||||
};
|
||||
return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement("form", {
|
||||
className: "text-input-form",
|
||||
onSubmit
|
||||
}, /* @__PURE__ */ import_react6.default.createElement("label", {
|
||||
className: "text-input-wrapper"
|
||||
}, /* @__PURE__ */ import_react6.default.createElement("input", {
|
||||
className: "text-input",
|
||||
type: "text",
|
||||
value,
|
||||
placeholder,
|
||||
onChange: (e) => setValue(e.target.value)
|
||||
})), /* @__PURE__ */ import_react6.default.createElement("button", {
|
||||
type: "submit",
|
||||
"data-encore-id": "buttonPrimary",
|
||||
className: "Button-sc-qlcn5g-0 Button-small-buttonPrimary"
|
||||
}, /* @__PURE__ */ import_react6.default.createElement("span", {
|
||||
className: "ButtonInner-sc-14ud5tc-0 ButtonInner-small encore-bright-accent-set"
|
||||
}, "Save"))));
|
||||
};
|
||||
var text_input_dialog_default = TextInputDialog;
|
||||
|
||||
// src/components/searchbar.tsx
|
||||
var import_react7 = __toESM(require_react());
|
||||
var SearchBar = (props) => {
|
||||
const { setSearch, placeholder } = props;
|
||||
const handleChange = (e) => {
|
||||
setSearch(e.target.value);
|
||||
};
|
||||
return /* @__PURE__ */ import_react7.default.createElement("div", {
|
||||
className: "x-filterBox-filterInputContainer x-filterBox-expandedOrHasFilter",
|
||||
role: "search"
|
||||
}, /* @__PURE__ */ import_react7.default.createElement("input", {
|
||||
type: "text",
|
||||
className: "x-filterBox-filterInput",
|
||||
role: "searchbox",
|
||||
maxLength: 80,
|
||||
autoCorrect: "off",
|
||||
autoCapitalize: "off",
|
||||
spellCheck: "false",
|
||||
placeholder: `Search ${placeholder}`,
|
||||
"aria-hidden": "false",
|
||||
onChange: handleChange
|
||||
}), /* @__PURE__ */ import_react7.default.createElement("div", {
|
||||
className: "x-filterBox-overlay"
|
||||
}, /* @__PURE__ */ import_react7.default.createElement("span", {
|
||||
className: "x-filterBox-searchIconContainer"
|
||||
}, /* @__PURE__ */ import_react7.default.createElement("svg", {
|
||||
"data-encore-id": "icon",
|
||||
role: "img",
|
||||
"aria-hidden": "true",
|
||||
className: "Svg-sc-ytk21e-0 Svg-img-icon-small x-filterBox-searchIcon",
|
||||
viewBox: "0 0 16 16"
|
||||
}, /* @__PURE__ */ import_react7.default.createElement("path", {
|
||||
d: "M7 1.75a5.25 5.25 0 1 0 0 10.5 5.25 5.25 0 0 0 0-10.5zM.25 7a6.75 6.75 0 1 1 12.096 4.12l3.184 3.185a.75.75 0 1 1-1.06 1.06L11.304 12.2A6.75 6.75 0 0 1 .25 7z"
|
||||
})))), /* @__PURE__ */ import_react7.default.createElement("button", {
|
||||
className: "x-filterBox-expandButton",
|
||||
"aria-hidden": "false",
|
||||
"aria-label": "Search Playlists",
|
||||
type: "button"
|
||||
}, /* @__PURE__ */ import_react7.default.createElement("svg", {
|
||||
"data-encore-id": "icon",
|
||||
role: "img",
|
||||
"aria-hidden": "true",
|
||||
className: "Svg-sc-ytk21e-0 Svg-img-icon-small x-filterBox-searchIcon",
|
||||
viewBox: "0 0 16 16"
|
||||
}, /* @__PURE__ */ import_react7.default.createElement("path", {
|
||||
d: "M7 1.75a5.25 5.25 0 1 0 0 10.5 5.25 5.25 0 0 0 0-10.5zM.25 7a6.75 6.75 0 1 1 12.096 4.12l3.184 3.185a.75.75 0 1 1-1.06 1.06L11.304 12.2A6.75 6.75 0 0 1 .25 7z"
|
||||
}))));
|
||||
};
|
||||
var searchbar_default = SearchBar;
|
||||
|
||||
// src/components/album_menu_item.tsx
|
||||
var createCollection = () => {
|
||||
const onSave = (value) => {
|
||||
CollectionsWrapper.createCollection(value);
|
||||
};
|
||||
Spicetify.PopupModal.display({
|
||||
title: "Create Collection",
|
||||
content: /* @__PURE__ */ import_react8.default.createElement(text_input_dialog_default, {
|
||||
def: "New Collection",
|
||||
placeholder: "Collection Name",
|
||||
onSave
|
||||
})
|
||||
});
|
||||
};
|
||||
var CollectionSearchMenu = () => {
|
||||
const { MenuItem } = Spicetify.ReactComponent;
|
||||
const { SVGIcons } = Spicetify;
|
||||
const [textFilter, setTextFilter] = import_react8.default.useState("");
|
||||
const [collections, setCollections] = import_react8.default.useState(null);
|
||||
const context = import_react8.default.useContext(Spicetify.ContextMenuV2._context);
|
||||
const uri = context?.props?.uri;
|
||||
import_react8.default.useEffect(() => {
|
||||
const fetchCollections = async () => {
|
||||
setCollections(await CollectionsWrapper.getContents({ textFilter, limit: 20, offset: 0 }));
|
||||
};
|
||||
fetchCollections();
|
||||
}, [textFilter]);
|
||||
if (!collections)
|
||||
return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null);
|
||||
const addToCollection = (collectionUri) => {
|
||||
CollectionsWrapper.addAlbumToCollection(collectionUri, uri);
|
||||
};
|
||||
const activeCollections = CollectionsWrapper.getCollectionsWithAlbum(uri);
|
||||
const hasCollections = activeCollections.length > 0;
|
||||
const removeFromCollections = () => {
|
||||
for (const collection of activeCollections) {
|
||||
CollectionsWrapper.removeAlbumFromCollection(collection.uri, uri);
|
||||
}
|
||||
};
|
||||
const allCollectionsLength = collections.totalLength;
|
||||
const menuItems = collections.items.map((collection, index) => {
|
||||
return /* @__PURE__ */ import_react8.default.createElement(MenuItem, {
|
||||
key: collection.uri,
|
||||
onClick: () => {
|
||||
addToCollection(collection.uri);
|
||||
},
|
||||
divider: index === 0 ? "before" : void 0
|
||||
}, collection.name);
|
||||
});
|
||||
const menuLength = allCollectionsLength + (hasCollections ? 1 : 0);
|
||||
return /* @__PURE__ */ import_react8.default.createElement("div", {
|
||||
className: "main-contextMenu-filterPlaylistSearchContainer",
|
||||
style: { "--context-menu-submenu-length": `${menuLength}` }
|
||||
}, /* @__PURE__ */ import_react8.default.createElement("li", {
|
||||
role: "presentation",
|
||||
className: "main-contextMenu-filterPlaylistSearch"
|
||||
}, /* @__PURE__ */ import_react8.default.createElement("div", {
|
||||
role: "menuitem"
|
||||
}, /* @__PURE__ */ import_react8.default.createElement(searchbar_default, {
|
||||
setSearch: setTextFilter,
|
||||
placeholder: "collections"
|
||||
}))), /* @__PURE__ */ import_react8.default.createElement(MenuItem, {
|
||||
key: "new-collection",
|
||||
leadingIcon: /* @__PURE__ */ import_react8.default.createElement(leading_icon_default, {
|
||||
path: SVGIcons.plus2px
|
||||
}),
|
||||
onClick: createCollection
|
||||
}, "Create collection"), hasCollections && /* @__PURE__ */ import_react8.default.createElement(MenuItem, {
|
||||
key: "remove-collection",
|
||||
leadingIcon: /* @__PURE__ */ import_react8.default.createElement(leading_icon_default, {
|
||||
path: SVGIcons.minus
|
||||
}),
|
||||
onClick: removeFromCollections
|
||||
}, "Remove from all"), menuItems);
|
||||
};
|
||||
var AlbumMenuItem = () => {
|
||||
const { MenuSubMenuItem } = Spicetify.ReactComponent;
|
||||
const { SVGIcons } = Spicetify;
|
||||
return /* @__PURE__ */ import_react8.default.createElement(MenuSubMenuItem, {
|
||||
displayText: "Add to collection",
|
||||
divider: "after",
|
||||
leadingIcon: /* @__PURE__ */ import_react8.default.createElement(leading_icon_default, {
|
||||
path: SVGIcons.plus2px
|
||||
})
|
||||
}, /* @__PURE__ */ import_react8.default.createElement(CollectionSearchMenu, null));
|
||||
};
|
||||
var album_menu_item_default = AlbumMenuItem;
|
||||
|
||||
// src/components/artist_menu_item.tsx
|
||||
var import_react9 = __toESM(require_react());
|
||||
var ArtistMenuItem = () => {
|
||||
const { MenuItem } = Spicetify.ReactComponent;
|
||||
const { SVGIcons } = Spicetify;
|
||||
const context = import_react9.default.useContext(Spicetify.ContextMenuV2._context);
|
||||
const uri = context?.props?.uri;
|
||||
return /* @__PURE__ */ import_react9.default.createElement(MenuItem, {
|
||||
divider: "after",
|
||||
leadingIcon: /* @__PURE__ */ import_react9.default.createElement(leading_icon_default, {
|
||||
path: SVGIcons.plus2px
|
||||
}),
|
||||
onClick: () => CollectionsWrapper.createCollectionFromDiscog(uri)
|
||||
}, "Create Discog Collection");
|
||||
};
|
||||
var artist_menu_item_default = ArtistMenuItem;
|
||||
|
||||
// ../node_modules/uuid/dist/esm-browser/rng.js
|
||||
var getRandomValues;
|
||||
var rnds8 = new Uint8Array(16);
|
||||
function rng() {
|
||||
if (!getRandomValues) {
|
||||
getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
|
||||
if (!getRandomValues) {
|
||||
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
||||
}
|
||||
}
|
||||
return getRandomValues(rnds8);
|
||||
}
|
||||
|
||||
// ../node_modules/uuid/dist/esm-browser/stringify.js
|
||||
var byteToHex = [];
|
||||
for (let i = 0; i < 256; ++i) {
|
||||
byteToHex.push((i + 256).toString(16).slice(1));
|
||||
}
|
||||
function unsafeStringify(arr, offset = 0) {
|
||||
return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
|
||||
}
|
||||
|
||||
// ../node_modules/uuid/dist/esm-browser/native.js
|
||||
var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
||||
var native_default = {
|
||||
randomUUID
|
||||
};
|
||||
|
||||
// ../node_modules/uuid/dist/esm-browser/v4.js
|
||||
function v4(options, buf, offset) {
|
||||
if (native_default.randomUUID && !buf && !options) {
|
||||
return native_default.randomUUID();
|
||||
}
|
||||
options = options || {};
|
||||
const rnds = options.random || (options.rng || rng)();
|
||||
rnds[6] = rnds[6] & 15 | 64;
|
||||
rnds[8] = rnds[8] & 63 | 128;
|
||||
if (buf) {
|
||||
offset = offset || 0;
|
||||
for (let i = 0; i < 16; ++i) {
|
||||
buf[offset + i] = rnds[i];
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
return unsafeStringify(rnds);
|
||||
}
|
||||
var v4_default = v4;
|
||||
|
||||
// src/extensions/collections_wrapper.ts
|
||||
var _CollectionsWrapper = class extends EventTarget {
|
||||
_collections;
|
||||
constructor() {
|
||||
super();
|
||||
this._collections = JSON.parse(localStorage.getItem("library:collections") || "[]");
|
||||
}
|
||||
saveCollections() {
|
||||
localStorage.setItem("library:collections", JSON.stringify(this._collections));
|
||||
this.dispatchEvent(new CustomEvent("update", { detail: this._collections }));
|
||||
}
|
||||
getCollection(uri) {
|
||||
return this._collections.find((collection) => collection.uri === uri);
|
||||
}
|
||||
async getCollectionContents(uri) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
throw new Error("Collection not found");
|
||||
const items = this._collections.filter((collection2) => collection2.parentCollection === uri);
|
||||
const albums = await Spicetify.Platform.LibraryAPI.getContents({
|
||||
filters: ["0"],
|
||||
offset: 0,
|
||||
limit: 9999
|
||||
});
|
||||
items.push(...albums.items.filter((album) => collection.items.includes(album.uri)));
|
||||
return items;
|
||||
}
|
||||
async getContents(props) {
|
||||
const { collectionUri, offset, limit, textFilter } = props;
|
||||
let items = collectionUri ? await this.getCollectionContents(collectionUri) : this._collections;
|
||||
const openedCollectionName = collectionUri ? this.getCollection(collectionUri)?.name : void 0;
|
||||
if (textFilter) {
|
||||
const regex = new RegExp(`\\b${textFilter}`, "i");
|
||||
items = items.filter((collection) => regex.test(collection.name));
|
||||
}
|
||||
items = items.slice(offset, offset + limit);
|
||||
return { items, totalLength: this._collections.length, offset, openedCollectionName };
|
||||
}
|
||||
async cleanCollections() {
|
||||
for (const collection of this._collections) {
|
||||
const boolArray = await Spicetify.Platform.LibraryAPI.contains(...collection.items);
|
||||
if (boolArray.includes(false)) {
|
||||
collection.items = collection.items.filter((_, i) => boolArray[i]);
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Album removed from collection");
|
||||
this.syncCollection(collection.uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
async syncCollection(uri) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
const { PlaylistAPI } = Spicetify.Platform;
|
||||
if (!collection.syncedPlaylistUri)
|
||||
return;
|
||||
const playlist = await PlaylistAPI.getPlaylist(collection.syncedPlaylistUri);
|
||||
const playlistTracks = playlist.contents.items.filter((t) => t.type === "track").map((t) => t.uri);
|
||||
const collectionTracks = await this.getTracklist(uri);
|
||||
const wanted = collectionTracks.filter((track) => !playlistTracks.includes(track));
|
||||
const unwanted = playlistTracks.filter((track) => !collectionTracks.includes(track)).map((uri2) => ({ uri: uri2, uid: [] }));
|
||||
if (wanted.length)
|
||||
await PlaylistAPI.add(collection.syncedPlaylistUri, wanted, { before: "end" });
|
||||
if (unwanted.length)
|
||||
await PlaylistAPI.remove(collection.syncedPlaylistUri, unwanted);
|
||||
}
|
||||
unsyncCollection(uri) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
collection.syncedPlaylistUri = void 0;
|
||||
this.saveCollections();
|
||||
}
|
||||
async getTracklist(collectionUri) {
|
||||
const collection = this.getCollection(collectionUri);
|
||||
if (!collection)
|
||||
return [];
|
||||
return Promise.all(
|
||||
collection.items.map(async (uri) => {
|
||||
const album = await Spicetify.Platform.LibraryAPI.getAlbum(uri);
|
||||
return album.items.map((t) => t.uri);
|
||||
})
|
||||
).then((tracks) => tracks.flat());
|
||||
}
|
||||
async convertToPlaylist(uri) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
const { Platform, showNotification } = Spicetify;
|
||||
const { RootlistAPI, PlaylistAPI } = Platform;
|
||||
if (collection.syncedPlaylistUri) {
|
||||
showNotification("Synced Playlist already exists", true);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const playlistUri = await RootlistAPI.createPlaylist(collection.name, { before: "start" });
|
||||
const items = await this.getTracklist(uri);
|
||||
await PlaylistAPI.add(playlistUri, items, { before: "start" });
|
||||
collection.syncedPlaylistUri = playlistUri;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
showNotification("Failed to create playlist", true);
|
||||
}
|
||||
}
|
||||
async createCollectionFromDiscog(artistUri) {
|
||||
const [raw, info] = await Promise.all([
|
||||
Spicetify.GraphQL.Request(Spicetify.GraphQL.Definitions.queryArtistDiscographyAlbums, {
|
||||
uri: artistUri,
|
||||
offset: 0,
|
||||
limit: 50
|
||||
}),
|
||||
Spicetify.GraphQL.Request(Spicetify.GraphQL.Definitions.queryArtistOverview, {
|
||||
uri: artistUri,
|
||||
locale: Spicetify.Locale.getLocale(),
|
||||
includePrerelease: false
|
||||
})
|
||||
]);
|
||||
const items = raw?.data?.artistUnion.discography.albums?.items;
|
||||
const name = info?.data?.artistUnion.profile.name;
|
||||
const image = info?.data?.artistUnion.visuals.avatarImage?.sources?.[0]?.url;
|
||||
if (!name || !items?.length) {
|
||||
Spicetify.showNotification("Artist not found or has no albums");
|
||||
return;
|
||||
}
|
||||
const collectionUri = this.createCollection(`${name} Albums`);
|
||||
if (image)
|
||||
this.setCollectionImage(collectionUri, image);
|
||||
for (const album of items) {
|
||||
this.addAlbumToCollection(collectionUri, album.releases.items[0].uri);
|
||||
}
|
||||
}
|
||||
createCollection(name, parentCollection = "") {
|
||||
const id = v4_default();
|
||||
this._collections.push({
|
||||
type: "collection",
|
||||
uri: id,
|
||||
name,
|
||||
items: [],
|
||||
addedAt: new Date(),
|
||||
lastPlayedAt: new Date(),
|
||||
parentCollection
|
||||
});
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection created");
|
||||
return id;
|
||||
}
|
||||
deleteCollection(uri) {
|
||||
this._collections = this._collections.filter((collection) => collection.uri !== uri);
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection deleted");
|
||||
}
|
||||
deleteCollectionAndAlbums(uri) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
for (const album of collection.items) {
|
||||
Spicetify.Platform.LibraryAPI.remove({ uris: [album] });
|
||||
}
|
||||
this.deleteCollection(uri);
|
||||
}
|
||||
async addAlbumToCollection(collectionUri, albumUri) {
|
||||
const collection = this.getCollection(collectionUri);
|
||||
if (!collection)
|
||||
return;
|
||||
await Spicetify.Platform.LibraryAPI.add({ uris: [albumUri] });
|
||||
collection.items.push(albumUri);
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Album added to collection");
|
||||
this.syncCollection(collectionUri);
|
||||
}
|
||||
removeAlbumFromCollection(collectionUri, albumUri) {
|
||||
const collection = this.getCollection(collectionUri);
|
||||
if (!collection)
|
||||
return;
|
||||
collection.items = collection.items.filter((item) => item !== albumUri);
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Album removed from collection");
|
||||
this.syncCollection(collectionUri);
|
||||
}
|
||||
getCollectionsWithAlbum(albumUri) {
|
||||
return this._collections.filter((collection) => {
|
||||
return collection.items.some((item) => item === albumUri);
|
||||
});
|
||||
}
|
||||
renameCollection(uri, name) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
collection.name = name;
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection renamed");
|
||||
}
|
||||
setCollectionImage(uri, url) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
collection.image = url;
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection image set");
|
||||
}
|
||||
removeCollectionImage(uri) {
|
||||
const collection = this.getCollection(uri);
|
||||
if (!collection)
|
||||
return;
|
||||
collection.image = void 0;
|
||||
this.saveCollections();
|
||||
Spicetify.showNotification("Collection image removed");
|
||||
}
|
||||
};
|
||||
var CollectionsWrapper2 = _CollectionsWrapper;
|
||||
__publicField(CollectionsWrapper2, "INSTANCE", new _CollectionsWrapper());
|
||||
window.CollectionsWrapper = CollectionsWrapper2.INSTANCE;
|
||||
|
||||
// src/extensions/folder_image_wrapper.ts
|
||||
var _FolderImageWrapper = class extends EventTarget {
|
||||
_folderImages;
|
||||
constructor() {
|
||||
super();
|
||||
this._folderImages = JSON.parse(localStorage.getItem("library:folderImages") || "{}");
|
||||
}
|
||||
getFolderImage(uri) {
|
||||
return this._folderImages[uri];
|
||||
}
|
||||
getFolderImages() {
|
||||
return this._folderImages;
|
||||
}
|
||||
setFolderImage({ uri, url }) {
|
||||
this._folderImages[uri] = url;
|
||||
this.saveFolderImages();
|
||||
Spicetify.showNotification("Folder image updated");
|
||||
}
|
||||
removeFolderImage(uri) {
|
||||
delete this._folderImages[uri];
|
||||
this.saveFolderImages();
|
||||
Spicetify.showNotification("Folder image removed");
|
||||
}
|
||||
saveFolderImages() {
|
||||
this.dispatchEvent(new CustomEvent("update", { detail: this._folderImages }));
|
||||
localStorage.setItem("library:folderImages", JSON.stringify(this._folderImages));
|
||||
}
|
||||
};
|
||||
var FolderImageWrapper2 = _FolderImageWrapper;
|
||||
__publicField(FolderImageWrapper2, "INSTANCE", new _FolderImageWrapper());
|
||||
window.FolderImageWrapper = FolderImageWrapper2.INSTANCE;
|
||||
|
||||
// src/extensions/extension.tsx
|
||||
var styleLink = document.createElement("link");
|
||||
styleLink.rel = "stylesheet";
|
||||
styleLink.href = "/spicetify-routes-library.css";
|
||||
document.head.appendChild(styleLink);
|
||||
var setCardSize = (size) => {
|
||||
document.documentElement.style.setProperty("--library-card-size", `${size}px`);
|
||||
};
|
||||
var setSearchBarSize = (enlarged) => {
|
||||
const size = enlarged ? 300 : 200;
|
||||
document.documentElement.style.setProperty("--library-searchbar-size", `${size}px`);
|
||||
};
|
||||
var FolderImage = ({ url }) => {
|
||||
return /* @__PURE__ */ import_react10.default.createElement("img", {
|
||||
alt: "Folder Image",
|
||||
"aria-hidden": "true",
|
||||
draggable: "false",
|
||||
loading: "eager",
|
||||
src: url,
|
||||
className: "main-image-image x-entityImage-image main-image-loading main-image-loaded"
|
||||
});
|
||||
};
|
||||
var FolderPlaceholder = () => {
|
||||
return /* @__PURE__ */ import_react10.default.createElement("div", {
|
||||
className: "x-entityImage-imagePlaceholder"
|
||||
}, /* @__PURE__ */ import_react10.default.createElement("svg", {
|
||||
"data-encore-id": "icon",
|
||||
role: "img",
|
||||
"aria-hidden": "true",
|
||||
className: "Svg-sc-ytk21e-0 Svg-img-icon-medium",
|
||||
viewBox: "0 0 24 24"
|
||||
}, /* @__PURE__ */ import_react10.default.createElement("path", {
|
||||
d: "M1 4a2 2 0 0 1 2-2h5.155a3 3 0 0 1 2.598 1.5l.866 1.5H21a2 2 0 0 1 2 2v13a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V4zm7.155 0H3v16h18V7H10.464L9.021 4.5a1 1 0 0 0-.866-.5z"
|
||||
})));
|
||||
};
|
||||
var SpicetifyLibrary = class {
|
||||
ConfigWrapper = new config_wrapper_default(
|
||||
[
|
||||
{
|
||||
name: "Card Size",
|
||||
key: "cardSize",
|
||||
type: "slider",
|
||||
min: 100,
|
||||
max: 200,
|
||||
step: 0.05,
|
||||
def: 180,
|
||||
callback: setCardSize
|
||||
},
|
||||
{
|
||||
name: "Extend Search Bar",
|
||||
key: "extendSearchBar",
|
||||
type: "toggle",
|
||||
def: false,
|
||||
callback: setSearchBarSize
|
||||
},
|
||||
{
|
||||
name: "Playlists Page",
|
||||
key: "show-playlists",
|
||||
type: "toggle",
|
||||
def: true,
|
||||
sectionHeader: "Pages"
|
||||
},
|
||||
{ name: "Albums Page", key: "show-albums", type: "toggle", def: true },
|
||||
{ name: "Collections Page", key: "show-collections", type: "toggle", def: true },
|
||||
{ name: "Artists Page", key: "show-artists", type: "toggle", def: true },
|
||||
{ name: "Shows Page", key: "show-shows", type: "toggle", def: true }
|
||||
],
|
||||
"library"
|
||||
);
|
||||
};
|
||||
window.SpicetifyLibrary = new SpicetifyLibrary();
|
||||
(function wait() {
|
||||
const { LocalStorageAPI } = Spicetify.Platform;
|
||||
if (!LocalStorageAPI) {
|
||||
setTimeout(wait, 100);
|
||||
return;
|
||||
}
|
||||
main(LocalStorageAPI);
|
||||
})();
|
||||
function main(LocalStorageAPI) {
|
||||
const isAlbum = (props) => props.uri?.includes("album");
|
||||
const isArtist = (props) => props.uri?.includes("artist");
|
||||
Spicetify.ContextMenuV2.registerItem(/* @__PURE__ */ import_react10.default.createElement(album_menu_item_default, null), isAlbum);
|
||||
Spicetify.ContextMenuV2.registerItem(/* @__PURE__ */ import_react10.default.createElement(artist_menu_item_default, null), isArtist);
|
||||
Spicetify.Platform.LibraryAPI.getEvents()._emitter.addListener("update", () => CollectionsWrapper.cleanCollections());
|
||||
function injectFolderImages() {
|
||||
const rootlist = document.querySelector(".main-rootlist-wrapper > div:nth-child(2)");
|
||||
if (!rootlist)
|
||||
return setTimeout(injectFolderImages, 100);
|
||||
setTimeout(() => {
|
||||
for (const el of Array.from(rootlist.children)) {
|
||||
const uri = el.querySelector("[aria-labelledby]")?.getAttribute("aria-labelledby")?.slice(14);
|
||||
if (uri?.includes("folder")) {
|
||||
const imageBox = el.querySelector(".x-entityImage-imageContainer");
|
||||
if (!imageBox)
|
||||
return;
|
||||
const imageUrl = FolderImageWrapper.getFolderImage(uri);
|
||||
if (!imageUrl)
|
||||
import_react_dom.default.render(/* @__PURE__ */ import_react10.default.createElement(FolderPlaceholder, null), imageBox);
|
||||
else
|
||||
import_react_dom.default.render(/* @__PURE__ */ import_react10.default.createElement(FolderImage, {
|
||||
url: imageUrl
|
||||
}), imageBox);
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
injectFolderImages();
|
||||
FolderImageWrapper.addEventListener("update", injectFolderImages);
|
||||
function injectYLXButtons() {
|
||||
const ylx_filter = document.querySelector(".main-yourLibraryX-libraryRootlist > .main-yourLibraryX-libraryFilter");
|
||||
if (!ylx_filter) {
|
||||
return setTimeout(injectYLXButtons, 100);
|
||||
}
|
||||
injectFiltersButton(ylx_filter);
|
||||
injectCollapseButton(ylx_filter);
|
||||
}
|
||||
function injectFiltersButton(ylx_filter) {
|
||||
const toggleFiltersButton = document.createElement("span");
|
||||
toggleFiltersButton.classList.add("toggle-filters-button");
|
||||
ylx_filter.appendChild(toggleFiltersButton);
|
||||
import_react_dom.default.render(/* @__PURE__ */ import_react10.default.createElement(toggle_filters_default, null), toggleFiltersButton);
|
||||
}
|
||||
function injectCollapseButton(ylx_filter) {
|
||||
const collapseButton = document.createElement("span");
|
||||
collapseButton.classList.add("collapse-button");
|
||||
ylx_filter.appendChild(collapseButton);
|
||||
import_react_dom.default.render(
|
||||
/* @__PURE__ */ import_react10.default.createElement(Spicetify.ReactComponent.TooltipWrapper, {
|
||||
label: "Collapse Sidebar",
|
||||
placement: "top"
|
||||
}, /* @__PURE__ */ import_react10.default.createElement(collapse_button_default, null)),
|
||||
collapseButton
|
||||
);
|
||||
}
|
||||
const state = LocalStorageAPI.getItem("ylx-sidebar-state");
|
||||
if (state === 0)
|
||||
injectYLXButtons();
|
||||
LocalStorageAPI.getEvents()._emitter.addListener("update", (e) => {
|
||||
const { key, value } = e.data;
|
||||
if (key === "ylx-sidebar-state" && value === 0) {
|
||||
injectFolderImages();
|
||||
injectYLXButtons();
|
||||
}
|
||||
if (key === "ylx-sidebar-state" && value === 1) {
|
||||
injectFolderImages();
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
})();
|
||||
69
config/spicetify/CustomApps/library/folder_image_wrapper.js
Normal file
69
config/spicetify/CustomApps/library/folder_image_wrapper.js
Normal file
@@ -0,0 +1,69 @@
|
||||
(async function() {
|
||||
while (!Spicetify.React || !Spicetify.ReactDOM) {
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
}
|
||||
"use strict";
|
||||
var library = (() => {
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var __publicField = (obj, key, value) => {
|
||||
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
||||
return value;
|
||||
};
|
||||
|
||||
// src/extensions/folder_image_wrapper.ts
|
||||
var folder_image_wrapper_exports = {};
|
||||
__export(folder_image_wrapper_exports, {
|
||||
default: () => folder_image_wrapper_default
|
||||
});
|
||||
var _FolderImageWrapper = class extends EventTarget {
|
||||
_folderImages;
|
||||
constructor() {
|
||||
super();
|
||||
this._folderImages = JSON.parse(localStorage.getItem("library:folderImages") || "{}");
|
||||
}
|
||||
getFolderImage(uri) {
|
||||
return this._folderImages[uri];
|
||||
}
|
||||
getFolderImages() {
|
||||
return this._folderImages;
|
||||
}
|
||||
setFolderImage({ uri, url }) {
|
||||
this._folderImages[uri] = url;
|
||||
this.saveFolderImages();
|
||||
Spicetify.showNotification("Folder image updated");
|
||||
}
|
||||
removeFolderImage(uri) {
|
||||
delete this._folderImages[uri];
|
||||
this.saveFolderImages();
|
||||
Spicetify.showNotification("Folder image removed");
|
||||
}
|
||||
saveFolderImages() {
|
||||
this.dispatchEvent(new CustomEvent("update", { detail: this._folderImages }));
|
||||
localStorage.setItem("library:folderImages", JSON.stringify(this._folderImages));
|
||||
}
|
||||
};
|
||||
var FolderImageWrapper = _FolderImageWrapper;
|
||||
__publicField(FolderImageWrapper, "INSTANCE", new _FolderImageWrapper());
|
||||
window.FolderImageWrapper = FolderImageWrapper.INSTANCE;
|
||||
var folder_image_wrapper_default = FolderImageWrapper;
|
||||
return __toCommonJS(folder_image_wrapper_exports);
|
||||
})();
|
||||
|
||||
})();
|
||||
1615
config/spicetify/CustomApps/library/index.js
Normal file
1615
config/spicetify/CustomApps/library/index.js
Normal file
File diff suppressed because it is too large
Load Diff
11
config/spicetify/CustomApps/library/manifest.json
Normal file
11
config/spicetify/CustomApps/library/manifest.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "Your Library",
|
||||
"icon": "<svg height=\"24\" width=\"24\" viewBox=\"0 0 24 24\">\r\n<path d=\"M14.5 2.134a1 1 0 0 1 1 0l6 3.464a1 1 0 0 1 .5.866V21a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1V3a1 1 0 0 1 .5-.866zM16 4.732V20h4V7.041l-4-2.309zM3 22a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1zm6 0a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1z\"></path>\r\n</svg>\r\n",
|
||||
"active-icon": "<svg height=\"24\" width=\"24\" viewBox=\"0 0 24 24\">\r\n<path d=\"M3 22a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1zM15.5 2.134A1 1 0 0 0 14 3v18a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V6.464a1 1 0 0 0-.5-.866l-6-3.464zM9 2a1 1 0 0 0-1 1v18a1 1 0 1 0 2 0V3a1 1 0 0 0-1-1z\"></path>\r\n</svg>",
|
||||
"subfiles": [],
|
||||
"subfiles_extension": [
|
||||
"collections_wrapper.js",
|
||||
"extension.js",
|
||||
"folder_image_wrapper.js"
|
||||
]
|
||||
}
|
||||
379
config/spicetify/CustomApps/library/style.css
Normal file
379
config/spicetify/CustomApps/library/style.css
Normal file
@@ -0,0 +1,379 @@
|
||||
/* ../../../AppData/Local/Temp/tmp-4464-wbZ6O1BKhuot/19178f16f304/navBar.module.css */
|
||||
.navBar-module__topBarHeaderItem___piw4C_library {
|
||||
-webkit-app-region: no-drag;
|
||||
display: inline-block;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.navBar-module__topBarHeaderItemLink___xA4uv_library {
|
||||
margin: 0 8px 0 0;
|
||||
}
|
||||
.navBar-module__topBarActive___XhWpm_library {
|
||||
background-color: var(--spice-tab-active);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.navBar-module__topBarHeaderItemLink___xA4uv_library {
|
||||
border-radius: 4px;
|
||||
color: var(--spice-text);
|
||||
display: inline-block;
|
||||
margin: 0 8px;
|
||||
padding: 8px 16px;
|
||||
position: relative;
|
||||
text-decoration: none !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.navBar-module__topBarNav___qWGeZ_library {
|
||||
-webkit-app-region: drag;
|
||||
pointer-events: none;
|
||||
width: 100%;
|
||||
}
|
||||
.navBar-module__topBarHeaderItem___piw4C_library .navBar-module__optionsMenuDropBox___pzfNI_library {
|
||||
color: var(--spice-text);
|
||||
border: 0;
|
||||
max-width: 150px;
|
||||
height: 42px;
|
||||
padding: 0 30px 0 12px;
|
||||
background-color: initial;
|
||||
cursor: pointer;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
.navBar-module__topBarHeaderItem___piw4C_library .navBar-module__optionsMenuDropBox___pzfNI_library svg {
|
||||
position: absolute;
|
||||
margin-left: 8px;
|
||||
}
|
||||
div.navBar-module__topBarHeaderItemLink___xA4uv_library {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* ../../../AppData/Local/Temp/tmp-4464-wbZ6O1BKhuot/19178f16dc80/app.css */
|
||||
:root {
|
||||
--library-card-size: 180px;
|
||||
--library-searchbar-size: 200px;
|
||||
}
|
||||
#library-app .header-right .x-filterBox-expandedOrHasFilter .x-filterBox-filterInput {
|
||||
width: var(--library-searchbar-size);
|
||||
}
|
||||
#library-app .grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(var(--library-card-size), 1fr)) !important;
|
||||
}
|
||||
#library-app .main-card-cardContainer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#library-app .load-more-card {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
#library-app .load-more-card div:nth-child(2) {
|
||||
text-align: center;
|
||||
font-size: var(--encore-text-size-base);
|
||||
}
|
||||
#library-app .load-more-card div:first-child {
|
||||
fill: var(--text-subdued);
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
#library-app .load-more-card:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
.text-input-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18px;
|
||||
}
|
||||
.text-input-form .text-input {
|
||||
background: rgba(var(--spice-rgb-selected-row), 0.1);
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
color: var(--spice-text);
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
width: 100%;
|
||||
}
|
||||
.text-input-form .text-input:focus {
|
||||
background-color: var(--spice-tab-active);
|
||||
border: 1px solid var(--spice-button-disabled);
|
||||
outline: none;
|
||||
}
|
||||
.text-input-form button {
|
||||
align-self: end;
|
||||
}
|
||||
|
||||
/* ../../../AppData/Local/Temp/tmp-4464-wbZ6O1BKhuot/19178f16ee21/external.css */
|
||||
body:not(.show-ylx-filters) .main-yourLibraryX-filterArea:not(:has(> .main-yourLibraryX-libraryFilter)),
|
||||
.main-yourLibraryX-header:not(:has(> .main-yourLibraryX-headerContent > .main-yourLibraryX-collapseButton > button:nth-child(2))),
|
||||
.main-yourLibraryX-collapseButton > button:first-child,
|
||||
.main-yourLibraryX-headerContent > button {
|
||||
display: none;
|
||||
}
|
||||
.main-yourLibraryX-library {
|
||||
padding-top: 8px;
|
||||
}
|
||||
.main-yourLibraryX-header {
|
||||
margin-top: -8px;
|
||||
}
|
||||
.main-yourLibraryX-libraryFilter .main-yourLibraryX-librarySortWrapper button span:first-child,
|
||||
.main-yourLibraryX-libraryFilter span[role=presentation] span[role=presentation] button span:first-child {
|
||||
display: none;
|
||||
}
|
||||
.main-yourLibraryX-libraryFilter .main-yourLibraryX-librarySortWrapper,
|
||||
.main-yourLibraryX-libraryFilter span[role=presentation] {
|
||||
margin-left: auto;
|
||||
}
|
||||
.toggle-filters-button > button:after,
|
||||
.collapse-button > button:after,
|
||||
.expand-button > button:after {
|
||||
display: none;
|
||||
}
|
||||
.expand-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
z-index: 1;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.expand-button > button {
|
||||
visibility: hidden;
|
||||
margin: 0 5px;
|
||||
}
|
||||
li.main-yourLibraryX-navItem[data-id="/library"] {
|
||||
display: flex;
|
||||
}
|
||||
li.main-yourLibraryX-navItem[data-id="/library"] > a {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.main-yourLibraryX-libraryFilter .toggle-filters-button > button,
|
||||
.main-yourLibraryX-libraryFilter .collapse-button > button,
|
||||
.main-yourLibraryX-libraryFilter .main-yourLibraryX-librarySortWrapper > button,
|
||||
.main-yourLibraryX-libraryFilter span[role=presentation] span[role=presentation] > button {
|
||||
padding: 0;
|
||||
}
|
||||
.main-yourLibraryX-libraryFilter .toggle-filters-button,
|
||||
.main-yourLibraryX-libraryFilter .collapse-button,
|
||||
.main-yourLibraryX-libraryFilter .main-yourLibraryX-librarySortWrapper,
|
||||
.main-yourLibraryX-libraryFilter span[role=presentation] span[role=presentation] {
|
||||
display: flex;
|
||||
flex-basis: 32px;
|
||||
justify-content: center;
|
||||
min-width: 24px;
|
||||
flex-shrink: 10;
|
||||
}
|
||||
.main-yourLibraryX-libraryFilter .main-yourLibraryX-librarySortWrapper > button > span:nth-child(2),
|
||||
.main-yourLibraryX-libraryFilter span[role=presentation] span[role=presentation] > button > span:nth-child(2) {
|
||||
margin: 0;
|
||||
}
|
||||
.LayoutResizer__resize-bar {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
.Root__nav-bar .x-filterBox-expandedOrHasFilter .x-filterBox-filterInput {
|
||||
width: 100%;
|
||||
}
|
||||
.Root__nav-bar .x-filterBox-expandedOrHasFilter {
|
||||
flex-grow: 1;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.Root__nav-bar:has(> .LayoutResizer__resize-bar:hover) .expand-button > button,
|
||||
.Root__nav-bar .expand-button:hover > button {
|
||||
visibility: visible;
|
||||
height: 32px;
|
||||
background-color: black;
|
||||
}
|
||||
.text-input-form .Button-small-buttonPrimary {
|
||||
box-sizing: border-box;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 700;
|
||||
font-family: var(--font-family, CircularSp, CircularSp-Arab, CircularSp-Hebr, CircularSp-Cyrl, CircularSp-Grek, CircularSp-Deva, var(--fallback-fonts, sans-serif));
|
||||
background-color: transparent;
|
||||
border: 0px;
|
||||
border-radius: 9999px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-transform: none;
|
||||
touch-action: manipulation;
|
||||
transition-duration: 33ms;
|
||||
transition-property:
|
||||
background-color,
|
||||
border-color,
|
||||
color,
|
||||
box-shadow,
|
||||
filter,
|
||||
transform;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
vertical-align: middle;
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
padding: 0px;
|
||||
min-inline-size: 0px;
|
||||
}
|
||||
.text-input-form .ButtonInner-small {
|
||||
box-sizing: border-box;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
position: relative;
|
||||
background-color: var(--background-base, #1ed760);
|
||||
color: var(--text-base, #000000);
|
||||
display: flex;
|
||||
border-radius: 9999px;
|
||||
font-size: inherit;
|
||||
min-block-size: var(--encore-control-size-smaller, 32px);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-block-start: var(--encore-spacing-tighter-4, 4px);
|
||||
padding-block-end: var(--encore-spacing-tighter-4, 4px);
|
||||
padding-inline-start: var(--encore-spacing-base, 16px);
|
||||
padding-inline-end: var(--encore-spacing-base, 16px);
|
||||
}
|
||||
.text-input-form .Button-small-buttonPrimary:hover .ButtonInner-sc-14ud5tc-0,
|
||||
.text-input-form .Button-small-buttonPrimary:hover .ButtonFocus-sc-2hq6ey-0 {
|
||||
transform: scale(1.04);
|
||||
}
|
||||
|
||||
/* ../../../AppData/Local/Temp/tmp-4464-wbZ6O1BKhuot/19178f16f0a2/config_modal.css */
|
||||
.config-container {
|
||||
gap: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.config-container .section-header {
|
||||
box-sizing: border-box;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
margin-block: 0px;
|
||||
font-size: 1.125rem;
|
||||
font-weight: 700;
|
||||
color: var(--spice-text);
|
||||
}
|
||||
.config-container .col.description {
|
||||
box-sizing: border-box;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
margin-block: 0px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 400;
|
||||
color: var(--spice-subtext);
|
||||
}
|
||||
.config-container .disabled {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.config-container .text-input {
|
||||
background: rgba(var(--spice-rgb-selected-row), 0.1);
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
color: var(--spice-text);
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
width: 100%;
|
||||
}
|
||||
.config-container .text-input:focus {
|
||||
background-color: var(--spice-tab-active);
|
||||
border: 1px solid var(--spice-button-disabled);
|
||||
outline: none;
|
||||
}
|
||||
.config-container .dropdown-input {
|
||||
background-color: var(--spice-tab-active);
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
color: rgba(var(--spice-rgb-selected-row), 0.7);
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
height: 32px;
|
||||
letter-spacing: 0.24px;
|
||||
line-height: 20px;
|
||||
padding: 0 32px 0 12px;
|
||||
width: 100%;
|
||||
}
|
||||
.config-container .tooltip-icon {
|
||||
float: right;
|
||||
margin-left: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
fill: var(--spice-subtext);
|
||||
}
|
||||
.config-container .tooltip-icon:hover {
|
||||
fill: var(--spice-text);
|
||||
}
|
||||
.config-container .tooltip {
|
||||
text-align: center;
|
||||
}
|
||||
.config-container .setting-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.config-container .playback-progressbar {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
/* ../../../AppData/Local/Temp/tmp-4464-wbZ6O1BKhuot/19178f16f163/shared.css */
|
||||
.grid {
|
||||
--grid-gap: 24px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)) !important;
|
||||
}
|
||||
.loadingWrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 60vh;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.loadingWrapper .status-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
fill: currentColor;
|
||||
}
|
||||
.page-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
}
|
||||
.badge {
|
||||
position: absolute;
|
||||
top: 3%;
|
||||
left: 3%;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
border-radius: 50%;
|
||||
background-color: rgb(65, 110, 170);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
}
|
||||
.page-header {
|
||||
align-content: space-between;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 16px 0;
|
||||
}
|
||||
.page-header .header-right,
|
||||
.page-header .header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.page-header .header-right {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.page-header .header-left {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.new-update {
|
||||
background-color: var(--spice-player);
|
||||
color: var(--spice-text);
|
||||
border-radius: 8px;
|
||||
padding: 2px 12px;
|
||||
margin: 0 24px;
|
||||
border: 0px;
|
||||
}
|
||||
35
config/spicetify/CustomApps/marketplace/README.md
Normal file
35
config/spicetify/CustomApps/marketplace/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Spicetify Marketplace
|
||||
|
||||
<p>
|
||||
<a href="https://github.com/spicetify/spicetify-marketplace/releases/latest">
|
||||
<img src="https://img.shields.io/github/v/release/spicetify/spicetify-marketplace?include_prereleases">
|
||||
</a>
|
||||
<a href="https://github.com/spicetify/spicetify-marketplace/releases">
|
||||
<img src="https://img.shields.io/github/downloads/spicetify/spicetify-marketplace/total.svg">
|
||||
</a>
|
||||
<a href="https://github.com/spicetify/spicetify-marketplace/issues?q=is%3Aissue+is%3Aclosed">
|
||||
<img src="https://img.shields.io/github/issues-closed/spicetify/spicetify-marketplace">
|
||||
</a>
|
||||
<a href="https://github.com/spicetify/spicetify-marketplace/commits/main">
|
||||
<img src="https://img.shields.io/github/commit-activity/m/spicetify/spicetify-marketplace">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Customize your Spotify client directly from within [Spicetify](https://github.com/spicetify/spicetify-cli)!
|
||||
|
||||
Marketplace allows you to **browse, download, and install** extensions, themes, and CSS snippets with ease. You can also browse custom apps, but will need to do some manual installation to get them working.
|
||||
|
||||
Made with [Spicetify Creator](https://github.com/spicetify/spicetify-creator)
|
||||
|
||||
Head to the [wiki](https://github.com/spicetify/spicetify-marketplace/wiki) to get started!
|
||||
|
||||
---
|
||||
|
||||
## Links
|
||||
- [Overview](https://github.com/spicetify/spicetify-marketplace/wiki)
|
||||
- [Installation](https://github.com/spicetify/spicetify-marketplace/wiki/Installation)
|
||||
- [Publishing to Marketplace](https://github.com/spicetify/spicetify-marketplace/wiki/Publishing-to-Marketplace)
|
||||
- [Contributions](https://github.com/spicetify/spicetify-marketplace/wiki/Contributions)
|
||||
- [Development](https://github.com/spicetify/spicetify-marketplace/wiki/Development)
|
||||
- [Translating/Localizing Marketplace](https://github.com/spicetify/spicetify-marketplace/wiki/Localizing-Marketplace)
|
||||
|
||||
10
config/spicetify/CustomApps/marketplace/extension.js
Normal file
10
config/spicetify/CustomApps/marketplace/extension.js
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user