diff --git a/arch_news.sh b/arch_news.sh
deleted file mode 100755
index 8aaadb7..0000000
--- a/arch_news.sh
+++ /dev/null
@@ -1,254 +0,0 @@
-#!/bin/bash
-
-# Arch Linux News Notifier
-# Fetches latest news from Arch Linux RSS feed and shows notifications for new items
-
-# Configuration
-RSS_URL="https://archlinux.org/feeds/news/"
-CACHE_FILE="$HOME/.cache/arch-news-seen"
-TEMP_FILE="/tmp/arch-news-latest"
-
-ICON_NORMAL="/usr/share/pixmaps/tabler--coffee.svg"
-ICON_URGENT="/usr/share/pixmaps/charm--circle-warning.svg"
-
-# Create cache directory if it doesn't existnClick to open:
-mkdir -p "$(dirname "$CACHE_FILE")"
-
-# Function to extract and format news items
-parse_rss() {
- # Debug: show what we're working with
- if [[ "$DEBUG" == "1" ]]; then
- echo "=== DEBUG: RSS file content preview ===" >&2
- head -20 "$TEMP_FILE" >&2
- echo "=== END DEBUG ===" >&2
- fi
-
- if command -v xmllint >/dev/null 2>&1; then
- # Use xmllint to extract items properly
- xmllint --xpath "//item[position()<=5]" "$TEMP_FILE" 2>/dev/null |
- sed 's|- |\n
- |g' |
- sed 's|
| \n|g' |
- grep -A 20 '- ' |
- awk -v RS='
' '
- /- / {
- title = ""; link = ""; pubdate = ""
-
- # Extract title
- if (match($0, /]*>([^<]*)<\/title>/, arr)) {
- title = arr[1]
- gsub(/>/, ">", title)
- gsub(/</, "<", title)
- gsub(/&/, "&", title)
- }
-
- # Extract link (not atom:link)
- if (match($0, /([^<]*)<\/link>/, arr)) {
- link = arr[1]
- }
-
- # Extract pubDate
- if (match($0, /([^<]*)<\/pubDate>/, arr)) {
- pubdate = arr[1]
- }
-
- if (title && link && pubdate) {
- print pubdate "|" title "|" link
- }
- }'
- else
- # Fallback: simple grep approach
- local temp_items="/tmp/arch-items-$"
-
- # Extract each item block
- awk '/
- /,/<\/item>/' "$TEMP_FILE" >"$temp_items"
-
- # Process with simple pattern matching
- while IFS= read -r line; do
- if [[ "$line" =~ \([^<]*)\ ]]; then
- title="${BASH_REMATCH[1]}"
- title="${title//>/>}"
- title="${title//</<}"
- title="${title//&/&}"
- elif [[ "$line" =~ \([^<]*)\ ]] && [[ ! "$line" =~ atom:link ]]; then
- link="${BASH_REMATCH[1]}"
- elif [[ "$line" =~ \([^<]*)\ ]]; then
- pubdate="${BASH_REMATCH[1]}"
-
- # When we have all three, output and reset
- if [[ -n "$title" && -n "$link" && -n "$pubdate" ]]; then
- echo "$pubdate|$title|$link"
- title=""
- link=""
- pubdate=""
- fi
- fi
- done <"$temp_items"
-
- rm -f "$temp_items"
- fi
-}
-
-# Function to send notification
-send_notification() {
- local title="$1"
- local body="$2"
- local url="$3"
-
- # Determine urgency level based on content
- local urgency="normal"
- local icon=$ICON_NORMAL
-
- # Check for urgent intervention keywords (case insensitive)
- if echo "$title $body" | grep -qi "\(manual intervention\|action required\|breaking change\|immediate action\|urgent\|critical\|important.*update\|requires.*intervention\)"; then
- urgency="critical"
- icon=$ICON_URGENT
- fi
-
- # Send notification with appropriate urgency
- notify-send \
- --urgency="$urgency" \
- --app-name="Arch News" \
- --icon="$icon" \
- --expire-time=20000 \
- "$title" \
- "$body\n$url"
-
- # Debug output
- if [[ "$DEBUG" == "1" ]]; then
- echo "=== DEBUG: Notification sent ===" >&2
- echo "Title: $title" >&2
- echo "Urgency: $urgency" >&2
- echo "Reason: $(echo "$title $body" | grep -i "\(manual intervention\|action required\|breaking change\|immediate action\|urgent\|critical\|important.*update\|requires.*intervention\)" || echo "normal news")" >&2
- echo "=== END DEBUG ===" >&2
- fi
-}
-
-# Main execution
-main() {
- # Parse command line options
- local force_show=false
- local show_latest=false
-
- while [[ $# -gt 0 ]]; do
- case $1 in
- --force)
- force_show=true
- shift
- ;;
- --show-latest)
- show_latest=true
- shift
- ;;
- --clear-cache)
- rm -f "$CACHE_FILE"
- echo "Cache cleared"
- exit 0
- ;;
- --help | -h)
- echo "Usage: $0 [options]"
- echo "Options:"
- echo " --force Show notifications for latest news even if already seen"
- echo " --show-latest Show notification for the latest news item only"
- echo " --clear-cache Clear the seen items cache"
- echo " --help Show this help message"
- exit 0
- ;;
- *)
- echo "Unknown option: $1" >&2
- exit 1
- ;;
- esac
- done
-
- # Check if required tools are available
- if ! command -v xmllint >/dev/null 2>&1; then
- echo "Error: xmllint is required (install libxml2-utils)" >&2
- exit 1
- fi
-
- if ! command -v notify-send >/dev/null 2>&1; then
- echo "Error: notify-send is required" >&2
- exit 1
- fi
-
- # Fetch RSS feed
- if ! curl -s --max-time 30 "$RSS_URL" >"$TEMP_FILE"; then
- echo "Error: Failed to fetch RSS feed" >&2
- exit 1
- fi
-
- # Debug: Check if file was created and has content
- if [[ "$DEBUG" == "1" ]]; then
- echo "=== DEBUG: Temp file info ===" >&2
- ls -la "$TEMP_FILE" >&2
- echo "First few lines:" >&2
- head -5 "$TEMP_FILE" >&2
- echo "=== END DEBUG ===" >&2
- fi
-
- # Check if file is not empty
- if [[ ! -s "$TEMP_FILE" ]]; then
- echo "Error: RSS feed is empty" >&2
- exit 1
- fi
-
- # Create cache file if it doesn't exist
- [[ ! -f "$CACHE_FILE" ]] && touch "$CACHE_FILE"
-
- # Parse RSS and check for new items
- local new_items=0
- local items_processed=0
-
- # Debug: show all parsed items
- if [[ "$DEBUG" == "1" ]]; then
- echo "=== DEBUG: All parsed RSS items ===" >&2
- parse_rss | nl >&2
- echo "=== END DEBUG ===" >&2
- fi
-
- while IFS='|' read -r pubdate title link; do
- [[ -z "$title" ]] && continue
- ((items_processed++))
-
- # Create a unique identifier for this news item
- local item_id=$(echo "$title$pubdate" | md5sum | cut -d' ' -f1)
-
- # Show latest item only if requested
- if [[ "$show_latest" == true && $items_processed -eq 1 ]]; then
- local formatted_date=$(date -d "$pubdate" "+%d.%m.%Y" 2>/dev/null || echo "Recent")
- send_notification "$title" "Published: $formatted_date" "$link"
- echo "$item_id" >>"$CACHE_FILE"
- ((new_items++))
- break
- fi
-
- # Check if we've already seen this item (or force showing)
- if [[ "$force_show" == true ]] || ! grep -q "$item_id" "$CACHE_FILE"; then
- # New item found - send notification
- local formatted_date=$(date -d "$pubdate" "+%d.%m.%Y" 2>/dev/null || echo "Recent")
- send_notification "$title" "Published: $formatted_date" "$link"
-
- # Mark as seen (only if not forcing)
- if [[ "$force_show" == false ]]; then
- echo "$item_id" >>"$CACHE_FILE"
- fi
- ((new_items++))
-
- # Add delay between notifications for better mako stacking
- [[ $new_items -gt 1 ]] && sleep 1.5
- fi
- done < <(parse_rss)
-
- # Clean up
- rm -f "$TEMP_FILE"
-
- # Limit cache file size (keep last 100 entries)
- if [[ -f "$CACHE_FILE" ]]; then
- tail -100 "$CACHE_FILE" >"$CACHE_FILE.tmp" && mv "$CACHE_FILE.tmp" "$CACHE_FILE"
- fi
-
- echo "Checked Arch Linux news - $new_items new items found"
-}
-
-# Run main function
-main "$@"
diff --git a/lorem b/lorem
deleted file mode 100755
index 23ea9a5..0000000
--- a/lorem
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-
-# Check if argument is provided
-if [ $# -eq 0 ]; then
- echo "Usage: $0 "
- exit 1
-fi
-
-# Check if argument is a number
-if ! [[ "$1" =~ ^[0-9]+$ ]]; then
- echo "Error: Please provide a valid number"
- exit 1
-fi
-
-# Lorem ipsum word bank
-words=(
- "lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing" "elit"
- "sed" "do" "eiusmod" "tempor" "incididunt" "ut" "labore" "et" "dolore"
- "magna" "aliqua" "enim" "ad" "minim" "veniam" "quis" "nostrud"
- "exercitation" "ullamco" "laboris" "nisi" "aliquip" "ex" "ea" "commodo"
- "consequat" "duis" "aute" "irure" "in" "reprehenderit" "voluptate"
- "velit" "esse" "cillum" "fugiat" "nulla" "pariatur" "excepteur" "sint"
- "occaecat" "cupidatat" "non" "proident" "sunt" "culpa" "qui" "officia"
- "deserunt" "mollit" "anim" "id" "est" "laborum"
-)
-
-# Generate requested number of words
-result=""
-for ((i=1; i<=$1; i++)); do
- # Get random word from array
- word=${words[$RANDOM % ${#words[@]}]}
-
- if [ $i -eq 1 ]; then
- result="$word"
- else
- result="$result $word"
- fi
-done
-
-echo "$result"
diff --git a/niri/config.kdl b/niri/config.kdl
index da8d10f..da87487 100644
--- a/niri/config.kdl
+++ b/niri/config.kdl
@@ -236,6 +236,10 @@ spawn-at-startup "wl-paste" "--type" "text" "--watch" "cliphist" "store"
spawn-at-startup "wl-paste" "--type" "image" "--watch" "cliphist" "store"
spawn-at-startup "arch_news.sh"
+spawn-at-startup "days_notify.sh"
+
+spawn-at-startup "swayidle" "-w" "timeout" "300" "niri msg action power-off-monitors" "resume" "niri msg action power-on-monitors"
+
// Uncomment this line to ask the clients to omit their client-side decorations if possible.
// If the client will specifically ask for CSD, the request will be honored.
// Additionally, clients will be informed that they are tiled, removing some client-side rounded corners.
@@ -264,8 +268,7 @@ animations {
// https://variety4me.github.io/niri_docs/Configuration-Switch-Events/
switch-events {
- lid-close { spawn "waylock"; }
- lid-open { spawn "brightnessctl" "s" "50%"; }
+ lid-close { spawn "waylock" "&&" "systemctl" "hibernate"; }
}
// Window rules let you adjust behavior for individual windows.
@@ -278,6 +281,9 @@ window-rule {
// - host Firefox (app-id is "firefox")
// - Flatpak Firefox (app-id is "org.mozilla.firefox")
match app-id=r#"zen$"# title="^Picture-in-Picture$"
+ match app-id=r#"Blanket$"#
+ match app-id=r#"Dialect$"#
+ match app-id=r#"com.example.ollama-chat"#
open-floating true
}
@@ -325,7 +331,9 @@ binds {
XF86AudioLowerVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1-"; }
XF86AudioMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; }
XF86AudioMicMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; }
-
+
+ XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "set" "10+%"; }
+ XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "set" "10-%"; }
// Open/close the Overview: a zoomed-out view of workspaces and windows.
// You can also move the mouse into the top-left hot corner,
// or do a four-finger swipe up on a touchpad.
@@ -535,6 +543,7 @@ binds {
Print { screenshot; }
Ctrl+Print { screenshot-screen; }
Alt+Print { screenshot-window; }
+ Mod+Print { spawn "sh" "-c" "wl-paste | swappy -f - ";} // markup the image
// Applications such as remote-desktop clients and software KVM switches may
// request that niri stops processing the keyboard shortcuts defined here
@@ -552,5 +561,5 @@ binds {
// Powers off the monitors. To turn them back on, do any input like
// moving the mouse or pressing any other key.
- Mod+Shift+P { power-off-monitors; }
+ XF86Display { power-off-monitors; }
}
diff --git a/rentry b/rentry
deleted file mode 100755
index 1b2ea15..0000000
--- a/rentry
+++ /dev/null
@@ -1,160 +0,0 @@
-#!/usr/bin/env python3
-
-import getopt
-import http.cookiejar
-import sys
-import urllib.parse
-import urllib.request
-from http.cookies import SimpleCookie
-from json import loads as json_loads
-from os import environ
-
-_headers = {"Referer": 'https://rentry.co'}
-
-
-class UrllibClient:
- """Simple HTTP Session Client, keeps cookies."""
-
- def __init__(self):
- self.cookie_jar = http.cookiejar.CookieJar()
- self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookie_jar))
- urllib.request.install_opener(self.opener)
-
- def get(self, url, headers={}):
- request = urllib.request.Request(url, headers=headers)
- return self._request(request)
-
- def post(self, url, data=None, headers={}):
- postdata = urllib.parse.urlencode(data).encode()
- request = urllib.request.Request(url, postdata, headers)
- return self._request(request)
-
- def _request(self, request):
- response = self.opener.open(request)
- response.status_code = response.getcode()
- response.data = response.read().decode('utf-8')
- return response
-
-
-def raw(url):
- client = UrllibClient()
- return json_loads(client.get('https://rentry.co/api/raw/{}'.format(url)).data)
-
-
-def new(url, edit_code, text):
- client, cookie = UrllibClient(), SimpleCookie()
-
- cookie.load(vars(client.get('https://rentry.co'))['headers']['Set-Cookie'])
- csrftoken = cookie['csrftoken'].value
-
- payload = {
- 'csrfmiddlewaretoken': csrftoken,
- 'url': url,
- 'edit_code': edit_code,
- 'text': text
- }
-
- return json_loads(client.post('https://rentry.co/api/new', payload, headers=_headers).data)
-
-
-def edit(url, edit_code, text):
- client, cookie = UrllibClient(), SimpleCookie()
-
- cookie.load(vars(client.get('https://rentry.co'))['headers']['Set-Cookie'])
- csrftoken = cookie['csrftoken'].value
-
- payload = {
- 'csrfmiddlewaretoken': csrftoken,
- 'edit_code': edit_code,
- 'text': text
- }
-
- return json_loads(client.post('https://rentry.co/api/edit/{}'.format(url), payload, headers=_headers).data)
-
-
-def usage():
- print('''
-Usage: rentry {new | edit | raw} {-h | --help} {-u | --url} {-p | --edit-code} text
-
-Commands:
- new create a new entry
- edit edit an existing entry
- raw get raw markdown text of an existing entry
-
-Options:
- -h, --help show this help message and exit
- -u, --url URL url for the entry, random if not specified
- -p, --edit-code EDIT-CODE edit code for the entry, random if not specified
-
-Examples:
- rentry new 'markdown text' # new entry with random url and edit code
- rentry new -p pw -u example 'text' # with custom edit code and url
- rentry edit -p pw -u example 'text' # edit the example entry
- cat file | rentry new # read from pipe and paste it to rentry
- rentry raw -u example # get raw markdown text
- rentry raw -u https://rentry.co/example # -u accepts absolute and relative urls
- ''')
-
-
-if __name__ == '__main__':
- try:
- environ.pop('POSIXLY_CORRECT', None)
- opts, args = getopt.gnu_getopt(sys.argv[1:], "hu:p:", ["help", "url=", "edit-code="])
- except getopt.GetoptError as e:
- sys.exit("error: {}".format(e))
-
- command, url, edit_code, text = None, '', '', None
-
- for o, a in opts:
- if o in ("-h", "--help"):
- usage()
- sys.exit()
- elif o in ("-u", "--url"):
- url = urllib.parse.urlparse(a).path.strip('/')
- elif o in ("-p", "--edit-code"):
- edit_code = a
-
- command = (args[0:1] or [None])[0]
- command or sys.exit(usage())
- command in ['new', 'edit', 'raw'] or sys.exit('error: command must be new, edit or raw')
-
- text = (args[1:2] or [None])[0]
- if not text and command != 'raw':
- text = sys.stdin.read().strip()
- text or sys.exit('error: text is required')
-
- if command == 'new':
- response = new(url, edit_code, text)
- if response['status'] != '200':
- print('error: {}'.format(response['content']))
- try:
- for i in response['errors'].split('.'):
- i and print(i)
- sys.exit(1)
- except:
- sys.exit(1)
- else:
- print('Url: {}\nEdit code: {}'.format(response['url'], response['edit_code']))
-
- elif command == 'edit':
- url or sys.exit('error: url is required')
- edit_code or sys.exit('error: edit code is required')
-
- response = edit(url, edit_code, text)
- if response['status'] != '200':
- print('error: {}'.format(response['content']))
- try:
- for i in response['errors'].split('.'):
- i and print(i)
- sys.exit(1)
- except:
- sys.exit(1)
- else:
- print('Ok')
-
- elif command == 'raw':
- url or sys.exit('error: url is required')
- response = raw(url)
- if response['status'] != '200':
- sys.exit('error: {}'.format(response['content']))
- print(response['content'])
diff --git a/speak.sh b/speak.sh
deleted file mode 100755
index 0a28d3d..0000000
--- a/speak.sh
+++ /dev/null
@@ -1,165 +0,0 @@
-#!/bin/bash
-# Chunked TTS processor - Divides text into chunks, processes and plays them sequentially
-
-EXEC_PATH="$HOME/kokoros/target/release/koko"
-MODEL_PATH="$HOME/kokoros/checkpoints/kokoro-v1.0.onnx"
-VOICE_DATA="$HOME/kokoros/voices-v1.0.bin"
-SPEED=1.1
-VOICE_STYLE="af_heart"
-# Style mixing supported for Kokoros: "af_sky.4+af_nicole.5"
-# https://github.com/hexgrad/kokoro/tree/main/kokoro.js/voices
-
-# Chunking parameters
-MIN_CHUNK_SIZE=80
-MAX_CHUNK_SIZE=200
-MIN_SENTENCES=2
-
-export LC_ALL=en_US.UTF-8
-export LANG=en_US.UTF-8
-
-clipboard_content=$(xclip -o)
-filtered_content=$(echo "$clipboard_content" | sed -E '
- s/-(\r|\n)//g
- s/\r|\n/ /g
- s/ +/ /g
- s/^ *//g
- s/ *$//g
- s/--/ — /g
- s/ - / — /g
- s/\.\.\./…/g
- s/([0-9]),([0-9])/\1\2/g
- s/([.,;:])([^ ])/\1 \2/g
-')
-
-TEMP_DIR=$(mktemp -d)
-echo "Using temporary directory: $TEMP_DIR"
-
-# Save the cleaned text to a file
-echo "$filtered_content" > "$TEMP_DIR/full_text.txt"
-
-# Smart chunking: Split text into optimal chunks
-cat "$TEMP_DIR/full_text.txt" |
- sed -E 's/([.!?]) +/\1\n/g' |
- awk -v min_size="$MIN_CHUNK_SIZE" -v max_size="$MAX_CHUNK_SIZE" -v min_sentences="$MIN_SENTENCES" '
- BEGIN {
- chunk = "";
- sentence_count = 0;
- }
-
- NF > 0 {
- sentence = $0;
-
- if (length(chunk) > 0) {
- test_chunk = chunk " " sentence;
- } else {
- test_chunk = sentence;
- }
-
- should_output = 0;
-
- # If adding this sentence would exceed max size, output current chunk first
- if (length(test_chunk) > max_size && length(chunk) > 0) {
- should_output = 1;
- }
- # If we have minimum sentences and minimum size, we can output
- else if (sentence_count >= min_sentences && length(chunk) >= min_size) {
- if (length(sentence) > (max_size - min_size)) {
- should_output = 1;
- }
- else if (length(test_chunk) >= min_size * 1.5) {
- chunk = test_chunk;
- sentence_count++;
- should_output = 1;
- }
- }
-
- if (should_output && length(chunk) > 0) {
- print chunk;
- chunk = "";
- sentence_count = 0;
-
- if (length(test_chunk) > max_size) {
- chunk = sentence;
- sentence_count = 1;
- }
- }
- else {
- chunk = test_chunk;
- sentence_count++;
- }
- }
-
- END {
- if (length(chunk) > 0) {
- print chunk;
- }
- }' > "$TEMP_DIR/chunks.txt"
-
-process_chunk() {
- local chunk="$1"
- local output_file="$2"
- echo "Processing: ${chunk:0:40}..."
- echo "$chunk" > "$TEMP_DIR/current_chunk.txt"
-
- "$EXEC_PATH" \
- --model "$MODEL_PATH" \
- --data "$VOICE_DATA" \
- --speed "$SPEED" \
- --style "$VOICE_STYLE" \
- text "$(cat "$TEMP_DIR/current_chunk.txt")" \
- --output "$output_file"
-
- if [ ! -f "$output_file" ]; then
- echo "Error: Failed to create audio file for chunk. Skipping..."
- return 1
- fi
-
- return 0
-}
-
-# Process the first chunk immediately
-FIRST_CHUNK=$(head -n 1 "$TEMP_DIR/chunks.txt")
-FIRST_OUTPUT="$TEMP_DIR/chunk_0.wav"
-process_chunk "$FIRST_CHUNK" "$FIRST_OUTPUT"
-
-if [ -f "$FIRST_OUTPUT" ]; then
- aplay "$FIRST_OUTPUT" &
- PLAY_PID=$!
-else
- echo "Failed to process first chunk. Continuing with next chunks..."
- PLAY_PID=0
-fi
-
-# Process remaining chunks
-CHUNK_NUM=1
-while read -r chunk; do
- if [ $CHUNK_NUM -eq 1 ]; then
- CHUNK_NUM=$((CHUNK_NUM + 1))
- continue
- fi
-
- OUTPUT_FILE="$TEMP_DIR/chunk_$CHUNK_NUM.wav"
-
- process_chunk "$chunk" "$OUTPUT_FILE"
-
- if [ $PLAY_PID -ne 0 ]; then
- wait $PLAY_PID || true
- fi
-
- if [ -f "$OUTPUT_FILE" ]; then
- aplay "$OUTPUT_FILE" &
- PLAY_PID=$!
- else
- echo "Skipping playback of chunk $CHUNK_NUM (file not created)"
- PLAY_PID=0
- fi
-
- CHUNK_NUM=$((CHUNK_NUM + 1))
-done < "$TEMP_DIR/chunks.txt"
-
-if [ $PLAY_PID -ne 0 ]; then
- wait $PLAY_PID || true
-fi
-
-echo "Processing complete!"
-rm -rf "$TEMP_DIR"
\ No newline at end of file
diff --git a/waybar/config.jsonc b/waybar/config.jsonc
index 6e754f8..34bc8a3 100644
--- a/waybar/config.jsonc
+++ b/waybar/config.jsonc
@@ -5,91 +5,60 @@
"spacing": 0,
"modules-left": [
"niri/workspaces",
+ "custom/keyboard",
+ "custom/bitcoin",
"tray",
- "group/power-wrapper",
- "custom/keyboard"
+ "bluetooth",
+ "group/pulseaudio-wrapper",
+ "group/backlight-wrapper"
],
"modules-center": ["niri/window"],
"modules-right": [
"battery",
- "bluetooth",
- "group/pulseaudio-wrapper",
- "group/backlight-wrapper",
"custom/gpu-power",
"temperature",
"memory",
"cpu",
- "clock"
+ "clock",
+ "custom/power"
],
-"niri/workspaces": {
- "format": "{icon}",
- "format-icons": {
- "1": "Ⅰ",
- "2": "Ⅱ",
- "3": "Ⅲ",
- "4": "Ⅳ",
- "5": "Ⅴ",
- "6": "Ⅵ",
- "7": "Ⅶ",
- "8": "Ⅷ",
- "9": "Ⅸ",
- "default": ""
- }
-},
- "group/power-wrapper": {
- "orientation": "horizontal",
- "drawer": {
- "transition-duration": 300,
- "children-class": "power-hidden",
- "transition-left-to-right": false,
- "click-to-reveal": true
- },
- "modules": [
- "custom/power-button",
- "custom/lock",
- "custom/reboot",
- "custom/power"
- ]
+
+ "niri/workspaces": {
+ "format": "{icon}",
+ "format-icons": {
+ "1": "Ⅰ",
+ "2": "Ⅱ",
+ "3": "Ⅲ",
+ "4": "Ⅳ",
+ "5": "Ⅴ",
+ "6": "Ⅵ",
+ "7": "Ⅶ",
+ "8": "Ⅷ",
+ "9": "Ⅸ",
+ "default": ""
+ }
},
-
- "niri/window": {
- "format": "{title}",
- "max-length": 50,
- "tooltip": false
- },
-
- "custom/power-button": {
+
+ "custom/power": {
"format": "",
+ "on-click": "~/.local/bin/power-menu.sh",
"tooltip": true,
"tooltip-format": "Power Menu"
},
- "custom/lock": {
- "format": "",
- "on-click": "/home/jrosh/.local/bin/waylock",
- "tooltip": true,
- "tooltip-format": "Lock Screen"
- },
- "custom/reboot": {
- "format": "",
- "on-click": "zenity --question --text='Are you sure you want to reboot?' --icon-name='system-reboot' --title='Reboot System' && sleep 1 && systemctl reboot --force",
- "tooltip": true,
- "tooltip-format": "Reboot"
- },
- "custom/power": {
- "format": "",
- "on-click": "zenity --question --text='Are you sure you want to power off?' --icon-name='system-shutdown' --title='Power Off System' && sleep 1 && systemctl poweroff --force",
- "tooltip": true,
- "tooltip-format": "Power Off"
- },
"custom/keyboard": {
- "format": "{}",
- "exec": "niri msg keyboard-layouts | grep '\\*' | awk '{print $3}' | cut -d'(' -f1",
- "on-click": "niri msg action switch-layout next",
- "interval": 1,
- "tooltip": false
+ "format": "{}",
+ "exec": "niri msg keyboard-layouts | grep '\\*' | awk '{print $3}' | cut -d'(' -f1",
+ "on-click": "niri msg action switch-layout next",
+ "interval": 1,
+ "tooltip": false
},
-
+ "custom/bitcoin": {
+ "exec": "~/.local/bin/bitcoin.sh",
+ "format": "{}",
+ "interval": 180, // Update every 5 minutes
+ "return-type": "json"
+ },
"network": {
"format-wifi": " {essid}",
"format-ethernet": " Wired",
@@ -99,6 +68,7 @@
"format-alt": " {signalStrength}%",
"interval": 1
},
+
"battery": {
"states": {
"warning": 30,
@@ -116,7 +86,7 @@
"drawer": {
"transition-duration": 300,
"children-class": "audio-hidden",
- "transition-left-to-right": false,
+ "transition-left-to-right": true,
"click-to-reveal": true
},
"modules": [
@@ -126,9 +96,10 @@
"custom/audio-settings"
]
},
+
"pulseaudio": {
- "format": "{icon} {volume}%",
- "format-muted": " 0%",
+ "format": "{icon}",
+ "format-muted": "",
"format-icons": {
"headphone": "",
"hands-free": "",
@@ -138,29 +109,30 @@
"car": "",
"default": ["", "", ""]
},
- // Can't use on click events because it won't trigger drawer
- //"on-click": "pavucontrol",
- //"on-click-right": "pactl set-sink-mute @DEFAULT_SINK@ toggle",
"tooltip": true,
"tooltip-format": "Volume: {volume}%"
},
+
"pulseaudio/slider": {
"min": 0,
"max": 100,
"orientation": "horizontal"
},
+
"custom/audio-settings": {
"format": "",
"tooltip": true,
"tooltip-format": "Audio Settings",
"on-click": "pavucontrol"
},
+
"custom/audio-mute": {
"format": "",
"tooltip": true,
"tooltip-format": "Toggle Mute",
"on-click": "pactl set-sink-mute @DEFAULT_SINK@ toggle"
},
+
"temperature": {
"critical-threshold": 80,
"format": "{icon} {temperatureC}°C",
@@ -169,6 +141,7 @@
"tooltip": true,
"tooltip-format": "CPU Temperature: {temperatureC}°C"
},
+
"custom/gpu-power": {
"format": " {}W",
"exec": "nvidia-smi --query-gpu=power.draw --format=csv,noheader,nounits",
@@ -176,21 +149,25 @@
"tooltip-format": "GPU Power: {} Watts",
"interval": 5
},
+
"memory": {
- "format": " {used:0.1f}G/{total:0.1f}G",
+ "format": " {used:0.1f}G/{total:0.1f}G",
"tooltip": true,
"tooltip-format": "Memory: {used:0.2f}G/{total:0.2f}G"
},
+
"cpu": {
"format": " {usage}%",
"tooltip": true
},
+
"clock": {
"interval": 1,
"format": " {:%d.%m %a %H:%M}",
"tooltip": true,
"tooltip-format": "{:L%A, %d-%m-%Y}"
},
+
"tray": {
"icon-size": 14,
"spacing": 4
@@ -201,7 +178,7 @@
"drawer": {
"transition-duration": 300,
"children-class": "backlight-hidden",
- "transition-left-to-right": false,
+ "transition-left-to-right": true,
"click-to-reveal": true
},
"modules": [
@@ -209,12 +186,13 @@
"backlight/slider"
]
},
+
"backlight": {
"device": "intel_backlight",
- "format": "{icon} {percent}%",
+ "format": "{icon}",
"tooltip": true,
"tooltip-format": "Brightness: {percent}%",
- "format-icons": ["", "", "", ""]
+ "format-icons": ["", "", "", ""]
},
"backlight/slider": {
@@ -223,6 +201,7 @@
"orientation": "horizontal",
"device": "intel_backlight"
},
+
"bluetooth": {
"format": " {status}",
"format-connected": " {device_alias}",
diff --git a/waybar/style.css b/waybar/style.css
index a3c13c3..dc4ab11 100644
--- a/waybar/style.css
+++ b/waybar/style.css
@@ -1,31 +1,9 @@
/* =============================================================================
WAYBAR STYLESHEET - GRUVBOX THEME
- A clean, compact design using the Gruvbox color palette
+ Clean, compact design using the Gruvbox color palette
+ Updated for Waybar 0.13.0+
============================================================================= */
-/* -----------------------------------------------------------------------------
- GRUVBOX COLOR PALETTE (for reference)
- ----------------------------------------------------------------------------- */
-/*
- Background: #282828 (bg)
- Background 1: #3c3836 (bg1)
- Background 2: #504945 (bg2)
- Foreground: #ebdbb2 (fg)
- Gray: #928374 (gray)
- Red: #fb4934 (red)
- Green: #b8bb26 (green)
- Yellow: #fabd2f (yellow)
- Blue: #83a598 (blue)
- Purple: #d3869b (purple)
- Aqua: #8ec07c (aqua)
- Orange: #fe8019 (orange)
-
- Standard padding: 2px 4px
- Extended padding: 0px 10px
- Standard margin: 4px
- Border radius: 6px
-*/
-
/* -----------------------------------------------------------------------------
GLOBAL SETTINGS
----------------------------------------------------------------------------- */
@@ -33,262 +11,195 @@
font-family: "BlexMono Nerd Font Mono";
font-weight: 500;
font-size: 13px;
- color: #ebdbb2; /* Gruvbox foreground */
+ color: #ebdbb2;
}
-/* Transparent Waybar background */
#waybar {
- background-color: rgba(0, 0, 0, 0);
+ background-color: transparent;
border: none;
- box-shadow: none;
}
/* -----------------------------------------------------------------------------
MODULE LAYOUTS & BACKGROUNDS
----------------------------------------------------------------------------- */
-/* Standard modules with full rounded corners */
+/* Standard modules with rounded corners */
#workspaces,
#window,
#tray,
-#custom-keyboard {
- background-color: rgba(60, 56, 54, 0.85); /* bg1 with transparency */
+#custom-keyboard,
+#bluetooth,
+#custom-bitcoin {
+ background-color: rgba(60, 56, 54, 0.85);
padding: 2px 6px;
- margin-top: 2px;
- margin-right: 4px;
- margin-bottom: 0;
- margin-left: 4px;
+ margin: 2px 4px 0;
border-radius: 4px;
- border-width: 0px;
+}
+
+#custom-keyboard,
+#bluetooth {
font-size: 10px;
}
-/* Clock - right-side rounded */
-#clock {
- background-color: rgba(60, 56, 54, 0.85); /* bg1 with transparency */
- margin-top: 2px;
- margin-right: 2px;
- margin-bottom: 0;
- margin-left: 0;
- padding: 2px 6px;
- border-radius: 0 4px 4px 0;
- border-width: 0px;
+/* Drawer wrapper modules */
+#backlight-wrapper,
+#pulseaudio-wrapper {
+ background-color: rgba(60, 56, 54, 0.85);
+ padding: 0 8px 0 10px;
+ margin: 2px 4px 0 4px;
+ border-radius: 4px;
+}
+#backlight,
+#pulseaudio{font-size: 1.4rem; padding-right: 4px;}
+
+#custom-audio-settings,
+#custom-audio-mute{
+ padding: 0px 12px;
}
-/* Left-side modules - rounded left edge */
-#network {
- background-color: rgba(60, 56, 54, 0.85); /* bg1 with transparency */
- margin-top: 2px;
- margin-right: 0;
- margin-bottom: 0;
- margin-left: 2px;
+/* Clock - right edge */
+#custom-power {
+ background-color: rgba(60, 56, 54, 0.85);
+ margin: 2px 2px 0 0;
+ padding: 2px 12px;
+ border-radius: 0 4px 4px 0;
+ font-size: 14px;
+}
+
+/* Battery - left edge */
+#battery {
+ background-color: rgba(60, 56, 54, 0.85);
+ margin: 2px 0 0 2px;
padding: 2px 8px;
border-radius: 4px 0 0 4px;
- border-width: 0px;
}
/* Middle modules - no rounded edges */
-#bluetooth,
-#battery,
-#pulseaudio,
-#backlight,
#temperature,
#memory,
#cpu,
-#custom-gpu-power,
-#custom-audio-settings,
-#custom-audio-mute
-{
- background-color: rgba(60, 56, 54, 0.85); /* bg1 with transparency */
- margin-top: 2px;
- margin-right: 0;
- margin-bottom: 0;
- margin-left: 0;
+#clock,
+#custom-gpu-power {
+ background-color: rgba(60, 56, 54, 0.85);
+ margin: 2px 0 0;
padding: 2px 6px;
- border-width: 0px;
min-width: 18px;
}
+/* Audio settings icons */
+#custom-audio-settings,
+#custom-audio-mute {
+ font-size: 16px;
+}
+
+/* -----------------------------------------------------------------------------
+ SLIDER STYLING - PROPER CSS NODES
+ ----------------------------------------------------------------------------- */
+
+/* Slider containers */
#pulseaudio-slider,
#backlight-slider {
- background-color: rgba(60, 56, 54, 0.85);
- margin-top: 2px;
- margin-right: 0;
- margin-bottom: 0;
- margin-left: 0;
+ margin: 2px 0 0;
padding: 2px 6px;
- border-width: 0px;
min-width: 18px;
-}
+}
+/* Hide the actual slider handle */
#pulseaudio-slider slider,
-#backlight-slider slider{
- min-height: 0px;
- min-width: 0px;
+#backlight-slider slider {
+ min-height: 0;
+ min-width: 0;
opacity: 0;
- background-image: none;
+ background: transparent;
border: none;
box-shadow: none;
}
+/* Trough - the unfilled background */
#pulseaudio-slider trough,
#backlight-slider trough {
min-height: 8px;
min-width: 80px;
border-radius: 6px;
- background-color: #282828; /* bg - darker for contrast */
+ background-color: #282828;
}
-#pulseaudio-slider highlight,
+/* Highlight - the filled portion */
#backlight-slider highlight {
min-width: 4px;
+ min-height: 8px;
border-radius: 6px;
- background-color: #fabd2f; /* yellow - bright and visible */
+ background-color: #fabd2f;
}
-#pulseaudio-slider highlight{
+
+#pulseaudio-slider highlight {
+ min-width: 4px;
+ min-height: 8px;
+ border-radius: 6px;
background-color: #8ec07c;
}
-#custom-audio-settings,
-#custom-audio-mute{
- font-size: 16px;
-}
-
-/* -----------------------------------------------------------------------------
- POWER MANAGEMENT GROUP
- ----------------------------------------------------------------------------- */
-
-/* Power management drawer toggle button - standalone with full radius */
-#custom-power-button {
- background-color: rgba(60, 56, 54, 0.85); /* bg1 with transparency */
- margin-top: 2px;
- margin-right: 2px;
- margin-bottom: 0;
- margin-left: 2px;
- padding: 2px 6px;
- border-width: 0px;
- border-radius: 4px;
- min-width: 18px;
-}
-
-/* Lock button - first in power group, left rounded edge */
-#custom-lock {
- background-color: rgba(60, 56, 54, 0.85); /* bg1 with transparency */
- margin-top: 2px;
- margin-right: 0;
- margin-bottom: 0;
- margin-left: 2px;
- padding: 2px 6px;
- border-radius: 4px 0 0 4px;
- border-width: 0px;
-}
-
-/* Reboot button - middle button, no rounded edges */
-#custom-reboot {
- background-color: rgba(60, 56, 54, 0.85); /* bg1 with transparency */
- margin-top: 2px;
- margin-right: 0;
- margin-bottom: 0;
- margin-left: 0;
- padding: 2px 6px;
- border-width: 0px;
- border-radius: 0;
- min-width: 18px;
-}
-
-/* Power button - last in group, right rounded edge */
-#custom-power {
- background-color: rgba(60, 56, 54, 0.85); /* bg1 with transparency */
- margin-top: 2px;
- margin-right: 0;
- margin-bottom: 0;
- margin-left: 0;
- padding: 2px 6px;
- border-width: 0px;
- border-radius: 0 4px 4px 0;
- min-width: 18px;
-}
-
-.power-hidden:hover,
-#custom-power-button:hover .power-hidden,
-#custom-reboot:hover .power-hidden,
-#custom-power:hover .power-hidden,
-.backlight-hidden:hover,
-#backlight:hover .backlight-hidden,
-#backlight-slider:hover .power-hidden,
-.audio-hidden:hover,
-#pulseaudio:hover .audio-hidden,
-#pulseaudio-slider:hover .audio-hidden {
- opacity: 1;
+/* Drawer reveal on hover */
+.backlight-hidden,
+.audio-hidden {
+ transition: opacity 300ms;
}
/* -----------------------------------------------------------------------------
WORKSPACES (NIRI)
----------------------------------------------------------------------------- */
-/* Default workspace buttons */
+/* Workspace buttons default state */
#workspaces button {
background: transparent;
border: none;
- color: #928374; /* Gruvbox gray */
+ color: #928374;
padding: 1px 6px;
margin: 0 1px;
font-weight: 500;
border-radius: 0;
+ transition: all 200ms ease;
}
/* Hovered workspace */
#workspaces button:hover {
- background-color: rgba(131, 165, 152, 0.2); /* Gruvbox aqua with transparency */
+ background-color: rgba(131, 165, 152, 0.2);
padding: 1px 6px;
margin: 0 1px;
border-radius: 6px;
}
-/* Active workspace */
+/* Active workspace - clear distinct styling */
#workspaces button.active {
- background-color: #83a598; /* Gruvbox blue */
- color: #282828; /* Gruvbox bg */
+ background-color: #83a598;
+ color: #282828;
padding: 1px 6px;
margin: 0 1px;
border-radius: 6px;
+ font-weight: 600;
}
/* Urgent workspace */
#workspaces button.urgent {
- background-color: #fb4934; /* Gruvbox red */
- color: #282828; /* Gruvbox bg */
+ background-color: #fb4934;
+ color: #282828;
padding: 1px 6px;
margin: 0 1px;
border-radius: 6px;
}
+/* Empty workspace styling */
+#workspaces button.empty {
+ color: #665c54;
+}
+
/* -----------------------------------------------------------------------------
WINDOW TITLE
----------------------------------------------------------------------------- */
#window {
font-weight: 400;
font-style: italic;
- color: #ebdbb2; /* Gruvbox foreground */
-}
-
-/* -----------------------------------------------------------------------------
- CUSTOM MODULES - COLORS
- ----------------------------------------------------------------------------- */
-
-/* Lock button */
-#custom-lock {
- color: #8ec07c; /* Gruvbox aqua */
-}
-
-/* Reboot button */
-#custom-reboot {
- color: #fabd2f; /* Gruvbox yellow */
-}
-
-/* Power button */
-#custom-power {
- color: #fb4934; /* Gruvbox red */
+ color: #ebdbb2;
}
/* -----------------------------------------------------------------------------
@@ -297,121 +208,117 @@
/* Network */
#network {
- color: #8ec07c; /* Gruvbox aqua */
+ color: #8ec07c;
}
-/* Battery */
+/* Battery states */
#battery {
- color: #b8bb26; /* Gruvbox green */
+ color: #b8bb26;
}
#battery.warning {
- color: #fabd2f; /* Gruvbox yellow */
+ color: #fabd2f;
}
#battery.critical {
- color: #fb4934; /* Gruvbox red */
+ color: #fb4934;
+ animation: blink 1s ease-in-out infinite;
}
-/* Bluetooth */
-#bluetooth {
- color: #83a598; /* Gruvbox blue */
+@keyframes blink {
+ 50% {
+ opacity: 0.5;
+ }
}
/* Audio */
#pulseaudio {
- color: #8ec07c; /* Gruvbox aqua */
+ /* color: #8ec07c; */
+ color: #ebdbb2;
}
#pulseaudio.muted {
- color: #fb4934; /* Gruvbox red */
+ color: #fb4934;
}
/* Backlight */
-#backlight {
- color: #fabd2f; /* Gruvbox yellow */
-}
+/* #backlight {
+ color: #fabd2f;
+} */
/* GPU Power */
#custom-gpu-power {
- color: #83a598; /* Gruvbox blue */
+ color: #83a598;
}
-/* Temperature */
+/* Temperature states */
#temperature {
- color: #fe8019; /* Gruvbox orange */
+ color: #fe8019;
}
#temperature.warning {
- color: #fabd2f; /* Gruvbox yellow */
+ color: #fabd2f;
}
#temperature.critical {
- color: #fb4934; /* Gruvbox red */
+ color: #fb4934;
}
-/* Memory */
+/* Memory states */
#memory {
- color: #d3869b; /* Gruvbox purple */
+ color: #d3869b;
}
#memory.warning {
- color: #fabd2f; /* Gruvbox yellow */
+ color: #fabd2f;
}
#memory.critical {
- color: #fb4934; /* Gruvbox red */
+ color: #fb4934;
}
-/* CPU */
+/* CPU states */
#cpu {
- color: #fe8019; /* Gruvbox orange */
+ color: #fe8019;
}
#cpu.warning {
- color: #fabd2f; /* Gruvbox yellow */
+ color: #fabd2f;
}
#cpu.critical {
- color: #fb4934; /* Gruvbox red */
+ color: #fb4934;
}
/* Clock */
#clock {
- color: #d3869b; /* Gruvbox purple */
+ color: #8ec07c;
}
-/* System tray */
+/* -----------------------------------------------------------------------------
+ SYSTEM TRAY
+ ----------------------------------------------------------------------------- */
#tray {
- background-color: rgba(60, 56, 54, 0.85); /* bg1 with transparency */
+ background-color: rgba(60, 56, 54, 0.85);
padding: 2px 6px;
}
#tray > .passive {
padding: 1px 3px;
- margin-top: 0;
- margin-right: 1px;
- margin-bottom: 0;
- margin-left: 1px;
-}
-
-#tray > .needs-attention {
- padding: 1px 3px;
- margin-top: 0;
- margin-right: 1px;
- margin-bottom: 0;
- margin-left: 1px;
- background-color: #fb4934; /* Gruvbox red */
- color: #282828; /* Gruvbox bg */
- border-radius: 3px;
+ margin: 0 1px;
}
#tray > .active {
padding: 1px 3px;
- margin-top: 0;
- margin-right: 1px;
- margin-bottom: 0;
- margin-left: 1px;
+ margin: 0 1px;
+}
+
+#tray > .needs-attention {
+ padding: 1px 3px;
+ margin: 0 1px;
+ background-color: #fb4934;
+ color: #282828;
+ border-radius: 3px;
}
/* -----------------------------------------------------------------------------
@@ -419,21 +326,15 @@
----------------------------------------------------------------------------- */
#bluetooth:hover,
#network:hover,
-#backlight:hover,
#custom-audio-settings:hover,
#custom-audio-mute:hover,
#battery:hover,
-#pulseaudio:hover,
#temperature:hover,
#memory:hover,
#cpu:hover,
#clock:hover,
-#custom-lock:hover,
-#custom-reboot:hover,
#custom-power:hover,
-#custom-power-button:hover,
#window:hover {
- background-color: rgba(80, 73, 69, 0.9); /* Gruvbox bg2 */
+ background-color: rgba(80, 73, 69, 0.9);
+ transition: background-color 200ms ease;
}
-
-
diff --git a/waylock b/waylock
deleted file mode 100755
index 2d7bb4a..0000000
--- a/waylock
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/bash
-
-# Gruvbox Dark Theme Swaylock Command
-# Colors based on the Gruvbox color scheme
-# Background: dark0_hard (#1d2021)
-# Foreground: light1 (#ebdbb2)
-# Red: bright_red (#fb4934)
-# Green: bright_green (#b8bb26)
-# Yellow: bright_yellow (#fabd2f)
-# Blue: bright_blue (#83a598)
-# Purple: bright_purple (#d3869b)
-# Orange: bright_orange (#fe8019)
-
-swaylock \
- --color 1d2021 \
- --inside-color 282828 \
- --inside-clear-color 458588 \
- --inside-caps-lock-color fabd2f \
- --inside-ver-color d3869b \
- --inside-wrong-color fb4934 \
- --ring-color 3c3836 \
- --ring-clear-color 689d6a \
- --ring-caps-lock-color fe8019 \
- --ring-ver-color b16286 \
- --ring-wrong-color cc241d \
- --line-color 00000000 \
- --line-clear-color 00000000 \
- --line-caps-lock-color 00000000 \
- --line-ver-color 00000000 \
- --line-wrong-color 00000000 \
- --text-color ebdbb2 \
- --text-clear-color 1d2021 \
- --text-caps-lock-color 1d2021 \
- --text-ver-color 1d2021 \
- --text-wrong-color 1d2021 \
- --key-hl-color b8bb26 \
- --bs-hl-color fb4934 \
- --caps-lock-key-hl-color fe8019 \
- --caps-lock-bs-hl-color fb4934 \
- --separator-color 00000000 \
- --indicator-radius 100 \
- --indicator-thickness 7 \
- --indicator-idle-visible \
- --font "BlexMono Nerd Font Mono" \
- --font-size 24 \
- --show-failed-attempts \
- --show-keyboard-layout