fix scroll
ober
ffafa19201f072e1ede32741c6d41e714753d538
--- a/signal/main.ss +++ b/signal/main.ss @@ -143,7 +143,8 @@ linking once before using this tool: (def (main argv) (cond - [(null? argv) (usage) (exit 2)] + [(null? argv) (let-values ([(account args) (parse-account-flag '())]) + (cmd-tui account))] [else (let ([sub (car argv)] [rest (cdr argv)]) --- a/signal/tui/main.ss +++ b/signal/tui/main.ss @@ -12,14 +12,14 @@ terminal-display) (import (except (scheme) - make-hash-table hash-table? - sort sort! - printf fprintf - path-extension path-absolute? - with-input-from-string with-output-to-string - iota 1+ 1- - partition - make-date make-time) + make-hash-table hash-table? + sort sort! + printf fprintf + path-extension path-absolute? + with-input-from-string with-output-to-string + iota 1+ 1- + partition + make-date make-time) (except (jerboa prelude) meta atom?) (std csp) (std text json) @@ -50,7 +50,7 @@ conversations selected-index mode picker-query picker-index removed aliases logdb live-capture? resend challenge rate-limits send-events capture-events capture-stop-box capture-worker - thread-scroll mention-active? mention-index mention-candidates)) + thread-scroll conv-scroll mention-active? mention-index mention-candidates)) ;; Open the encrypted message log. Passphrase comes from JERBOA_SIGNAL_DB_KEY ;; if set (enables headless use), otherwise we prompt. A blank passphrase or a @@ -207,10 +207,11 @@ (make-channel/buf 256) (box #f) #f - 0 - #f - 0 - '())) + 0 + 0 + #f + 0 + '())) ;; Pull recent rows out of the encrypted log so search and scrollback cover ;; previous sessions, not just this one. Runs after contact/group seeding so @@ -1033,6 +1034,16 @@ (tui-state-selected-index-set! state next-index) (conversation-unread-set! conv 0) (tui-state-thread-scroll-set! state 0) + ;; Auto-scroll conversations list so selection is visible. + ;; The visible area shows `height` rows starting at conv-scroll. + (let* ([body-h (max 4 (- (tui-state-height state) 4))] + [left-w (if (< (tui-state-width state) 80) 18 24)] + [height (- body-h 3)] + [scroll (tui-state-conv-scroll state)]) + (when (>= next-index (+ scroll height)) + (tui-state-conv-scroll-set! state (- next-index (- height 1)))) + (when (< next-index scroll) + (tui-state-conv-scroll-set! state next-index))) (cancel-mention! state) (tui-state-status-set! state @@ -2633,26 +2644,36 @@ (def (draw-conversations! state x y width height) (let* ([conversations (tui-state-conversations state)] - [selected-index (clamp-index (tui-state-selected-index state) - (length conversations))]) - (let loop ([conversations conversations] - [idx 0] - [row y]) - (when (and (pair? conversations) (< row (+ y height))) - (let* ([conv (car conversations)] - [selected? (= idx selected-index)] - [marker (if selected? "> " " ")] - [unread (conversation-unread conv)] - [suffix (if (> unread 0) - (string-append " (" (number->string unread) ")") - "")] - [fgc (if selected? (fg-accent) (fg))] - [bgc (if selected? (selected-bg) (panel-bg))]) - (draw-text! x row width fgc bgc - (string-append marker - (conversation-title conv) - suffix)) - (loop (cdr conversations) (+ idx 1) (+ row 1))))))) + [total (length conversations)] + [selected-index (clamp-index (tui-state-selected-index state) total)] + [scroll (tui-state-conv-scroll state)] + [max-scroll (max 0 (- total height))]) + ;; Scroll indicator (up arrow if scroll > 0) + (when (> scroll 0) + (draw-text! x y width (fg-dim) (panel-bg) "^")) + ;; Draw visible slice + (let loop ([idx scroll] + [row (+ y (if (> scroll 0) 1 0))]) + (when (and (< idx total) (< row (+ y height))) + (let* ([conv (list-ref conversations idx)] + [selected? (= idx selected-index)] + [marker (if selected? "> " " ")] + [unread (conversation-unread conv)] + [suffix (if (> unread 0) + (string-append " (" (number->string unread) ")") + "")] + [fgc (if selected? (fg-accent) (fg))] + [bgc (if selected? (selected-bg) (panel-bg))]) + (draw-text! x row width fgc bgc + (string-append marker + (conversation-title conv) + suffix)) + (loop (+ idx 1) (+ row 1))))) + ;; Scroll indicator (down arrow if more items below) + (when (< (+ scroll height) total) + (let* ([ind-row (+ y height -1)] + [ind-row (if (> scroll 0) ind-row (- ind-row 1))]) + (draw-text! x ind-row width (fg-dim) (panel-bg) "v"))))) (def (draw-new-message-page! state x y width height) (draw-panel! x y width height "New Message") @@ -2834,7 +2855,10 @@ width rows scroll)]) - (let loop ([rs rendered] [row (+ y 3)]) + ;; Scroll indicator (up arrow if scroll > 0) + (when (> scroll 0) + (draw-text! x (+ y 3) width (fg-dim) (bg) "^")) + (let loop ([rs rendered] [row (+ y 3 (if (> scroll 0) 1 0))]) (if (and (pair? rs) (< row (+ y 3 rows))) (begin (draw-text! x row width (chat-message-fg (caar rs)) (bg) @@ -2842,7 +2866,11 @@ (loop (cdr rs) (+ row 1))) (when (and typing (< row (+ y height))) (draw-text! x row width (fg-dim) (bg) - (string-append typing " is typing..."))))))) + (string-append typing " is typing..."))))) + ;; Scroll indicator (down arrow if more rows below) + (let* ([max-scroll (max-thread-scroll conv width rows)]) + (when (< scroll max-scroll) + (draw-text! x (+ y height -1) width (fg-dim) (bg) "v"))))) (begin (draw-text! x y width (fg-strong) (bg) "jerboa-signal") (draw-text! x (+ y 1) width (fg-dim) (bg) @@ -2899,6 +2927,17 @@ (clamp-index (+ (tui-state-thread-scroll state) delta) (+ max-scroll 1))))))) + ;; Scroll the conversations list. Positive delta scrolls down. + (def (scroll-conversations! state delta) + (let* ([total (length (tui-state-conversations state))] + [body-h (max 4 (- (tui-state-height state) 4))] + [left-w (if (< (tui-state-width state) 80) 18 24)] + [height (- body-h 3)] + [max-scroll (max 0 (- total height))] + [scroll (tui-state-conv-scroll state)] + [new-scroll (clamp-index (+ scroll delta) (+ max-scroll 1))]) + (tui-state-conv-scroll-set! state new-scroll))) + ;; --- @mention support --- ;; All direct conversation titles (contact names) as mention candidates.