more qr tweaks (closes #533);

* --qr-every draws the qr-code periodically, with/without --qr-pin
* --qr-winch redraws --qr-pin on console size change
* --qr-pin logs detected console size for debug
This commit is contained in:
ed 2025-08-27 19:01:19 +00:00
parent f4f702c39d
commit 2848941e01
2 changed files with 53 additions and 14 deletions

View file

@ -1157,6 +1157,8 @@ def add_qr(ap, tty):
ap2.add_argument("--qrz", metavar="N", type=int, default=0, help="[\033[32m1\033[0m]=1x, [\033[32m2\033[0m]=2x, [\033[32m0\033[0m]=auto (try [\033[32m2\033[0m] on broken fonts)")
ap2.add_argument("--qr-pin", metavar="N", type=int, default=0, help="sticky/pin the qr-code to always stay on-screen; [\033[32m0\033[0m]=disabled, [\033[32m1\033[0m]=with-url, [\033[32m2\033[0m]=just-qr")
ap2.add_argument("--qr-wait", metavar="SEC", type=float, default=0, help="wait \033[33mSEC\033[0m before printing the qr-code to the log")
ap2.add_argument("--qr-every", metavar="SEC", type=float, default=0, help="print the qr-code every \033[33mSEC\033[0m (try this with/without --qr-pin in case of issues)")
ap2.add_argument("--qr-winch", metavar="SEC", type=float, default=0, help="when --qr-pin is enabled, check for terminal size change every \033[33mSEC\033[0m")
ap2.add_argument("--qr-file", metavar="TXT", type=u, action="append", help="\033[34mREPEATABLE:\033[0m write qr-code to file.\n └─To create txt or svg, \033[33mTXT\033[0m is Filepath:Zoom:Pad, for example [\033[32mqr.txt:1:2\033[0m]\n └─To create png or gif, \033[33mTXT\033[0m is Filepath:Zoom:Pad:Foreground:Background, for example [\033[32mqr.png:8:2:333333:ffcc55\033[0m], or [\033[32mqr.png:8:2::ffcc55\033[0m] for transparent")

View file

@ -134,6 +134,7 @@ class SvcHub(object):
self.nsigs = 3
self.retcode = 0
self.httpsrv_up = 0
self.qr_tsz = None
self.log_mutex = threading.Lock()
self.cday = 0
@ -787,7 +788,27 @@ class SvcHub(object):
self.signal_handler(signal.SIGTERM, None)
def sticky_qr(self) -> None:
tw, th = termsize()
self._sticky_qr()
def _unsticky_qr(self, flush=True) -> None:
print("\033[s\033[J\033[r\033[u", file=sys.stderr, end="")
if flush:
sys.stderr.flush()
def _sticky_qr(self, force: bool = False) -> None:
sz = termsize()
if self.qr_tsz == sz:
if not force:
return
else:
force = False
if self.qr_tsz:
self._unsticky_qr(False)
else:
atexit.register(self._unsticky_qr)
tw, th = self.qr_tsz = sz
zs1, qr = self.tcpsrv.qr.split("\n", 1)
url, colr = zs1.split(" ", 1)
nl = len(qr.split("\n")) # numlines
@ -811,17 +832,34 @@ class SvcHub(object):
url = "%s\033[%d;%dH%s\033[0m" % (colr, sh + 1, (nl + lp) * 2, url)
qr = colr + qr
def unlock():
print("\033[s\033[r\033[u", file=sys.stderr)
atexit.register(unlock)
t = "%s\033[%dA" % ("\n" * nl, nl)
t = "%s\033[s\033[1;%dr\033[%dH%s%s\033[u" % (t, sh - 1, sh, qr, url)
self.pr(t, file=sys.stderr)
if not force:
self.log("qr", "sticky-qrcode %sx%s,%s" % (tw, th, sh), 6)
self.pr(t, file=sys.stderr, end="")
def sleepy_qr(self):
time.sleep(self.args.qr_wait)
self.log("qr-code", self.tcpsrv.qr)
def _qr_thr(self):
qr = self.tcpsrv.qr
w8 = self.args.qr_wait
if w8:
time.sleep(w8)
self.log("qr-code", qr)
w8 = self.args.qr_every
msg = "%s\033[%dA" % (qr, len(qr.split("\n")))
while w8:
time.sleep(w8)
if self.stopping:
break
if self.args.qr_pin:
self._sticky_qr(True)
else:
self.log("qr-code", msg)
w8 = self.args.qr_winch
while w8:
time.sleep(w8)
if self.stopping:
break
self._sticky_qr()
def cb_httpsrv_up(self) -> None:
self.httpsrv_up += 1
@ -837,11 +875,10 @@ class SvcHub(object):
if self.tcpsrv.qr:
if self.args.qr_pin:
self.sticky_qr()
else:
if self.args.qr_wait:
Daemon(self.sleepy_qr, "qr_w8")
else:
self.log("qr-code", self.tcpsrv.qr)
if self.args.qr_wait or self.args.qr_every or self.args.qr_winch:
Daemon(self._qr_thr, "qr")
elif not self.args.qr_pin:
self.log("qr-code", self.tcpsrv.qr)
else:
self.log("root", "workers OK\n")