From 6a169af344b452cfae113df4c4e5c6d339764fa7 Mon Sep 17 00:00:00 2001 From: Crony Akatsuki Date: Fri, 6 Jun 2025 16:23:00 +0200 Subject: [PATCH] feat(desktop): add more config options for qutebrowser. --- .../greasemonkey/darkmode-disable.js | 16 ++++ .../qutebrowser/greasemonkey/scrollHelper.js | 83 +++++++++++++++++ .../qutebrowser/pyconfig/redirectors.py | 33 +++++++ .../configs/qutebrowser/userscripts/buku | 74 +++++++++++++++ modules/linux/home-manager/qutebrowser.nix | 90 +++---------------- 5 files changed, 219 insertions(+), 77 deletions(-) create mode 100644 modules/linux/home-manager/configs/qutebrowser/greasemonkey/darkmode-disable.js create mode 100644 modules/linux/home-manager/configs/qutebrowser/greasemonkey/scrollHelper.js create mode 100644 modules/linux/home-manager/configs/qutebrowser/pyconfig/redirectors.py create mode 100755 modules/linux/home-manager/configs/qutebrowser/userscripts/buku diff --git a/modules/linux/home-manager/configs/qutebrowser/greasemonkey/darkmode-disable.js b/modules/linux/home-manager/configs/qutebrowser/greasemonkey/darkmode-disable.js new file mode 100644 index 0000000..df64d51 --- /dev/null +++ b/modules/linux/home-manager/configs/qutebrowser/greasemonkey/darkmode-disable.js @@ -0,0 +1,16 @@ +// ==UserScript== +// @name DarkMode Disable +// @match https://monkeytype.com/* +// @match https://nc.cronyakatsuki.xyz/* +// @match https://company-mode.github.io/* +// @match https://adventofcode.com/* +// @match https://cronyakatsuki.xyz/qbt/* +// @match https://www.keybr.com/* +// @match https://192.168.100:8006/* +// @match https://proxmox.me:8006/* +// ==/UserScript== + +const meta = document.createElement("meta"); +meta.name = "color-scheme"; +meta.content = "dark light"; +document.head.appendChild(meta); diff --git a/modules/linux/home-manager/configs/qutebrowser/greasemonkey/scrollHelper.js b/modules/linux/home-manager/configs/qutebrowser/greasemonkey/scrollHelper.js new file mode 100644 index 0000000..6a7cbff --- /dev/null +++ b/modules/linux/home-manager/configs/qutebrowser/greasemonkey/scrollHelper.js @@ -0,0 +1,83 @@ +// ==UserScript== +// @name Adds scrolling JS that can be used within QB to do smarter scrolling +// @qute-js-world jseval +// @run-at document-start +// ==/UserScript== +unsafeWindow.scrollHelper = (() => { + const scrollableElemOverflowTypes = [ + 'auto', + 'scroll', + ] + + const getFocusedWindow = (nextElem) => { + if (nextElem === null) return null + if (nextElem === undefined) return getFocusedWindow(window.document.activeElement ?? null) + return getFocusedWindow(nextElem.contentDocument?.activeElement ?? null) ?? nextElem.ownerDocument?.defaultView ?? null + } + + const getScrollMaxY = ({ document: { documentElement } }) => documentElement.scrollHeight - documentElement.clientHeight + + const getWindowVisibleArea = ({ document: { documentElement } }) => documentElement.clientHeight * documentElement.clientWidth + + const findVertScrollableWindow = () => { + const focusedWindow = getFocusedWindow() ?? window + if (getScrollMaxY(focusedWindow) > 0) return focusedWindow + if (getScrollMaxY(window) > 0) return window + + return Array + .from(window.frames) + .sort((x, y) => getWindowVisibleArea(y) - getWindowVisibleArea(x)) + .find((frame) => getScrollMaxY(frame) > 0) ?? window + } + + const getScrollTopMax = (elem) => elem.scrollHeight - elem.clientHeight + const isElementVertScrollable = (element) => element.clientHeight !==0 && + scrollableElemOverflowTypes.includes(getComputedStyle(element).overflowY) + + const findVertScrollableAncestor = (delta, nextElem) => { + if (!(nextElem?.parentNode instanceof Element)) return nextElem + + if (isElementVertScrollable(nextElem)) { + if (delta < 0 && nextElem.scrollTop > 0) return nextElem + if (delta > 0 && nextElem.scrollTop < getScrollTopMax(nextElem)) return nextElem + if (delta === 0 && getScrollTopMax(nextElem) > 0) return nextElem + } + + return findVertScrollableAncestor(delta, nextElem.parentNode) + } + + const getSelectionElem = () => { + const selection = getFocusedWindow().getSelection() + return selection.rangeCount !== 0 + ? selection.getRangeAt(0).startContainer + : null + } + + const getParentIfNotElement = (maybeElement) => maybeElement instanceof Element ? maybeElement : maybeElement?.parentNode + + const findVertScrollable = (delta = 0) => { + const selectionScrollableElem = findVertScrollableAncestor(delta, getParentIfNotElement(getSelectionElem())) + if (selectionScrollableElem instanceof Element) return selectionScrollableElem + + const scrollableDoc = findVertScrollableWindow().document + const scrollableElem = scrollableDoc.body || scrollableDoc.getElementsByTagName('body')[0] || scrollableDoc.documentElement + return findVertScrollableAncestor(delta, getParentIfNotElement(scrollableElem)) + } + + return { + scrollTo: (position) => findVertScrollable().scrollTo({top: position}), + scrollToPercent: (percentPosition) => { + const scrollElement = findVertScrollable() + const paneHeight = scrollElement.scrollHeight + scrollElement.scrollTo({top: percentPosition / 100 * paneHeight}) + }, + scrollBy: (delta) => findVertScrollable(delta).scrollBy({top: delta, behavior: 'smooth'}), + scrollPage: (pages) => { + const fakeDelta = pages < 0 ? -10 : 10 + const scrollElement = findVertScrollable(fakeDelta) + const pageHeight = scrollElement.clientHeight + scrollElement.scrollBy({top: pageHeight * pages}) + }, + } + +})() diff --git a/modules/linux/home-manager/configs/qutebrowser/pyconfig/redirectors.py b/modules/linux/home-manager/configs/qutebrowser/pyconfig/redirectors.py new file mode 100644 index 0000000..22868c6 --- /dev/null +++ b/modules/linux/home-manager/configs/qutebrowser/pyconfig/redirectors.py @@ -0,0 +1,33 @@ +import operator + +from qutebrowser.api import interceptor, message + +REDIRECT_MAP = { + "reddit.com": operator.methodcaller("setHost", "libreddit.cronyakatsuki.xyz"), + "old.reddit.com": operator.methodcaller("setHost", "libreddit.cronyakatsuki.xyz"), + "www.reddit.com": operator.methodcaller("setHost", "libreddit.cronyakatsuki.xyz"), + "twitter.com": operator.methodcaller("setHost", "nitter.cronyakatsuki.xyz"), + "www.twitter.com": operator.methodcaller("setHost", "nitter.cronyakatsuki.xyz"), + "music.youtube.com": operator.methodcaller( + "setHost", "hyperpipe.cronyakatsuki.xyz" + ), + "twitch.tv": operator.methodcaller("setHost", "safetwitch.cronyakatsuki.xyz"), + "www.twitch.tv": operator.methodcaller("setHost", "safetwitch.cronyakatsuki.xyz"), + "tiktok.com": operator.methodcaller("setHost", "proxytok.cronyakatsuki.xyz"), + "www.tiktok.com": operator.methodcaller("setHost", "proxytok.cronyakatsuki.xyz"), + "imgur.com": operator.methodcaller("setHost", "rimgo.cronyakatsuki.xyz"), + "www.imgur.com": operator.methodcaller("setHost", "rimgo.cronyakatsuki.xyz"), + "github.com": operator.methodcaller("setHost", "gh.cronyakatsuki.xyz"), + "gist.github.com": operator.methodcaller("setHost", "gh.cronyakatsuki.xyz/gist"), +} + + +def int_fn(info: interceptor.Request): + url = info.request_url + redir = REDIRECT_MAP.get(url.host()) + if redir is not None and redir(url) is not False: + message.info("Redirecting to " + url.toString()) + info.redirect(url) + + +interceptor.register(int_fn) diff --git a/modules/linux/home-manager/configs/qutebrowser/userscripts/buku b/modules/linux/home-manager/configs/qutebrowser/userscripts/buku new file mode 100755 index 0000000..ebe9d93 --- /dev/null +++ b/modules/linux/home-manager/configs/qutebrowser/userscripts/buku @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +# Qutebrowser userscript for interacting with buku +# requries buku and dmenu (with list patch) + +get_bookmark() { + buku --nostdin -p -f5 | sed 's/\t/;/g' | column -t -s ';' | tofi --horizontal false --height 380 --prompt-text "$1 bookmark: " | awk '{ print $1 }' +} + +get_url() { + buku --nostdin -p "$1" -f10 +} + +get_title() { + buku --nostdin -p "$1" -f30 +} + +fifo() { + printf '%s\n' "$1" >>"$QUTE_FIFO" +} + +add() { + buku --nostdin -a "$QUTE_URL" + $TERMINAL --class badd,badd -e buku -w -1 + fifo "message-info 'Added current url to buku'" +} + +open() { + bookmark=$(get_bookmark "Open") + [ -z "$bookmark" ] && fifo "message-info 'No Bookmark selected!!!'" && exit + if [ "$1" == "-t" ]; then + fifo "open -t $(get_url "$bookmark")" + fifo "message-info 'Opening bookmark $(get_title "$bookmark") in new tab.'" + else + fifo "open $(get_url "$bookmark")" + fifo "message-info 'Opening bookmark $(get_title "$bookmark").'" + fi +} + +delete() { + bookmark=$(get_bookmark "Delete") + title=$(get_title "$bookmark") + buku --nostdin -d "$bookmark" --tacit + fifo "message-info 'Deleted bookmark $title.'" +} + +edit() { + bookmark=$(get_bookmark "Edit") + fifo "message-info 'Editing bookmark $(get_title "$bookmark")'" + $TERMINAL --class badd,badd -e buku -w "$bookmark" +} + +main() { + case "$1" in + "add") + [ -n "$2" ] && QUTE_URL=$2 + add + exit + ;; + "open") + open "$2" + exit + ;; + "delete") + delete + exit + ;; + "edit") + edit + ;; + esac +} + +main $@ diff --git a/modules/linux/home-manager/qutebrowser.nix b/modules/linux/home-manager/qutebrowser.nix index 0fd1935..2391695 100644 --- a/modules/linux/home-manager/qutebrowser.nix +++ b/modules/linux/home-manager/qutebrowser.nix @@ -9,83 +9,16 @@ config = lib.mkIf config.crony.qutebrowser.enable { home.file = { - ".config/qutebrowser/userscripts/buku" = { - text = '' - #!/usr/bin/env bash - - # Qutebrowser userscript for interacting with buku - # requries buku and dmenu (with list patch) - - get_bookmark() { - buku --nostdin -p -f5 | sed 's/\t/;/g' | column -t -s ';' | tofi --horizontal false --height 380 --prompt-text "$1 bookmark: " | awk '{ print $1 }' - } - - get_url() { - buku --nostdin -p "$1" -f10 - } - - get_title() { - buku --nostdin -p "$1" -f30 - } - - fifo() { - printf '%s\n' "$1" >>"$QUTE_FIFO" - } - - add() { - buku --nostdin -a "$QUTE_URL" - $TERMINAL --class badd,badd -e buku -w -1 - fifo "message-info 'Added current url to buku'" - } - - open() { - bookmark=$(get_bookmark "Open") - [ -z "$bookmark" ] && fifo "message-info 'No Bookmark selected!!!'" && exit - if [ "$1" == "-t" ]; then - fifo "open -t $(get_url "$bookmark")" - fifo "message-info 'Opening bookmark $(get_title "$bookmark") in new tab.'" - else - fifo "open $(get_url "$bookmark")" - fifo "message-info 'Opening bookmark $(get_title "$bookmark").'" - fi - } - - delete() { - bookmark=$(get_bookmark "Delete") - title=$(get_title "$bookmark") - buku --nostdin -d "$bookmark" --tacit - fifo "message-info 'Deleted bookmark $title.'" - } - - edit() { - bookmark=$(get_bookmark "Edit") - fifo "message-info 'Editing bookmark $(get_title "$bookmark")'" - $TERMINAL --class badd,badd -e buku -w "$bookmark" - } - - main() { - case "$1" in - "add") - [ -n "$2" ] && QUTE_URL=$2 - add - exit - ;; - "open") - open "$2" - exit - ;; - "delete") - delete - exit - ;; - "edit") - edit - ;; - esac - } - - main $@ - ''; + ".config/qutebrowser/userscripts" = { + source = ./configs/qutebrowser/userscripts; + executable = true; + }; + ".config/qutebrowser/pyconfig" = { + source = ./configs/qutebrowser/pyconfig; + executable = true; + }; + ".config/qutebrowser/greasemonkey" = { + source = ./configs/qutebrowser/greasemonkey; executable = true; }; }; @@ -93,6 +26,9 @@ programs.qutebrowser = { enable = true; loadAutoconfig = true; + extraConfig = '' + config.source("pyconfig/redirectors.py") + ''; searchEngines = { DEFAULT = "https://searx.cronyakatsuki.xyz/?q={}"; aw = "https://wiki.archlinux.org/?search={}";