nandi/frqpublic Fork 0
5b10207
Commits
Clone
git clone https://git.rickub.com/nandi/frq.git
git clone ssh://git@rickub.com/nandi/frq.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Give the terminal a compose bar the size of the draft, and a strip that scrolls

Three rows were kept for the compose field whatever was in it: one you typed
in and two ruled empty boxes under it, under a placeholder advertising a
paragraph nobody writes in an IRC client. The field is the size of the draft
now — a line until there is a second line, growing to five and no further —
counted here rather than reported, since nothing in the terminal fires
`:on-rows`. Send and the picture beside it centre on the box instead of
sitting on its first row, and a row of air goes above the bar: a spacer, not
a `:margin-top`, which a terminal does not read.

And the overview strip is a `:scroll` rather than the first eight lines with
the rest simply gone. Two things stood in the way of that. Its height was
counted at twenty points a line, which is a little over half a row here, so
eight lines asked for five rows and got five. And a `:scroll` with no ceiling
is as tall as its content: it took the rows the conversation was reading in
and drew every line rather than scrolling any. Both are one number now, and
`overview-list-height` is what the pane is given and what the backlog is laid
out against.

The ceiling needs `:max-height` honoured for a box in jolt-tui, which it now
is.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandi committed 2026-09-12T00:08:52-07:00 Browse files
5b10207 parent: d8fadee
modified common/frq/screens/chat.cljc +122 -39
@@ -40,6 +40,35 @@
4040
4141 (defonce ^:private draft-rows (atom 1))
4242
43+;; How tall the compose field is allowed to grow. The same ceiling in both
44+;; backends, for different reasons: a window past it scrolls with the caret in
45+;; view, and a terminal past it would be spending a quarter of the screen on
46+;; a message that has not been sent yet.
47+(def ^:private draft-max-rows 5)
48+
49+(defn- terminal-draft-rows
50+ "How many rows the terminal's compose field wants for what is in it.
51+
52+ The library sizes an entry by the `:rows` it was given and reports nothing
53+ back — there is no `:on-rows` to grow on, the way a window grows — so the
54+ wrapping is counted here instead, and the answer is both what the field is
55+ given and what `below-messages` keeps for it.
56+
57+ An empty field is one row, so the bar starts as a line rather than as a
58+ block of ruled nothing, and the text begins at the top of the rect and grows
59+ downwards from there.
60+
61+ The width is the row less what is beside the field — the picture button, the
62+ Send button, and the gaps around them, about twenty-two cells of eight points
63+ each. An estimate, and the cheap way to be wrong: a row over-counted is a row
64+ of conversation, where a row under-counted is a line of the draft with
65+ nowhere to go."
66+ []
67+ (let [cols (max 20 (quot (- @cells/window-width (* 22 8)) 8))
68+ wrapped (fn [line] (max 1 (long (Math/ceil (/ (count line) (double cols))))))]
69+ (min draft-max-rows
70+ (max 1 (reduce + (map wrapped (str/split-lines (or @cells/draft ""))))))))
71+
4372 ;; What the rows under the conversation need left to them: the jump button's
4473 ;; row, the separator, the compose bar and the air around it. The columns of
4574 ;; the row reserve it, and so nothing inside them has to — a `:scroll` that
@@ -75,9 +104,29 @@
75104 108)
76105 (def overview-lines 8)
77106
107+(defn- overview-list-height
108+ "How tall the strip's list of lines is, in points.
109+
110+ The number is both the reserve the backlog is laid out against and the
111+ height the terminal's scroll is given, and it has to be one number: a pane
112+ an inch taller than what was kept for it is a compose bar an inch off the
113+ bottom of the screen.
114+
115+ Counted from the lines there are, up to the ceiling — a room with two lines
116+ in it should not have a screenful reserved against it — and from the ceiling
117+ once there are more, which is the point at which the pane starts scrolling
118+ instead of growing.
119+
120+ A row of chrome a line, not the twenty points a window's line box is: a line
121+ here is one row of the terminal, and twenty points of a window's scale comes
122+ out as a little over half of one. Eight lines then asked for five rows, got
123+ five, and cut three lines off a strip that had just been given a scroll to
124+ show them in."
125+ []
126+ (* @chrome-row (min overview-lines (count (actions/recent-everywhere)))))
127+
78128 (defn- overview-height []
79- (* (chrome-scale)
80- (+ 24 (* 20 (min overview-lines (count (actions/recent-everywhere)))) 16)))
129+ (+ (overview-list-height) (* (chrome-scale) (+ 24 16))))
81130
82131 (defn- below-messages []
83132 ;; 115 is that, counted: the gap under the row of columns, the jump button's
@@ -94,18 +143,20 @@
94143 (+ 115
95144 (if @cells/replying-to 34 0)
96145 (if @cells/attachment 76 0)))
97- ;; The two extra rows the terminal's compose field wraps into, in points:
98- ;; a row down the page is two cells' worth of the scale.
99- (if @terminal? (* 4 (chrome-scale)) 0)
100- ;; And the lines a window's compose field has GROWN by. Unscaled and
101- ;; outside the terminal's arm on purpose: the field only reports its
102- ;; height where it can change — the terminal's is the fixed block of
103- ;; three rows reserved just above — so `draft-rows` is one there and
104- ;; this term is zero. Twenty points a line is a 16-point face's line
105- ;; box rounded up: the reserve has to be at least what the field took,
106- ;; because a point too few does not crop the list, it slides the
107- ;; compose bar off the bottom of the window.
108- (* 20 (dec @draft-rows))
146+ ;; The rows the compose field has GROWN by, and the row of air above it.
147+ ;;
148+ ;; Twenty points a line in a window: a 16-point face's line box rounded
149+ ;; up, and the reserve has to be at least what the field took, because a
150+ ;; point too few does not crop the list — it slides the compose bar off
151+ ;; the bottom of the window. `draft-rows` is what the field reported.
152+ ;;
153+ ;; A row of chrome a line in a terminal, counted here rather than
154+ ;; reported: nothing there fires `:on-rows`, so `terminal-draft-rows` is
155+ ;; asked the same question the field was given its height by. It used to
156+ ;; be a fixed three rows whatever was in it, two of them blank.
157+ (if @terminal?
158+ (* @chrome-row (terminal-draft-rows))
159+ (* 20 (dec @draft-rows)))
109160 ;; And the overview strip, when it is up. Reserved here rather than
110161 ;; anywhere else because this is the number the backlog is laid out
111162 ;; against: without it the strip is drawn past the bottom of the window
@@ -948,11 +999,12 @@
948999 horizontal split this is. The backlog above keeps its own scroll and its own
9491000 place in it, so reading down here does not move the conversation.
9501001
951- A terminal gets a handful of lines and no scroll. Its rows are cells rather
952- than points, and a second scrolling pane in a screen that is already a
953- conversation, a compose bar and a tab bar leaves neither half enough rows to
954- be worth reading — so there it stays the strip it was, and `below-messages`
955- reserves it by the row."
1002+ A terminal scrolls it too, but inside a fixed block of rows rather than a
1003+ half of the column: the screen is already a conversation, a compose bar and
1004+ a tab bar, and a second half-height pane would leave neither half enough
1005+ rows to read. So the strip is as tall as `overview-lines`, `below-messages`
1006+ reserves exactly that, and the lines past the eighth are a wheel or a page
1007+ away instead of being cut off with nothing to say they were there."
9561008 []
9571009 (let [lines (actions/recent-everywhere)
9581010 ;; The way back, and only while there is somewhere to go: the strip
@@ -998,10 +1050,23 @@
9981050 ms)
9991051 [[:dim-label {:label "Nothing has been said in any other room yet."}]]))]
10001052 (if @terminal?
1001- (into [:vbox {:key :overview :spacing 4 :margin-top 4}
1002- [:separator {}]
1003- [heading]]
1004- (rows (take overview-lines lines)))
1053+ [:vbox {:key :overview :spacing 4 :margin-top 4}
1054+ [:separator {}]
1055+ [heading]
1056+ ;; The same name as the window's, and for the same reason: the strip
1057+ ;; comes and goes with a keypress, and a reader who had paged down it
1058+ ;; should not be put back at the top for having looked away.
1059+ (into [:scroll {:scroll-key "overview-list" :orientation :vertical
1060+ :spacing 4
1061+ ;; The reserve, exactly, and as a ceiling as well as a
1062+ ;; floor — see `overview-list-height`. A height-request
1063+ ;; on its own is a minimum: the pane took the height of
1064+ ;; everything in it, drew every line, and paid for the
1065+ ;; surplus out of the conversation above rather than
1066+ ;; scrolling.
1067+ :height-request (overview-list-height)
1068+ :max-height (overview-list-height)}]
1069+ (rows lines))]
10051070 [:vbox {:key :overview :spacing 4 :margin-top 4 :fill-height true}
10061071 [:separator {}]
10071072 [heading]
@@ -1243,6 +1308,12 @@
12431308 ;; reply banner, the edit banner and the attachment share a wrapper now
12441309 ;; and cost one between them whether or not they have anything in them.
12451310 ;; This margin plus the window's own is what answers it underneath.
1311+ ;; Air above the bar as well as under it. A row rather than a margin
1312+ ;; because a terminal reads `:margin` and not `:margin-top`, and this is
1313+ ;; the backend that needs it: the banners above are usually empty and the
1314+ ;; strip or the last line of the conversation sat directly on the field,
1315+ ;; so a message being typed read as one more message in the room.
1316+ (when @terminal? [:spacer {:key :compose-gap :size @chrome-row}])
12461317 [:hbox {:spacing 8 :align :center :margin-bottom 12}
12471318 ;; narrow enough that Send keeps its place on a phone-width row
12481319 ;; A picture is pasted where everything else is typed: Ctrl+V. The field
@@ -1262,14 +1333,24 @@
12621333 (if (and (actions/desktop?) (not @terminal?))
12631334 [:image {:src "src/frq/icons/insert-image.png"
12641335 :size [36 36]
1336+ ;; On the middle of the field rather than the top of it: the
1337+ ;; box grows downwards as a message is typed, and a button
1338+ ;; pinned to its first row drifts away from the thing it acts
1339+ ;; on. Read by the terminal, where the row can be several
1340+ ;; cells tall; a window's backends ignore it.
1341+ :valign :center
12651342 ;; for a backend that sizes a picture by its bounds instead
12661343 :max-width 36
12671344 :max-height 36
12681345 :on-click actions/open-image-picker!}]
1269- [:button {:label "🖼" :on-click actions/open-image-picker!}])
1270- ;; In a terminal the row is the width of the screen and a message is
1271- ;; longer than 260 points of it: the field takes the surplus and wraps
1272- ;; into three rows rather than scrolling one line sideways.
1346+ [:button {:label "🖼" :valign :center :on-click actions/open-image-picker!}])
1347+ ;; In a terminal the row is the width of the screen, so the field takes
1348+ ;; the surplus rather than scrolling one line sideways — and it is as
1349+ ;; tall as what has been typed into it. Three rows were kept for it
1350+ ;; always, empty almost always, drawn as two ruled boxes under the one
1351+ ;; being typed in: rows spent on a paragraph nobody had written, taken
1352+ ;; off the conversation above. Now the box is a line until there is a
1353+ ;; second line to put in it.
12731354 [:entry {:text @cells/draft
12741355 :width-request 260
12751356 ;; Always, not only in a terminal. A window is the case that
@@ -1278,19 +1359,21 @@
12781359 ;; of the bar with the rest of it empty. The number stays as
12791360 ;; the minimum it always was.
12801361 :hexpand true
1281- :rows (if @terminal? 3 1)
1282- ;; In a window the field starts as one line and takes another
1283- ;; every time the message stops fitting, up to five — past
1284- ;; which it scrolls, keeping the caret in view. A paragraph
1285- ;; typed into a one-line box was readable a dozen characters
1286- ;; at a time, which is not how anybody writes one.
1287- :max-rows 5
1362+ :rows (if @terminal? (terminal-draft-rows) 1)
1363+ ;; The field starts as one line and takes another every time
1364+ ;; the message stops fitting, up to five — past which it
1365+ ;; scrolls, keeping the caret in view. A paragraph typed into a
1366+ ;; one-line box was readable a dozen characters at a time,
1367+ ;; which is not how anybody writes one.
1368+ ;;
1369+ ;; A window grows itself and says so through `:on-rows`; a
1370+ ;; terminal is given the height `terminal-draft-rows` counted,
1371+ ;; which is the same ceiling reached the other way round.
1372+ :max-rows draft-max-rows
12881373 :on-rows #(reset! draft-rows %)
1289- ;; The break is worth saying out loud where it is new: Enter
1290- ;; sends, as it always has, and the box under it takes a
1291- ;; paragraph now — which nobody would think to try unasked.
1292- :placeholder (if @terminal? "Message — Shift+Enter for a new line" "Message")
1374+ :placeholder "Message"
12931375 :on-change #(reset! cells/draft %)
12941376 :on-paste-empty actions/paste-image!
12951377 :on-activate actions/send-draft!}]
1296- [:button {:label "Send" :kind :primary :on-click actions/send-draft!}]]]))
1378+ [:button {:label "Send" :kind :primary :valign :center
1379+ :on-click actions/send-draft!}]]]))
@@ -40,6 +40,35 @@
40 40
41 (defonce ^:private draft-rows (atom 1))41 (defonce ^:private draft-rows (atom 1))
42 42
43+;; How tall the compose field is allowed to grow. The same ceiling in both
44+;; backends, for different reasons: a window past it scrolls with the caret in
45+;; view, and a terminal past it would be spending a quarter of the screen on
46+;; a message that has not been sent yet.
47+(def ^:private draft-max-rows 5)
48+
49+(defn- terminal-draft-rows
50+ "How many rows the terminal's compose field wants for what is in it.
51+
52+ The library sizes an entry by the `:rows` it was given and reports nothing
53+ back — there is no `:on-rows` to grow on, the way a window grows — so the
54+ wrapping is counted here instead, and the answer is both what the field is
55+ given and what `below-messages` keeps for it.
56+
57+ An empty field is one row, so the bar starts as a line rather than as a
58+ block of ruled nothing, and the text begins at the top of the rect and grows
59+ downwards from there.
60+
61+ The width is the row less what is beside the field — the picture button, the
62+ Send button, and the gaps around them, about twenty-two cells of eight points
63+ each. An estimate, and the cheap way to be wrong: a row over-counted is a row
64+ of conversation, where a row under-counted is a line of the draft with
65+ nowhere to go."
66+ []
67+ (let [cols (max 20 (quot (- @cells/window-width (* 22 8)) 8))
68+ wrapped (fn [line] (max 1 (long (Math/ceil (/ (count line) (double cols))))))]
69+ (min draft-max-rows
70+ (max 1 (reduce + (map wrapped (str/split-lines (or @cells/draft ""))))))))
71+
43 ;; What the rows under the conversation need left to them: the jump button's72 ;; What the rows under the conversation need left to them: the jump button's
44 ;; row, the separator, the compose bar and the air around it. The columns of73 ;; row, the separator, the compose bar and the air around it. The columns of
45 ;; the row reserve it, and so nothing inside them has to — a `:scroll` that74 ;; the row reserve it, and so nothing inside them has to — a `:scroll` that
@@ -75,9 +104,29 @@
75 108)104 108)
76 (def overview-lines 8)105 (def overview-lines 8)
77 106
107+(defn- overview-list-height
108+ "How tall the strip's list of lines is, in points.
109+
110+ The number is both the reserve the backlog is laid out against and the
111+ height the terminal's scroll is given, and it has to be one number: a pane
112+ an inch taller than what was kept for it is a compose bar an inch off the
113+ bottom of the screen.
114+
115+ Counted from the lines there are, up to the ceiling — a room with two lines
116+ in it should not have a screenful reserved against it — and from the ceiling
117+ once there are more, which is the point at which the pane starts scrolling
118+ instead of growing.
119+
120+ A row of chrome a line, not the twenty points a window's line box is: a line
121+ here is one row of the terminal, and twenty points of a window's scale comes
122+ out as a little over half of one. Eight lines then asked for five rows, got
123+ five, and cut three lines off a strip that had just been given a scroll to
124+ show them in."
125+ []
126+ (* @chrome-row (min overview-lines (count (actions/recent-everywhere)))))
127+
78 (defn- overview-height []128 (defn- overview-height []
79- (* (chrome-scale)129+ (+ (overview-list-height) (* (chrome-scale) (+ 24 16))))
80- (+ 24 (* 20 (min overview-lines (count (actions/recent-everywhere)))) 16)))
81 130
82 (defn- below-messages []131 (defn- below-messages []
83 ;; 115 is that, counted: the gap under the row of columns, the jump button's132 ;; 115 is that, counted: the gap under the row of columns, the jump button's
@@ -94,18 +143,20 @@
94 (+ 115143 (+ 115
95 (if @cells/replying-to 34 0)144 (if @cells/replying-to 34 0)
96 (if @cells/attachment 76 0)))145 (if @cells/attachment 76 0)))
97- ;; The two extra rows the terminal's compose field wraps into, in points:146+ ;; The rows the compose field has GROWN by, and the row of air above it.
98- ;; a row down the page is two cells' worth of the scale.147+ ;;
99- (if @terminal? (* 4 (chrome-scale)) 0)148+ ;; Twenty points a line in a window: a 16-point face's line box rounded
100- ;; And the lines a window's compose field has GROWN by. Unscaled and149+ ;; up, and the reserve has to be at least what the field took, because a
101- ;; outside the terminal's arm on purpose: the field only reports its150+ ;; point too few does not crop the list — it slides the compose bar off
102- ;; height where it can change — the terminal's is the fixed block of151+ ;; the bottom of the window. `draft-rows` is what the field reported.
103- ;; three rows reserved just above — so `draft-rows` is one there and152+ ;;
104- ;; this term is zero. Twenty points a line is a 16-point face's line153+ ;; A row of chrome a line in a terminal, counted here rather than
105- ;; box rounded up: the reserve has to be at least what the field took,154+ ;; reported: nothing there fires `:on-rows`, so `terminal-draft-rows` is
106- ;; because a point too few does not crop the list, it slides the155+ ;; asked the same question the field was given its height by. It used to
107- ;; compose bar off the bottom of the window.156+ ;; be a fixed three rows whatever was in it, two of them blank.
108- (* 20 (dec @draft-rows))157+ (if @terminal?
158+ (* @chrome-row (terminal-draft-rows))
159+ (* 20 (dec @draft-rows)))
109 ;; And the overview strip, when it is up. Reserved here rather than160 ;; And the overview strip, when it is up. Reserved here rather than
110 ;; anywhere else because this is the number the backlog is laid out161 ;; anywhere else because this is the number the backlog is laid out
111 ;; against: without it the strip is drawn past the bottom of the window162 ;; against: without it the strip is drawn past the bottom of the window
@@ -948,11 +999,12 @@
948 horizontal split this is. The backlog above keeps its own scroll and its own999 horizontal split this is. The backlog above keeps its own scroll and its own
949 place in it, so reading down here does not move the conversation.1000 place in it, so reading down here does not move the conversation.
950 1001
951- A terminal gets a handful of lines and no scroll. Its rows are cells rather1002+ A terminal scrolls it too, but inside a fixed block of rows rather than a
952- than points, and a second scrolling pane in a screen that is already a1003+ half of the column: the screen is already a conversation, a compose bar and
953- conversation, a compose bar and a tab bar leaves neither half enough rows to1004+ a tab bar, and a second half-height pane would leave neither half enough
954- be worth reading — so there it stays the strip it was, and `below-messages`1005+ rows to read. So the strip is as tall as `overview-lines`, `below-messages`
955- reserves it by the row."1006+ reserves exactly that, and the lines past the eighth are a wheel or a page
1007+ away instead of being cut off with nothing to say they were there."
956 []1008 []
957 (let [lines (actions/recent-everywhere)1009 (let [lines (actions/recent-everywhere)
958 ;; The way back, and only while there is somewhere to go: the strip1010 ;; The way back, and only while there is somewhere to go: the strip
@@ -998,10 +1050,23 @@
998 ms)1050 ms)
999 [[:dim-label {:label "Nothing has been said in any other room yet."}]]))]1051 [[:dim-label {:label "Nothing has been said in any other room yet."}]]))]
1000 (if @terminal?1052 (if @terminal?
1001- (into [:vbox {:key :overview :spacing 4 :margin-top 4}1053+ [:vbox {:key :overview :spacing 4 :margin-top 4}
1002- [:separator {}]1054+ [:separator {}]
1003- [heading]]1055+ [heading]
1004- (rows (take overview-lines lines)))1056+ ;; The same name as the window's, and for the same reason: the strip
1057+ ;; comes and goes with a keypress, and a reader who had paged down it
1058+ ;; should not be put back at the top for having looked away.
1059+ (into [:scroll {:scroll-key "overview-list" :orientation :vertical
1060+ :spacing 4
1061+ ;; The reserve, exactly, and as a ceiling as well as a
1062+ ;; floor — see `overview-list-height`. A height-request
1063+ ;; on its own is a minimum: the pane took the height of
1064+ ;; everything in it, drew every line, and paid for the
1065+ ;; surplus out of the conversation above rather than
1066+ ;; scrolling.
1067+ :height-request (overview-list-height)
1068+ :max-height (overview-list-height)}]
1069+ (rows lines))]
1005 [:vbox {:key :overview :spacing 4 :margin-top 4 :fill-height true}1070 [:vbox {:key :overview :spacing 4 :margin-top 4 :fill-height true}
1006 [:separator {}]1071 [:separator {}]
1007 [heading]1072 [heading]
@@ -1243,6 +1308,12 @@
1243 ;; reply banner, the edit banner and the attachment share a wrapper now1308 ;; reply banner, the edit banner and the attachment share a wrapper now
1244 ;; and cost one between them whether or not they have anything in them.1309 ;; and cost one between them whether or not they have anything in them.
1245 ;; This margin plus the window's own is what answers it underneath.1310 ;; This margin plus the window's own is what answers it underneath.
1311+ ;; Air above the bar as well as under it. A row rather than a margin
1312+ ;; because a terminal reads `:margin` and not `:margin-top`, and this is
1313+ ;; the backend that needs it: the banners above are usually empty and the
1314+ ;; strip or the last line of the conversation sat directly on the field,
1315+ ;; so a message being typed read as one more message in the room.
1316+ (when @terminal? [:spacer {:key :compose-gap :size @chrome-row}])
1246 [:hbox {:spacing 8 :align :center :margin-bottom 12}1317 [:hbox {:spacing 8 :align :center :margin-bottom 12}
1247 ;; narrow enough that Send keeps its place on a phone-width row1318 ;; narrow enough that Send keeps its place on a phone-width row
1248 ;; A picture is pasted where everything else is typed: Ctrl+V. The field1319 ;; A picture is pasted where everything else is typed: Ctrl+V. The field
@@ -1262,14 +1333,24 @@
1262 (if (and (actions/desktop?) (not @terminal?))1333 (if (and (actions/desktop?) (not @terminal?))
1263 [:image {:src "src/frq/icons/insert-image.png"1334 [:image {:src "src/frq/icons/insert-image.png"
1264 :size [36 36]1335 :size [36 36]
1336+ ;; On the middle of the field rather than the top of it: the
1337+ ;; box grows downwards as a message is typed, and a button
1338+ ;; pinned to its first row drifts away from the thing it acts
1339+ ;; on. Read by the terminal, where the row can be several
1340+ ;; cells tall; a window's backends ignore it.
1341+ :valign :center
1265 ;; for a backend that sizes a picture by its bounds instead1342 ;; for a backend that sizes a picture by its bounds instead
1266 :max-width 361343 :max-width 36
1267 :max-height 361344 :max-height 36
1268 :on-click actions/open-image-picker!}]1345 :on-click actions/open-image-picker!}]
1269- [:button {:label "🖼" :on-click actions/open-image-picker!}])1346+ [:button {:label "🖼" :valign :center :on-click actions/open-image-picker!}])
1270- ;; In a terminal the row is the width of the screen and a message is1347+ ;; In a terminal the row is the width of the screen, so the field takes
1271- ;; longer than 260 points of it: the field takes the surplus and wraps1348+ ;; the surplus rather than scrolling one line sideways — and it is as
1272- ;; into three rows rather than scrolling one line sideways.1349+ ;; tall as what has been typed into it. Three rows were kept for it
1350+ ;; always, empty almost always, drawn as two ruled boxes under the one
1351+ ;; being typed in: rows spent on a paragraph nobody had written, taken
1352+ ;; off the conversation above. Now the box is a line until there is a
1353+ ;; second line to put in it.
1273 [:entry {:text @cells/draft1354 [:entry {:text @cells/draft
1274 :width-request 2601355 :width-request 260
1275 ;; Always, not only in a terminal. A window is the case that1356 ;; Always, not only in a terminal. A window is the case that
@@ -1278,19 +1359,21 @@
1278 ;; of the bar with the rest of it empty. The number stays as1359 ;; of the bar with the rest of it empty. The number stays as
1279 ;; the minimum it always was.1360 ;; the minimum it always was.
1280 :hexpand true1361 :hexpand true
1281- :rows (if @terminal? 3 1)1362+ :rows (if @terminal? (terminal-draft-rows) 1)
1282- ;; In a window the field starts as one line and takes another1363+ ;; The field starts as one line and takes another every time
1283- ;; every time the message stops fitting, up to five — past1364+ ;; the message stops fitting, up to five — past which it
1284- ;; which it scrolls, keeping the caret in view. A paragraph1365+ ;; scrolls, keeping the caret in view. A paragraph typed into a
1285- ;; typed into a one-line box was readable a dozen characters1366+ ;; one-line box was readable a dozen characters at a time,
1286- ;; at a time, which is not how anybody writes one.1367+ ;; which is not how anybody writes one.
1287- :max-rows 51368+ ;;
1369+ ;; A window grows itself and says so through `:on-rows`; a
1370+ ;; terminal is given the height `terminal-draft-rows` counted,
1371+ ;; which is the same ceiling reached the other way round.
1372+ :max-rows draft-max-rows
1288 :on-rows #(reset! draft-rows %)1373 :on-rows #(reset! draft-rows %)
1289- ;; The break is worth saying out loud where it is new: Enter1374+ :placeholder "Message"
1290- ;; sends, as it always has, and the box under it takes a
1291- ;; paragraph now — which nobody would think to try unasked.
1292- :placeholder (if @terminal? "Message — Shift+Enter for a new line" "Message")
1293 :on-change #(reset! cells/draft %)1375 :on-change #(reset! cells/draft %)
1294 :on-paste-empty actions/paste-image!1376 :on-paste-empty actions/paste-image!
1295 :on-activate actions/send-draft!}]1377 :on-activate actions/send-draft!}]
1296- [:button {:label "Send" :kind :primary :on-click actions/send-draft!}]]]))1378+ [:button {:label "Send" :kind :primary :valign :center
1379+ :on-click actions/send-draft!}]]]))