You are not logged in.
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 )
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
The timeout is user configurable - valid values are 15s to 300s (defaults to 60s)
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 (2024-04-26 08:47:12)
Offline