nandi/frqpublic Fork 0
61622f7
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.

Hold one copy of a message, and the words it ends with

A channel is replayed twice over — once on JOIN, once for the
CHATHISTORY we ask for — and in the second form an edited message is
two rows, the older of them still holding what it used to say. Landing
both put the pre-edit words under the line already showing the current
ones, and left them there whenever the revision fell outside the window
we asked for.

The msgid is the message, across every revision, so it is what a second
copy is recognised by. The copy in hand stays, unless the one arriving
is the server saying this message has been edited — then its words win,
which is the whole point of asking.
nandi committed 2026-08-31T20:45:32-07:00 Browse files
61622f7 parent: b52a754
modified src/frq/state.jolt +30 -3
@@ -198,8 +198,34 @@
198198 (swap! channels
199199 (fn [m]
200200 (let [m (ensure-channel m channel)
201- viewing? (and (chat-visible?) (= channel @current))]
202- (-> m
201+ viewing? (and (chat-visible?) (= channel @current))
202+ ;; The server hands the same message over more than once: a
203+ ;; JOIN replays the backlog, the CHATHISTORY we ask for
204+ ;; replays it again, and a line can have arrived live before
205+ ;; either. The msgid is the message's identity and it
206+ ;; survives every revision, so holding the copy we have is
207+ ;; what keeps a rejoin from doubling the buffer and what
208+ ;; keeps a replayed *pre-edit* row from landing under a line
209+ ;; already showing the current text.
210+ seen? (and id (some #(= id (:id %))
211+ (get-in m [channel :messages])))]
212+ (cond
213+ ;; The copy we already hold is the pre-edit one, and this is
214+ ;; the server's collapsed row saying so. Same message, later
215+ ;; word: take the text rather than the arrival order.
216+ (and seen? edited?)
217+ (assoc-in m [channel :messages]
218+ (mapv (fn [msg]
219+ (if (= id (:id msg))
220+ (assoc msg :text text :edited? true
221+ :images (media/image-urls text))
222+ msg))
223+ (get-in m [channel :messages])))
224+
225+ seen? m
226+
227+ :else
228+ (-> m
203229 (update-in [channel :messages] conj
204230 {:from from :text text :system? (= "*" from)
205231 :actor who
@@ -215,7 +241,8 @@
215241 :edited? (boolean edited?)
216242 ;; emoji -> the nicks who put it there
217243 :reactions (or reactions {})})
218- (update-in [channel :unread] (if viewing? (constantly 0) inc)))))))))
244+ (update-in [channel :unread]
245+ (if viewing? (constantly 0) inc))))))))))
219246
220247 (defn open-channel!
221248 "Show a buffer. A channel we are not in is joined on the way — a row can
@@ -198,8 +198,34 @@
198 (swap! channels198 (swap! channels
199 (fn [m]199 (fn [m]
200 (let [m (ensure-channel m channel)200 (let [m (ensure-channel m channel)
201- viewing? (and (chat-visible?) (= channel @current))]201+ viewing? (and (chat-visible?) (= channel @current))
202- (-> m202+ ;; The server hands the same message over more than once: a
203+ ;; JOIN replays the backlog, the CHATHISTORY we ask for
204+ ;; replays it again, and a line can have arrived live before
205+ ;; either. The msgid is the message's identity and it
206+ ;; survives every revision, so holding the copy we have is
207+ ;; what keeps a rejoin from doubling the buffer and what
208+ ;; keeps a replayed *pre-edit* row from landing under a line
209+ ;; already showing the current text.
210+ seen? (and id (some #(= id (:id %))
211+ (get-in m [channel :messages])))]
212+ (cond
213+ ;; The copy we already hold is the pre-edit one, and this is
214+ ;; the server's collapsed row saying so. Same message, later
215+ ;; word: take the text rather than the arrival order.
216+ (and seen? edited?)
217+ (assoc-in m [channel :messages]
218+ (mapv (fn [msg]
219+ (if (= id (:id msg))
220+ (assoc msg :text text :edited? true
221+ :images (media/image-urls text))
222+ msg))
223+ (get-in m [channel :messages])))
224+
225+ seen? m
226+
227+ :else
228+ (-> m
203 (update-in [channel :messages] conj229 (update-in [channel :messages] conj
204 {:from from :text text :system? (= "*" from)230 {:from from :text text :system? (= "*" from)
205 :actor who231 :actor who
@@ -215,7 +241,8 @@
215 :edited? (boolean edited?)241 :edited? (boolean edited?)
216 ;; emoji -> the nicks who put it there242 ;; emoji -> the nicks who put it there
217 :reactions (or reactions {})})243 :reactions (or reactions {})})
218- (update-in [channel :unread] (if viewing? (constantly 0) inc)))))))))244+ (update-in [channel :unread]
245+ (if viewing? (constantly 0) inc))))))))))
219 246
220 (defn open-channel!247 (defn open-channel!
221 "Show a buffer. A channel we are not in is joined on the way — a row can248 "Show a buffer. A channel we are not in is joined on the way — a row can