You are not logged in.

#1 2023-11-21 11:35:51

dogknowsnx
Member
Registered: 2021-04-12
Posts: 648

[ WAYBAR MODULE v0.7.1 ] RI - Rest your Eyes and Self

If you're the kind that wants to take regular breaks but you need a little nudge in order to do so, this might be for you.
This module is a very lightweight alternative to - and inspired by - SafeEyes. It will remind you to take a break every 20min by default (adjust "interval" inside the module to your liking). There will be a 10s queue during which you can pause a video etc. or opt out of the scheduled break by right-clicking on the icon - but there is a twist...

- This module has been tested successfully on other (non-systemd) Linux distros -

Scope/Features:

  • Break reminder (using 'bemenu-wayland')

  • Notifications (acoustical - 10s before a break and at the end of a break; optional 'libnotify').

  • Basic options (ships a config file; requires 'jq')

  • Skip breaks (no strict mode available)

  • Rewards (simple count of breaks taken consecutively - will be reduced to '1' by cheating as well as skipping on right-click)

  • Simplicity

(I'm not able to test this on a multi-display setup - please let me know if it works.
I don't mind listening to feature requests, but this module features everything I need right now, and I'd like to keep it simple.)

Please place script files (*.sh) inside '~/.local/bin/' and utility files inside '~/.local/share/',
and don't forget to make the scripts executable. Once everything is set up, you can test the module by running '~/.local/bin/ri.sh' from the terminal.

ri.sh:

#!/bin/bash
#
#[v0.7.1]
#
# This script depends on 'bemenu-wayland' 'jq'


[ $(pidof bemenu) ] && pkill -x bemenu

class="enabled" # don't move [10]

RIN=/tmp/riNHB
TMR=/tmp/riTMR
LCS=~/.local/share
CFG=${LCS}/ri.conf
RIT=${LCS}/ri.txt

tmo_cfg=$(jq -r .timeout_sec ${CFG})
idl_cfg=$(jq -r .idle_sec ${CFG})
snd_q_cfg=$(jq -r .sound_queue ${CFG})
snd_e_cfg=$(jq -r .sound_end ${CFG})
prs_cfg=$(jq -r .prompt_string ${CFG})
psr_cfg=$(jq -r .persist_reboot ${CFG})
trp_cfg=$(jq -r .transparent ${CFG})
lns_cfg=$(jq -r .lines ${CFG})

if [ -f ${CFG} ]
then
	if [[ "${tmo_cfg}" -lt 15 ]] || [[ "${tmo_cfg}" -gt 300 ]]
	then
		tmo_cfg=60
	fi

	if [[ "${psr_cfg}" = "yes" ]]
	then
		RIB=~/.cache/riBRK
	else
		RIB=/tmp/riBRK

		rm -f ~/.cache/riBRK
	fi
else
	tmo_cfg=60
	RIB=/tmp/riBRK

	rm -f ~/.cache/riBRK
fi

[ -f ${RIB} ] || date '+%H:%M' > ${RIB}

lst_brk=$(tail -n 1 ${RIB})
cnt_brk=$(cat ${RIB} | wc -l)

menu="<span color='#555555'>On click: on|off\nRight-click: skip</span>"

prt() {
	printf '%s\n' "{\"class\":\"$class\",\"tooltip\":\
			\"RI-mode: $class\nTimeout: ${tmo_cfg}s\nRewards: $cnt_brk  @$lst_brk\n$menu\"}"

	rm -f ${TMR}
}

trap prt EXIT

[ -s ${RIN} ] && exit

pgrep -f rinhibit >/dev/null 2>&1 && exit

[[ "$(( $(date +"%s") - $(stat -c "%Y" "/proc/$(pidof -s waybar)") ))" -lt "10" ]] && exit

if [[ "$(( $(date +"%s") - $(stat -c "%Y" "${RIB}") ))" -gt ${idl_cfg} ]]
then
	date '+%H:%M' >> ${RIB}

	exit
fi

tmr() {
	while pidof bemenu >/dev/null 2>&1
		do
			echo "1" >> ${TMR} ; sleep 1
		done
}

if [ -f ${CFG} ] && [[ "${trp_cfg}" = "yes" ]]
then
	bmn() {
		timeout ${tmo_cfg} bemenu -l "${lns_cfg}" -n -s -w --cw 1 --prompt="${prs_cfg} " \
			--fn 'monospace 15' --fixed-height --monitor=all --cf \#00000000 \
			--nf \#999999 --af \#999999 --hf \#00CF52 --tf \#999999 \
			--nb \#000000E6 --hb \#000000E6 --sb \#000000E6 \
			--ab \#000000E6 --fb \#00000000 --tb \#000000E6 &
	}
else
	bmn() {
		timeout ${tmo_cfg} bemenu -l "${lns_cfg}" -n -s -w --cw 1 --prompt="${prs_cfg}" \
			--fn 'monospace 15' --fixed-height --monitor=all --cf \#00000000 \
			--tf \#999999 --nf \#999999 --af \#999999 --hf \#00CF52 &
	}
fi

if [[ "${class}" = "enabled" ]]
then
	paplay ${LCS}/${snd_q_cfg} &
	# Alternatively (requires 'alsa-utils'):
	#aplay -q --file-type=wav ${LCS}/${snd_q_cfg} &

	# Popup (requires 'libnotify'):
	#notify-send -t 10000 "RI" "10...9...8..."

	sleep 10

	if [ ! -s ${RIN} ]
	then
		if [ -f ${RIT} ]
		then
			shuf -n 1 ${RIT} | bmn > /dev/null

			tmr
		else
			echo "Rest your eyes..." | bmn > /dev/null

			tmr
		fi

		TMT=$(( ${tmo_cfg} - 5 ))
		if [[ "$(cat ${TMR} | wc -l)" -lt ${TMT} ]]
		then
			echo "$(tail -n 1 ${RIB})" > ${RIB}
		else
			date '+%H:%M' >> ${RIB}
		fi

		lst_brk=$(tail -n 1 ${RIB})
		cnt_brk=$(cat ${RIB} | wc -l)

		paplay ${LCS}/${snd_e_cfg}
		# Alternatively (requires 'alsa-utils'):
		#aplay -q --file-type=wav ${LCS}/${snd_e_cfg}
	fi
fi

# Source code: "https://bbs.archlinux.org/viewtopic.php?id=290491"

module (NOTE: if you're on 'hyprland' or 'qtile', please use the second module):

    "custom/ri": {
        "format": "",
    //    "format": "<span size='large'></span>",
        "interval": 1200,
        "return-type":"json",
        "exec": "sleep 0.3 && ~/.local/bin/ri.sh",
        "on-click": "~/.local/bin/ri_swt.sh",
        "on-click-right": "~/.local/bin/ri_skp.sh",
        "tooltip": true
    },

module (qtile):

    "custom/ri": {
        "format": "",
    //    "format": "<span size='large'></span>",
        "interval": 1200,
        "return-type":"json",
        "exec": "sleep 0.5 && ~/.local/bin/ri.sh",
        "on-click": "sleep 0.3 && ~/.local/bin/ri_swt.sh",
        "on-click-right": "~/.local/bin/ri_skp.sh",
        "tooltip": true
    },

ri_swt.sh:

#!/bin/bash

RIN=/tmp/riNHB
RIS=~/.local/bin/ri.sh

if grep 'class="enabled"' ${RIS} >/dev/null 2>&1
then
	sed -i "10s/class=.*\ #/class=\"disabled\"\ #/" ${RIS}
else
	sed -i "10s/class=.*\ #/class=\"enabled\"\ #/" ${RIS}
fi

echo "skip" > ${RIN} && sleep 1 && : > ${RIN}

# Source code: "https://bbs.archlinux.org/viewtopic.php?id=290491"

ri_skp.sh:

#!/bin/bash

RIN=/tmp/riNHB
CFG=~/.local/share/ri.conf
psr_cfg=$(jq -r .persist_reboot ${CFG})

if [ -f ${CFG} ]
then
	if [[ "${psr_cfg}" = "yes" ]]
	then
		RIB=~/.cache/riBRK
	else
		RIB=/tmp/riBRK

		rm -f ~/.cache/riBRK
	fi
else
	RIB=/tmp/riBRK

	rm -f ~/.cache/riBRK
fi

echo "$(tail -n 1 ${RIB})" > ${RIB}
echo "skip" > ${RIN} && sleep 15 && : > ${RIN}

# Source code: "https://bbs.archlinux.org/viewtopic.php?id=290491"

style:

#custom-ri.enabled {
    color: #00CF52;
}

#custom-ri.disabled {
    color: #555555;
}

# Utility files

ri.conf:

{
  "timeout_sec": "60",
  "idle_sec": "18000",
  "sound_queue": "Hummingbird.wav",
  "sound_end": "A-Tone.wav",
  "prompt_string": "BREATHE!",
  "persist_reboot": "no",
  "transparent": "yes",
  "lines": "50"
}

NOTE: If 'bemenu' doesn't show up (depending on your hw/compositor combo), you may want to play with the "lines" option, e.g. decrease the number until 'bemenu' shows up).

The default sound files (wav) can be downloaded from:
https://soundbible.com/1815-A-Tone.html
https://soundbible.com/940-Hummingbird.html (though I think they recorded a swallow, not a hummingbird tongue)

Please rename and copy them to '~/.local/share/', or use/copy different files and set them in the config, respectively.

ri.txt (example - list of newline separated messages to be shown randomly during breaks):

Rest your eyes...
Everything is OK...
Enjoy the silence...
Let's do some eye gymnastics...

For more info on how to add the module to waybar, please consult:
https://github.com/Alexays/Waybar


# WIP (workaround for systemd - skip if using 'acpid')

In order to automatically skip breaks on resume from suspend, create the service file below and enable it by issuing (replace 'username' with your actual user):

# systemctl enable resume@username

/etc/systemd/system/resume@.service:

[Unit]
Description=User resume actions
After=suspend.target

[Service]
User=%I
Type=simple
ExecStart=/bin/sh -c 'exec -a rinhibit sleep 3' &

[Install]
WantedBy=suspend.target

If you are already using that service, simply append the 'ExecStart' command above (<your commands> ; <new command>)
For more info, please see: https://wiki.archlinux.org/title/Power_ … vice_files

Correspondingly, use the command below whenever you want to inhibit the module (e.g. in theming scripts using symlinks to different 'style.css' files where 'waybar' needs to be reloaded):

sh -c 'exec -a rinhibit sleep 3' &

This will spawn a simple 3 second sleep process renamed to "rinhibit", which gets picked up by the module.


# Screenshots

HwXv.png
The timeout is user configurable - valid values are 15s to 300s (defaults to 60s)

H3KU.png
NOTE: 'bemenu' will not overlay fullscreen applications - bemenu >=0.6.17


ri_upd.sh (script that checks for updates of this module - make sure to bump the version number found at the top of 'ri.sh' in order for this to work. Basically do the update according to the changelog..):

#!/bin/bash

RI="RI-module"
UTD="up-to-date"
UPD="Update"
SCR=~/.local/bin/ri.sh
URL=https://bbs.archlinux.org/viewtopic.php?id=290491

BLUE='\e[1;34m'
GREEN='\e[1;36m'
NOCOLOR='\e[0m'

grp() {
	grep $(curl -s "$1" | head -n 6 | grep "MODULE" |
		cut -d' ' -f 4) "$2" >/dev/null 2>&1
}

nsd() {
	[ -x /usr/bin/notify-send ] &&
		notify-send -t 5000 "$@"
}

ping -n -c 1 archlinux.org >/dev/null 2>&1 || exit 2

echo

if [ -f ${SCR} ]
then
	if grp ${URL} ${SCR}
	then
		printf "${RI}: ${BLUE}${UTD}${NOCOLOR}\n"

		nsd "${RI}" "${UTD}" --urgency=low
	else
		printf "${RI}: ${GREEN}${UPD}${NOCOLOR}: \"${URL}\"\n"

		nsd "${RI}" "${UPD} available"
	fi
fi

echo

Additional links:
https://github.com/Cloudef/bemenu

Other "humane tech" recommendations:
https://gitlab.com/chinstrap/gammastep / https://sr.ht/~kennylevinsen/wlsunset
https://github.com/darkreader/darkreader


CHANGELOG: 'Initial beta release 'v0.1.b'; forgot to add 'style' - *oops*; #ri.sh: implement inhibit on first start; bump version to 'v0.2.b'; #ri.conf: added option for transparency; #ri.sh: made necessary changes; bump version to 'v0.3.b'; #ri.conf: increase default timeout to 60s; #ri.sh: made necessary changes; 'bmn()': added '--monitor=all' switch; #ri.conf: added option for setting number of lines (height adjustment); #ri.sh: made necessary changes; bump version to 'v0.4.b'; #ri.sh: rewards will now be revoked by cheating, as well; bump version to 'v0.5.b': #ri.conf: added option to make rewards persistent upon reboot; #ri_skp.sh: made necessary changes: #ri.sh: made necessary changes; bump version to 'v0.6.b'; #ri.sh: small optimization; bump version to 'v0.7.b'; #ri.sh: "tooltip": new layout; play queue sound in background; bump version to 'v0.7.0'; #ri.conf: added option for setting an idle period (Explanation: If there hasn't been any activity for the given period of time, this period will be considered as a break taken, and the next scheduled break will be skipped - the value must be higher than the interval between breaks set in the module - it's effectively disabled by default by setting it to 5 hours); #ri.sh: made necessary changes; bump version to 'v0.7.1''

Last edited by dogknowsnx (Yesterday 08:47:12)


RI - Rest your Eyes and Self

"We are eternal, all this pain is an illusion" - Maynard James Keenan

Offline

Board footer

Powered by FluxBB