Share Discover and Settings, and the frame around them
The small two, and the cheapest of the ports: three definitions and 69 lines, one new cell, one constant and one action, and the renderer needed nothing at all — `frq.screens.settings` compiled for ClojureDart first time and drew correctly on the first run. That is what the last three screens were for. `tab-screen` comes with them because it is what puts a tab bar under a screen, and all three of them are one. Discover is worth looking at on the phone: it offers Open for a room you are already in and Join for the rest, which is the shared screen reading `frq.cells/channels` — the same logic, from the same file, over state the phone filled in itself. Two things the move exposed, both in text nobody had read in a while. The about line said the components were painted on the Vidya/egui backend, which has been two backends ago for some time and was never true on a phone; it is a reader conditional now, like the TLS note, because what paints them is the one thing that genuinely differs. And Quit is gone where there is nothing to quit: closing an app is a window's idea and Android has its own way out, so it asks `actions/desktop?` first. frq.app is 565 lines. It was 1,744 this morning. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
49fb82f parent: c0121fe modified
common/frq/actions.cljc +1 -1 | @@ -138,4 +138,4 @@ | ||
| 138 | 138 | (defn profile-hover! [& args] (call :profile-hover! args)) |
| 139 | 139 | (defn profile-unhover! [& args] (call :profile-unhover! args)) |
| 140 | 140 | (defn profile-open! [& args] (call :profile-open! args)) |
| 141 | - | |
| 141 | +(defn toggle-hide-join-part! [] (call :toggle-hide-join-part! [])) | |
| @@ -138,4 +138,4 @@ | |||
| 138 | (defn profile-hover! [& args] (call :profile-hover! args)) | 138 | (defn profile-hover! [& args] (call :profile-hover! args)) |
| 139 | (defn profile-unhover! [& args] (call :profile-unhover! args)) | 139 | (defn profile-unhover! [& args] (call :profile-unhover! args)) |
| 140 | (defn profile-open! [& args] (call :profile-open! args)) | 140 | (defn profile-open! [& args] (call :profile-open! args)) |
| 141 | - | 141 | +(defn toggle-hide-join-part! [] (call :toggle-hide-join-part! [])) |
modified
common/frq/cells.cljc +17 -0 | @@ -191,3 +191,20 @@ | ||
| 191 | 191 | ;; is a pill under many messages, and only the one under the pointer carries a |
| 192 | 192 | ;; card. |
| 193 | 193 | (defonce reaction-hover (atom nil)) |
| 194 | + | |
| 195 | +;; Comings and goings, hidden or not. A quiet room reads better with them — | |
| 196 | +;; they are how you notice someone arriving — and a busy one drowns in them, | |
| 197 | +;; so it is the reader's call. Only other people's: your own "Joined #chan" is | |
| 198 | +;; the answer to something you just did. | |
| 199 | +(defonce hide-join-part? (atom false)) | |
| 200 | + | |
| 201 | +(def popular-channels | |
| 202 | + [["#general" "General discussion"] | |
| 203 | + ["#test" "Test channel"] | |
| 204 | + ["#freeq" "freeq development & support"] | |
| 205 | + ["#dev" "Programming & technology"] | |
| 206 | + ["#music" "Music recommendations"] | |
| 207 | + ["#random" "Off-topic chat"]]) | |
| 208 | + | |
| 209 | + | |
| 210 | +;; joined as soon as the server sends 001 | |
| @@ -191,3 +191,20 @@ | |||
| 191 | ;; is a pill under many messages, and only the one under the pointer carries a | 191 | ;; is a pill under many messages, and only the one under the pointer carries a |
| 192 | ;; card. | 192 | ;; card. |
| 193 | (defonce reaction-hover (atom nil)) | 193 | (defonce reaction-hover (atom nil)) |
| 194 | + | ||
| 195 | +;; Comings and goings, hidden or not. A quiet room reads better with them — | ||
| 196 | +;; they are how you notice someone arriving — and a busy one drowns in them, | ||
| 197 | +;; so it is the reader's call. Only other people's: your own "Joined #chan" is | ||
| 198 | +;; the answer to something you just did. | ||
| 199 | +(defonce hide-join-part? (atom false)) | ||
| 200 | + | ||
| 201 | +(def popular-channels | ||
| 202 | + [["#general" "General discussion"] | ||
| 203 | + ["#test" "Test channel"] | ||
| 204 | + ["#freeq" "freeq development & support"] | ||
| 205 | + ["#dev" "Programming & technology"] | ||
| 206 | + ["#music" "Music recommendations"] | ||
| 207 | + ["#random" "Off-topic chat"]]) | ||
| 208 | + | ||
| 209 | + | ||
| 210 | +;; joined as soon as the server sends 001 | ||
added
common/frq/screens/settings.cljc +88 -0 | new file mode 100644 | ||
| @@ -0,0 +1,88 @@ | ||
| 1 | +(ns frq.screens.settings | |
| 2 | + "Discover and Settings, and the frame the tab bar sits in. | |
| 3 | + | |
| 4 | + The small two, and the last of frq.app's screens to move but the least | |
| 5 | + interesting: a list of rooms to join and a page of switches. `tab-screen` | |
| 6 | + comes with them because it is what puts a tab bar under a screen, and all | |
| 7 | + three of them are one." | |
| 8 | + (:require [clojure.string :as str] | |
| 9 | + [frq.actions :as actions] | |
| 10 | + [frq.cells :as cells] | |
| 11 | + [frq.screens.chats :refer [below-list tab-bar]] | |
| 12 | + [frq.screens.connect :refer [error-note]])) | |
| 13 | + | |
| 14 | +(defn- tab-screen | |
| 15 | + "One of the three screens the tab bar moves between, in the chats screen's | |
| 16 | + shape: the title at the top, the tabs pinned at the bottom, and `body` | |
| 17 | + scrolling between them. | |
| 18 | + | |
| 19 | + The same shape for all three, so switching tabs moves nothing but the | |
| 20 | + middle. As pages they were centred columns of their own widths with the tabs | |
| 21 | + wherever the content happened to end, and every switch resized the screen | |
| 22 | + under the pointer." | |
| 23 | + [title scroll-key & body] | |
| 24 | + [:vbox {:spacing 8 :margin 12 :fill-height true} | |
| 25 | + [:title {:label title}] | |
| 26 | + [:vbox {:key :list :fill-height true} | |
| 27 | + (into [:scroll {:scroll-key scroll-key :orientation :vertical | |
| 28 | + :reserve (below-list) :spacing 8}] | |
| 29 | + body)] | |
| 30 | + [:vbox {:key :foot :spacing 8} | |
| 31 | + [:separator {}] | |
| 32 | + [tab-bar]]]) | |
| 33 | + | |
| 34 | +(defn discover-screen [] | |
| 35 | + (tab-screen "Discover" "discover-list" | |
| 36 | + [:dim-label {:label "Popular channels on freeq."}] | |
| 37 | + [error-note] | |
| 38 | + (for [[name blurb] cells/popular-channels] | |
| 39 | + (let [joined? (get-in @cells/channels [name :joined?])] | |
| 40 | + [:card {:key name} | |
| 41 | + [:title-2 {:label name}] | |
| 42 | + [:dim-label {:label blurb}] | |
| 43 | + [:button {:label (if joined? "Open" "Join") | |
| 44 | + :kind :primary | |
| 45 | + :on-click #(if joined? (actions/open-channel! name) (actions/join! name))}]])))) | |
| 46 | + | |
| 47 | +(defn settings-screen [] | |
| 48 | + (tab-screen "Settings" "settings-list" | |
| 49 | + [:card {} | |
| 50 | + [:title-2 {:label "Connection"}] | |
| 51 | + [:status {:label @cells/status :live (actions/connected?)}] | |
| 52 | + [:label {:label (str "Server: " @cells/form-host ":" @cells/form-port)}] | |
| 53 | + [:label {:label (str "Nick: " @cells/form-nick)}] | |
| 54 | + (if-let [sess @cells/session] | |
| 55 | + [:vbox {:spacing 2} | |
| 56 | + [:label {:label (str "Signed in as " (:handle sess))}] | |
| 57 | + [:dim-label {:label (or (:did sess) "")}] | |
| 58 | + [:vbox {:key :forget} | |
| 59 | + (when @cells/broker-token | |
| 60 | + [:button {:label "Forget Bluesky session" | |
| 61 | + :kind :destructive | |
| 62 | + :on-click actions/forget-session!}])]] | |
| 63 | + [:dim-label {:label "Guest — not signed in."}]) | |
| 64 | + [:separator {}] | |
| 65 | + ;; Nothing to disconnect from when there is no connection — the way back to | |
| 66 | + ;; the connect screen is what is wanted then. | |
| 67 | + [:vbox {:key :connection-action} | |
| 68 | + (if (actions/connected?) | |
| 69 | + [:button {:label "Disconnect" :kind :destructive :on-click actions/disconnect!}] | |
| 70 | + [:button {:label "Back to connect" | |
| 71 | + :on-click #(reset! cells/screen :connect)}])]] | |
| 72 | + [:card {} | |
| 73 | + [:title-2 {:label "Messages"}] | |
| 74 | + [:checkbutton {:label "Hide join/part messages" | |
| 75 | + :active @cells/hide-join-part? | |
| 76 | + :on-toggled actions/toggle-hide-join-part!}] | |
| 77 | + [:dim-label {:label "Hides other people arriving, leaving and quitting. The people panel still follows who is here."}]] | |
| 78 | + [:card {} | |
| 79 | + [:title-2 {:label "frq"}] | |
| 80 | + ;; What this is, which is not the same sentence on both: the components | |
| 81 | + ;; are the same file either way, and what paints them is not. Vidya and | |
| 82 | + ;; egui were what it said, and both have been gone a while. | |
| 83 | + [:dim-label {:label #?(:cljd "freeq client — the same glimmer components as the desktop, compiled by ClojureDart and painted by Flutter." | |
| 84 | + :jolt "freeq client in jolt — glimmer components, painted by libcosmic.")}] | |
| 85 | + ;; No Quit where there is nothing to quit: closing an app is a window's | |
| 86 | + ;; idea, and Android has its own way of leaving one. | |
| 87 | + (when (actions/desktop?) | |
| 88 | + [:button {:label "Quit" :on-click actions/quit!}])])) | |
| new file mode 100644 | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | +(ns frq.screens.settings | ||
| 2 | + "Discover and Settings, and the frame the tab bar sits in. | ||
| 3 | + | ||
| 4 | + The small two, and the last of frq.app's screens to move but the least | ||
| 5 | + interesting: a list of rooms to join and a page of switches. `tab-screen` | ||
| 6 | + comes with them because it is what puts a tab bar under a screen, and all | ||
| 7 | + three of them are one." | ||
| 8 | + (:require [clojure.string :as str] | ||
| 9 | + [frq.actions :as actions] | ||
| 10 | + [frq.cells :as cells] | ||
| 11 | + [frq.screens.chats :refer [below-list tab-bar]] | ||
| 12 | + [frq.screens.connect :refer [error-note]])) | ||
| 13 | + | ||
| 14 | +(defn- tab-screen | ||
| 15 | + "One of the three screens the tab bar moves between, in the chats screen's | ||
| 16 | + shape: the title at the top, the tabs pinned at the bottom, and `body` | ||
| 17 | + scrolling between them. | ||
| 18 | + | ||
| 19 | + The same shape for all three, so switching tabs moves nothing but the | ||
| 20 | + middle. As pages they were centred columns of their own widths with the tabs | ||
| 21 | + wherever the content happened to end, and every switch resized the screen | ||
| 22 | + under the pointer." | ||
| 23 | + [title scroll-key & body] | ||
| 24 | + [:vbox {:spacing 8 :margin 12 :fill-height true} | ||
| 25 | + [:title {:label title}] | ||
| 26 | + [:vbox {:key :list :fill-height true} | ||
| 27 | + (into [:scroll {:scroll-key scroll-key :orientation :vertical | ||
| 28 | + :reserve (below-list) :spacing 8}] | ||
| 29 | + body)] | ||
| 30 | + [:vbox {:key :foot :spacing 8} | ||
| 31 | + [:separator {}] | ||
| 32 | + [tab-bar]]]) | ||
| 33 | + | ||
| 34 | +(defn discover-screen [] | ||
| 35 | + (tab-screen "Discover" "discover-list" | ||
| 36 | + [:dim-label {:label "Popular channels on freeq."}] | ||
| 37 | + [error-note] | ||
| 38 | + (for [[name blurb] cells/popular-channels] | ||
| 39 | + (let [joined? (get-in @cells/channels [name :joined?])] | ||
| 40 | + [:card {:key name} | ||
| 41 | + [:title-2 {:label name}] | ||
| 42 | + [:dim-label {:label blurb}] | ||
| 43 | + [:button {:label (if joined? "Open" "Join") | ||
| 44 | + :kind :primary | ||
| 45 | + :on-click #(if joined? (actions/open-channel! name) (actions/join! name))}]])))) | ||
| 46 | + | ||
| 47 | +(defn settings-screen [] | ||
| 48 | + (tab-screen "Settings" "settings-list" | ||
| 49 | + [:card {} | ||
| 50 | + [:title-2 {:label "Connection"}] | ||
| 51 | + [:status {:label @cells/status :live (actions/connected?)}] | ||
| 52 | + [:label {:label (str "Server: " @cells/form-host ":" @cells/form-port)}] | ||
| 53 | + [:label {:label (str "Nick: " @cells/form-nick)}] | ||
| 54 | + (if-let [sess @cells/session] | ||
| 55 | + [:vbox {:spacing 2} | ||
| 56 | + [:label {:label (str "Signed in as " (:handle sess))}] | ||
| 57 | + [:dim-label {:label (or (:did sess) "")}] | ||
| 58 | + [:vbox {:key :forget} | ||
| 59 | + (when @cells/broker-token | ||
| 60 | + [:button {:label "Forget Bluesky session" | ||
| 61 | + :kind :destructive | ||
| 62 | + :on-click actions/forget-session!}])]] | ||
| 63 | + [:dim-label {:label "Guest — not signed in."}]) | ||
| 64 | + [:separator {}] | ||
| 65 | + ;; Nothing to disconnect from when there is no connection — the way back to | ||
| 66 | + ;; the connect screen is what is wanted then. | ||
| 67 | + [:vbox {:key :connection-action} | ||
| 68 | + (if (actions/connected?) | ||
| 69 | + [:button {:label "Disconnect" :kind :destructive :on-click actions/disconnect!}] | ||
| 70 | + [:button {:label "Back to connect" | ||
| 71 | + :on-click #(reset! cells/screen :connect)}])]] | ||
| 72 | + [:card {} | ||
| 73 | + [:title-2 {:label "Messages"}] | ||
| 74 | + [:checkbutton {:label "Hide join/part messages" | ||
| 75 | + :active @cells/hide-join-part? | ||
| 76 | + :on-toggled actions/toggle-hide-join-part!}] | ||
| 77 | + [:dim-label {:label "Hides other people arriving, leaving and quitting. The people panel still follows who is here."}]] | ||
| 78 | + [:card {} | ||
| 79 | + [:title-2 {:label "frq"}] | ||
| 80 | + ;; What this is, which is not the same sentence on both: the components | ||
| 81 | + ;; are the same file either way, and what paints them is not. Vidya and | ||
| 82 | + ;; egui were what it said, and both have been gone a while. | ||
| 83 | + [:dim-label {:label #?(:cljd "freeq client — the same glimmer components as the desktop, compiled by ClojureDart and painted by Flutter." | ||
| 84 | + :jolt "freeq client in jolt — glimmer components, painted by libcosmic.")}] | ||
| 85 | + ;; No Quit where there is nothing to quit: closing an app is a window's | ||
| 86 | + ;; idea, and Android has its own way of leaving one. | ||
| 87 | + (when (actions/desktop?) | ||
| 88 | + [:button {:label "Quit" :on-click actions/quit!}])])) | ||
modified
flutter/README.md +5 -4 | @@ -135,12 +135,13 @@ screen rather than the subtree that read it. Fine at this size. | ||
| 135 | 135 | reads is `frq.cells` and what it calls is `frq.actions`, and each platform |
| 136 | 136 | fills those in: `frq.state`'s reducers on the desktop, dart:io here. |
| 137 | 137 | |
| 138 | -## Three screens shared, all drawn on both | |
| 138 | +## Five screens shared, all drawn on both | |
| 139 | 139 | |
| 140 | -`frq.screens.connect`, `frq.screens.chats` and `frq.screens.chat` are in | |
| 141 | -`common/`, with the cells under them in `frq.cells`, the derivations in | |
| 140 | +`frq.screens.connect`, `frq.screens.chats`, `frq.screens.chat` and | |
| 141 | +`frq.screens.settings` — the last carrying Discover, Settings and the frame the | |
| 142 | +tab bar sits in — are in `common/`, with the cells under them in `frq.cells`, the derivations in | |
| 142 | 143 | `frq.rooms`, the backend metrics in `frq.metrics` and everything a screen |
| 143 | -cannot do itself behind `frq.actions`. `frq.app` is 621 lines and was 1,744. | |
| 144 | +cannot do itself behind `frq.actions`. `frq.app` is 565 lines and was 1,744. | |
| 144 | 145 | |
| 145 | 146 | What `Length::Fill` means took four goes to get right, and the rule it ended |
| 146 | 147 | at is worth stating once: a child that fills is Flutter's `Expanded`, the |
| @@ -135,12 +135,13 @@ screen rather than the subtree that read it. Fine at this size. | |||
| 135 | reads is `frq.cells` and what it calls is `frq.actions`, and each platform | 135 | reads is `frq.cells` and what it calls is `frq.actions`, and each platform |
| 136 | fills those in: `frq.state`'s reducers on the desktop, dart:io here. | 136 | fills those in: `frq.state`'s reducers on the desktop, dart:io here. |
| 137 | 137 | ||
| 138 | -## Three screens shared, all drawn on both | 138 | +## Five screens shared, all drawn on both |
| 139 | 139 | ||
| 140 | -`frq.screens.connect`, `frq.screens.chats` and `frq.screens.chat` are in | 140 | +`frq.screens.connect`, `frq.screens.chats`, `frq.screens.chat` and |
| 141 | -`common/`, with the cells under them in `frq.cells`, the derivations in | 141 | +`frq.screens.settings` — the last carrying Discover, Settings and the frame the |
| 142 | +tab bar sits in — are in `common/`, with the cells under them in `frq.cells`, the derivations in | ||
| 142 | `frq.rooms`, the backend metrics in `frq.metrics` and everything a screen | 143 | `frq.rooms`, the backend metrics in `frq.metrics` and everything a screen |
| 143 | -cannot do itself behind `frq.actions`. `frq.app` is 621 lines and was 1,744. | 144 | +cannot do itself behind `frq.actions`. `frq.app` is 565 lines and was 1,744. |
| 144 | 145 | ||
| 145 | What `Length::Fill` means took four goes to get right, and the rule it ended | 146 | What `Length::Fill` means took four goes to get right, and the rule it ended |
| 146 | at is worth stating once: a child that fills is Flutter's `Expanded`, the | 147 | at is worth stating once: a child that fills is Flutter's `Expanded`, the |
modified
flutter/src/frq/main.cljd +8 -0 | @@ -32,6 +32,7 @@ | ||
| 32 | 32 | [frq.screens.connect :as connect] |
| 33 | 33 | [frq.screens.chats :as chats] |
| 34 | 34 | [frq.screens.chat :as chat] |
| 35 | + [frq.screens.settings :as settings] | |
| 35 | 36 | [frq.rooms :as rooms] |
| 36 | 37 | [frq.irc.parse :as irc])) |
| 37 | 38 | |
| @@ -275,6 +276,11 @@ | ||
| 275 | 276 | :toggle-users! (fn [] (swap! cells/show-users? not)) |
| 276 | 277 | :toggle-overview! (fn [] (swap! cells/overview? not)) |
| 277 | 278 | :toggle-chat-list! (fn [] (swap! cells/hide-chat-list? not)) |
| 279 | + :toggle-hide-join-part! (fn [] (swap! cells/hide-join-part? not)) | |
| 280 | + :quit! (fn [] nil) | |
| 281 | + :forget-session! (fn [] | |
| 282 | + (reset! cells/broker-token nil) | |
| 283 | + (reset! cells/session nil)) | |
| 278 | 284 | :jump-to-present! (fn [] (reset! cells/at-present? true)) |
| 279 | 285 | :open-channel! (fn [name] |
| 280 | 286 | (reset! cells/current name) |
| @@ -329,4 +335,6 @@ | ||
| 329 | 335 | :connect [connect/connect-screen] |
| 330 | 336 | :chats [chats/chats-screen] |
| 331 | 337 | :chat [chat/chat-screen] |
| 338 | + :discover [settings/discover-screen] | |
| 339 | + :settings [settings/settings-screen] | |
| 332 | 340 | [connected-screen])))))) |
| @@ -32,6 +32,7 @@ | |||
| 32 | [frq.screens.connect :as connect] | 32 | [frq.screens.connect :as connect] |
| 33 | [frq.screens.chats :as chats] | 33 | [frq.screens.chats :as chats] |
| 34 | [frq.screens.chat :as chat] | 34 | [frq.screens.chat :as chat] |
| 35 | + [frq.screens.settings :as settings] | ||
| 35 | [frq.rooms :as rooms] | 36 | [frq.rooms :as rooms] |
| 36 | [frq.irc.parse :as irc])) | 37 | [frq.irc.parse :as irc])) |
| 37 | 38 | ||
| @@ -275,6 +276,11 @@ | |||
| 275 | :toggle-users! (fn [] (swap! cells/show-users? not)) | 276 | :toggle-users! (fn [] (swap! cells/show-users? not)) |
| 276 | :toggle-overview! (fn [] (swap! cells/overview? not)) | 277 | :toggle-overview! (fn [] (swap! cells/overview? not)) |
| 277 | :toggle-chat-list! (fn [] (swap! cells/hide-chat-list? not)) | 278 | :toggle-chat-list! (fn [] (swap! cells/hide-chat-list? not)) |
| 279 | + :toggle-hide-join-part! (fn [] (swap! cells/hide-join-part? not)) | ||
| 280 | + :quit! (fn [] nil) | ||
| 281 | + :forget-session! (fn [] | ||
| 282 | + (reset! cells/broker-token nil) | ||
| 283 | + (reset! cells/session nil)) | ||
| 278 | :jump-to-present! (fn [] (reset! cells/at-present? true)) | 284 | :jump-to-present! (fn [] (reset! cells/at-present? true)) |
| 279 | :open-channel! (fn [name] | 285 | :open-channel! (fn [name] |
| 280 | (reset! cells/current name) | 286 | (reset! cells/current name) |
| @@ -329,4 +335,6 @@ | |||
| 329 | :connect [connect/connect-screen] | 335 | :connect [connect/connect-screen] |
| 330 | :chats [chats/chats-screen] | 336 | :chats [chats/chats-screen] |
| 331 | :chat [chat/chat-screen] | 337 | :chat [chat/chat-screen] |
| 338 | + :discover [settings/discover-screen] | ||
| 339 | + :settings [settings/settings-screen] | ||
| 332 | [connected-screen])))))) | 340 | [connected-screen])))))) |
modified
src/frq/app.clj +2 -69 | @@ -37,6 +37,8 @@ | ||
| 37 | 37 | ;; phone renders this very file. |
| 38 | 38 | [frq.screens.chats :refer [below-list chats-screen conversation-row |
| 39 | 39 | preview-line tab-bar]] |
| 40 | + [frq.screens.settings :refer [discover-screen settings-screen | |
| 41 | + tab-screen]] | |
| 40 | 42 | [frq.screens.chat :refer [chat-screen emoji-picker message-row |
| 41 | 43 | reactor-dialog sidebar-width |
| 42 | 44 | users-panel]] |
| @@ -418,77 +420,8 @@ | ||
| 418 | 420 | |
| 419 | 421 | ;; ---------------------------------------------------------------- discover |
| 420 | 422 | |
| 421 | -(defn- tab-screen | |
| 422 | - "One of the three screens the tab bar moves between, in the chats screen's | |
| 423 | - shape: the title at the top, the tabs pinned at the bottom, and `body` | |
| 424 | - scrolling between them. | |
| 425 | - | |
| 426 | - The same shape for all three, so switching tabs moves nothing but the | |
| 427 | - middle. As pages they were centred columns of their own widths with the tabs | |
| 428 | - wherever the content happened to end, and every switch resized the screen | |
| 429 | - under the pointer." | |
| 430 | - [title scroll-key & body] | |
| 431 | - [:vbox {:spacing 8 :margin 12 :fill-height true} | |
| 432 | - [:title {:label title}] | |
| 433 | - [:vbox {:key :list :fill-height true} | |
| 434 | - (into [:scroll {:scroll-key scroll-key :orientation :vertical | |
| 435 | - :reserve (below-list) :spacing 8}] | |
| 436 | - body)] | |
| 437 | - [:vbox {:key :foot :spacing 8} | |
| 438 | - [:separator {}] | |
| 439 | - [tab-bar]]]) | |
| 440 | - | |
| 441 | -(defn discover-screen [] | |
| 442 | - (tab-screen "Discover" "discover-list" | |
| 443 | - [:dim-label {:label "Popular channels on freeq."}] | |
| 444 | - [error-note] | |
| 445 | - (for [[name blurb] s/popular-channels] | |
| 446 | - (let [joined? (get-in @s/channels [name :joined?])] | |
| 447 | - [:card {:key name} | |
| 448 | - [:title-2 {:label name}] | |
| 449 | - [:dim-label {:label blurb}] | |
| 450 | - [:button {:label (if joined? "Open" "Join") | |
| 451 | - :kind :primary | |
| 452 | - :on-click #(if joined? (s/open-channel! name) (s/join! name))}]])))) | |
| 453 | - | |
| 454 | 423 | ;; ---------------------------------------------------------------- settings |
| 455 | 424 | |
| 456 | -(defn settings-screen [] | |
| 457 | - (tab-screen "Settings" "settings-list" | |
| 458 | - [:card {} | |
| 459 | - [:title-2 {:label "Connection"}] | |
| 460 | - [:status {:label @s/status :live (s/connected?)}] | |
| 461 | - [:label {:label (str "Server: " @s/form-host ":" @s/form-port)}] | |
| 462 | - [:label {:label (str "Nick: " @s/form-nick)}] | |
| 463 | - (if-let [sess @s/session] | |
| 464 | - [:vbox {:spacing 2} | |
| 465 | - [:label {:label (str "Signed in as " (:handle sess))}] | |
| 466 | - [:dim-label {:label (or (:did sess) "")}] | |
| 467 | - [:vbox {:key :forget} | |
| 468 | - (when @s/broker-token | |
| 469 | - [:button {:label "Forget Bluesky session" | |
| 470 | - :kind :destructive | |
| 471 | - :on-click s/forget-session!}])]] | |
| 472 | - [:dim-label {:label "Guest — not signed in."}]) | |
| 473 | - [:separator {}] | |
| 474 | - ;; Nothing to disconnect from when there is no connection — the way back to | |
| 475 | - ;; the connect screen is what is wanted then. | |
| 476 | - [:vbox {:key :connection-action} | |
| 477 | - (if (s/connected?) | |
| 478 | - [:button {:label "Disconnect" :kind :destructive :on-click s/disconnect!}] | |
| 479 | - [:button {:label "Back to connect" | |
| 480 | - :on-click #(reset! s/screen :connect)}])]] | |
| 481 | - [:card {} | |
| 482 | - [:title-2 {:label "Messages"}] | |
| 483 | - [:checkbutton {:label "Hide join/part messages" | |
| 484 | - :active @s/hide-join-part? | |
| 485 | - :on-toggled s/toggle-hide-join-part!}] | |
| 486 | - [:dim-label {:label "Hides other people arriving, leaving and quitting. The people panel still follows who is here."}]] | |
| 487 | - [:card {} | |
| 488 | - [:title-2 {:label "frq"}] | |
| 489 | - [:dim-label {:label "freeq client in jolt — glimmer components on the Vidya/egui backend."}] | |
| 490 | - [:button {:label "Quit" :on-click platform/quit!}]])) | |
| 491 | - | |
| 492 | 425 | ;; ---------------------------------------------------------------- shell |
| 493 | 426 | |
| 494 | 427 | (defn app [] |
| @@ -37,6 +37,8 @@ | |||
| 37 | ;; phone renders this very file. | 37 | ;; phone renders this very file. |
| 38 | [frq.screens.chats :refer [below-list chats-screen conversation-row | 38 | [frq.screens.chats :refer [below-list chats-screen conversation-row |
| 39 | preview-line tab-bar]] | 39 | preview-line tab-bar]] |
| 40 | + [frq.screens.settings :refer [discover-screen settings-screen | ||
| 41 | + tab-screen]] | ||
| 40 | [frq.screens.chat :refer [chat-screen emoji-picker message-row | 42 | [frq.screens.chat :refer [chat-screen emoji-picker message-row |
| 41 | reactor-dialog sidebar-width | 43 | reactor-dialog sidebar-width |
| 42 | users-panel]] | 44 | users-panel]] |
| @@ -418,77 +420,8 @@ | |||
| 418 | 420 | ||
| 419 | ;; ---------------------------------------------------------------- discover | 421 | ;; ---------------------------------------------------------------- discover |
| 420 | 422 | ||
| 421 | -(defn- tab-screen | ||
| 422 | - "One of the three screens the tab bar moves between, in the chats screen's | ||
| 423 | - shape: the title at the top, the tabs pinned at the bottom, and `body` | ||
| 424 | - scrolling between them. | ||
| 425 | - | ||
| 426 | - The same shape for all three, so switching tabs moves nothing but the | ||
| 427 | - middle. As pages they were centred columns of their own widths with the tabs | ||
| 428 | - wherever the content happened to end, and every switch resized the screen | ||
| 429 | - under the pointer." | ||
| 430 | - [title scroll-key & body] | ||
| 431 | - [:vbox {:spacing 8 :margin 12 :fill-height true} | ||
| 432 | - [:title {:label title}] | ||
| 433 | - [:vbox {:key :list :fill-height true} | ||
| 434 | - (into [:scroll {:scroll-key scroll-key :orientation :vertical | ||
| 435 | - :reserve (below-list) :spacing 8}] | ||
| 436 | - body)] | ||
| 437 | - [:vbox {:key :foot :spacing 8} | ||
| 438 | - [:separator {}] | ||
| 439 | - [tab-bar]]]) | ||
| 440 | - | ||
| 441 | -(defn discover-screen [] | ||
| 442 | - (tab-screen "Discover" "discover-list" | ||
| 443 | - [:dim-label {:label "Popular channels on freeq."}] | ||
| 444 | - [error-note] | ||
| 445 | - (for [[name blurb] s/popular-channels] | ||
| 446 | - (let [joined? (get-in @s/channels [name :joined?])] | ||
| 447 | - [:card {:key name} | ||
| 448 | - [:title-2 {:label name}] | ||
| 449 | - [:dim-label {:label blurb}] | ||
| 450 | - [:button {:label (if joined? "Open" "Join") | ||
| 451 | - :kind :primary | ||
| 452 | - :on-click #(if joined? (s/open-channel! name) (s/join! name))}]])))) | ||
| 453 | - | ||
| 454 | ;; ---------------------------------------------------------------- settings | 423 | ;; ---------------------------------------------------------------- settings |
| 455 | 424 | ||
| 456 | -(defn settings-screen [] | ||
| 457 | - (tab-screen "Settings" "settings-list" | ||
| 458 | - [:card {} | ||
| 459 | - [:title-2 {:label "Connection"}] | ||
| 460 | - [:status {:label @s/status :live (s/connected?)}] | ||
| 461 | - [:label {:label (str "Server: " @s/form-host ":" @s/form-port)}] | ||
| 462 | - [:label {:label (str "Nick: " @s/form-nick)}] | ||
| 463 | - (if-let [sess @s/session] | ||
| 464 | - [:vbox {:spacing 2} | ||
| 465 | - [:label {:label (str "Signed in as " (:handle sess))}] | ||
| 466 | - [:dim-label {:label (or (:did sess) "")}] | ||
| 467 | - [:vbox {:key :forget} | ||
| 468 | - (when @s/broker-token | ||
| 469 | - [:button {:label "Forget Bluesky session" | ||
| 470 | - :kind :destructive | ||
| 471 | - :on-click s/forget-session!}])]] | ||
| 472 | - [:dim-label {:label "Guest — not signed in."}]) | ||
| 473 | - [:separator {}] | ||
| 474 | - ;; Nothing to disconnect from when there is no connection — the way back to | ||
| 475 | - ;; the connect screen is what is wanted then. | ||
| 476 | - [:vbox {:key :connection-action} | ||
| 477 | - (if (s/connected?) | ||
| 478 | - [:button {:label "Disconnect" :kind :destructive :on-click s/disconnect!}] | ||
| 479 | - [:button {:label "Back to connect" | ||
| 480 | - :on-click #(reset! s/screen :connect)}])]] | ||
| 481 | - [:card {} | ||
| 482 | - [:title-2 {:label "Messages"}] | ||
| 483 | - [:checkbutton {:label "Hide join/part messages" | ||
| 484 | - :active @s/hide-join-part? | ||
| 485 | - :on-toggled s/toggle-hide-join-part!}] | ||
| 486 | - [:dim-label {:label "Hides other people arriving, leaving and quitting. The people panel still follows who is here."}]] | ||
| 487 | - [:card {} | ||
| 488 | - [:title-2 {:label "frq"}] | ||
| 489 | - [:dim-label {:label "freeq client in jolt — glimmer components on the Vidya/egui backend."}] | ||
| 490 | - [:button {:label "Quit" :on-click platform/quit!}]])) | ||
| 491 | - | ||
| 492 | ;; ---------------------------------------------------------------- shell | 425 | ;; ---------------------------------------------------------------- shell |
| 493 | 426 | ||
| 494 | (defn app [] | 427 | (defn app [] |
modified
src/frq/state.clj +3 -14 | @@ -54,16 +54,8 @@ | ||
| 54 | 54 | (def search cells/search) |
| 55 | 55 | (def login-url cells/login-url) |
| 56 | 56 | |
| 57 | -(def popular-channels | |
| 58 | - [["#general" "General discussion"] | |
| 59 | - ["#test" "Test channel"] | |
| 60 | - ["#freeq" "freeq development & support"] | |
| 61 | - ["#dev" "Programming & technology"] | |
| 62 | - ["#music" "Music recommendations"] | |
| 63 | - ["#random" "Off-topic chat"]]) | |
| 57 | +(def popular-channels cells/popular-channels) | |
| 64 | 58 | |
| 65 | - | |
| 66 | -;; joined as soon as the server sends 001 | |
| 67 | 59 | (def auto-join "#test") |
| 68 | 60 | |
| 69 | 61 | ;; How much backlog to ask for when the server did not volunteer any. |
| @@ -186,11 +178,7 @@ | ||
| 186 | 178 | ;; monotonic tick cannot be surprised by the system time moving. |
| 187 | 179 | (defonce access-tick (atom 0)) |
| 188 | 180 | |
| 189 | -;; Comings and goings, hidden or not. A quiet room reads better with them — | |
| 190 | -;; they are how you notice someone arriving — and a busy one drowns in them, | |
| 191 | -;; so it is the reader's call. Only other people's: your own "Joined #chan" is | |
| 192 | -;; the answer to something you just did. | |
| 193 | -(defonce hide-join-part? (atom false)) | |
| 181 | +(def hide-join-part? cells/hide-join-part?) | |
| 194 | 182 | |
| 195 | 183 | ;; Whether rooms.edn is the authority yet. |
| 196 | 184 | ;; |
| @@ -1961,6 +1949,7 @@ | ||
| 1961 | 1949 | :join! join! |
| 1962 | 1950 | :open-channel! open-channel! |
| 1963 | 1951 | :leave-channel! leave-channel! |
| 1952 | + :toggle-hide-join-part! toggle-hide-join-part! | |
| 1964 | 1953 | :send-draft! send-draft! |
| 1965 | 1954 | :cancel-edit! cancel-edit! |
| 1966 | 1955 | :cancel-reply! cancel-reply! |
| @@ -54,16 +54,8 @@ | |||
| 54 | (def search cells/search) | 54 | (def search cells/search) |
| 55 | (def login-url cells/login-url) | 55 | (def login-url cells/login-url) |
| 56 | 56 | ||
| 57 | -(def popular-channels | 57 | +(def popular-channels cells/popular-channels) |
| 58 | - [["#general" "General discussion"] | ||
| 59 | - ["#test" "Test channel"] | ||
| 60 | - ["#freeq" "freeq development & support"] | ||
| 61 | - ["#dev" "Programming & technology"] | ||
| 62 | - ["#music" "Music recommendations"] | ||
| 63 | - ["#random" "Off-topic chat"]]) | ||
| 64 | 58 | ||
| 65 | - | ||
| 66 | -;; joined as soon as the server sends 001 | ||
| 67 | (def auto-join "#test") | 59 | (def auto-join "#test") |
| 68 | 60 | ||
| 69 | ;; How much backlog to ask for when the server did not volunteer any. | 61 | ;; How much backlog to ask for when the server did not volunteer any. |
| @@ -186,11 +178,7 @@ | |||
| 186 | ;; monotonic tick cannot be surprised by the system time moving. | 178 | ;; monotonic tick cannot be surprised by the system time moving. |
| 187 | (defonce access-tick (atom 0)) | 179 | (defonce access-tick (atom 0)) |
| 188 | 180 | ||
| 189 | -;; Comings and goings, hidden or not. A quiet room reads better with them — | 181 | +(def hide-join-part? cells/hide-join-part?) |
| 190 | -;; they are how you notice someone arriving — and a busy one drowns in them, | ||
| 191 | -;; so it is the reader's call. Only other people's: your own "Joined #chan" is | ||
| 192 | -;; the answer to something you just did. | ||
| 193 | -(defonce hide-join-part? (atom false)) | ||
| 194 | 182 | ||
| 195 | ;; Whether rooms.edn is the authority yet. | 183 | ;; Whether rooms.edn is the authority yet. |
| 196 | ;; | 184 | ;; |
| @@ -1961,6 +1949,7 @@ | |||
| 1961 | :join! join! | 1949 | :join! join! |
| 1962 | :open-channel! open-channel! | 1950 | :open-channel! open-channel! |
| 1963 | :leave-channel! leave-channel! | 1951 | :leave-channel! leave-channel! |
| 1952 | + :toggle-hide-join-part! toggle-hide-join-part! | ||
| 1964 | :send-draft! send-draft! | 1953 | :send-draft! send-draft! |
| 1965 | :cancel-edit! cancel-edit! | 1954 | :cancel-edit! cancel-edit! |
| 1966 | :cancel-reply! cancel-reply! | 1955 | :cancel-reply! cancel-reply! |