1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
//! **What the window holds between frames** — the struct, and nothing else.
//!
//! Split from [`super`] at the 300-line cap on the seam that module's own doc
//! draws: [`super`] is the module list and the re-export surface, and this is
//! the snapshot a frame reads. Nothing here paints and nothing here dials, so
//! every rule for changing it is a pure function a test reads back as a value.
//!
//! **The questions asked of it are [`asked`]**, split off at the same cap when
//! the drag added the second of them: a field is what a pane learned to hold,
//! and a question is what two panes turned out to need one answer to.
/// The two questions asked of the model that no pane owns.
mod asked;
use super::{
Aim, Asking, Authoring, Bindings, Chunk, Columns, Configuring, Diagnosis, Dragged, Engines,
Enrolling, Fill, Fleet, Forking, Hits, Listing, Login, Lookup, Notice, Pages, Posted, Records,
Start, Trail, Tuning, Unmaking,
};
use crate::reply::convs::ConvRow;
use crate::reply::stream::Stream;
use crate::reply::transcript::Transcript;
/// Everything the window holds between frames.
#[derive(Debug, Clone, Default)]
pub struct Model {
/// Every channel's workspaces, in the order the channels were asked.
pub roster: Vec<Chunk>,
/// The aimed wall's conversations.
pub convs: Vec<ConvRow>,
/// **Which wall [`Self::convs`] is the ANSWER to**, or `None` while the aim
/// has not been answered about at all (bl-f780).
///
/// It rides beside the rows rather than being derived, because emptiness
/// cannot tell the two apart: a wall that answered zero conversations and a
/// wall nobody has asked about yet hold the same `Vec`, and painting *"no
/// conversations here"* over the second states a definite fact about a wall
/// nobody looked at — the same thing `crate::ui::convs::UNCERTAIN` refuses
/// to do one level down, on a conversation nobody could take a reading of.
///
/// It is set and cleared at exactly the two places `convs` is, and nowhere
/// else.
pub answered: Option<Aim>,
/// **What the aimed wall's roles are set to**, or `None` while nobody has
/// been answered about them — one field where [`Self::convs`] needs a pair,
/// because here the option carries the whole distinction (`tuning`).
pub roles: Option<Vec<crate::reply::roles::RoleRow>>,
/// **The tuning pane, while it is open** — the second pane in this window
/// that covers the conversation ([`Tuning`]).
pub tuning: Option<Tuning>,
/// **Which of the three LISTING panes is standing**, if any — the records
/// pane, the decision queue, or the clients pane (`listing`). One field
/// rather than a flag each: they hold nothing of their own, no two ever
/// stand together, and three bools would make *two of them open at once* a
/// state only the derivation order resolves — the reframe clippy's
/// `struct_excessive_bools` names, taken rather than suppressed.
pub listing: Option<Listing>,
/// **The machines registered in the aimed wall's workspace**, or `None`
/// while nobody has been answered about it — the one-option reading
/// [`Self::roles`] gets, one noun over (`clients`).
pub machines: Option<Vec<crate::reply::clients::ClientRow>>,
/// **The config pane, while it is open** — the eleventh covering pane, and
/// the fourth whose subject is the aimed wall (`config`; DESIGN §4.30). A
/// struct rather than a flag because it holds one question of its own:
/// which file it is pointed at.
pub configuring: Option<Configuring>,
/// **One config file's bytes and the settings its schema found**, or
/// `None` while nobody has been answered about the file the pane points at
/// — the one-option reading [`Self::roles`] gets (`config`).
pub config: Option<crate::reply::config::Config>,
/// **The aimed wall's config lineages**, on the same standing (`config`).
pub lineages: Option<Vec<crate::reply::lineages::Lineage>>,
/// **What a reviewer has staged for it**, on the same standing (bl-a1d6).
pub proposals: Option<crate::reply::proposals::Proposals>,
/// **The login pane, while it is open** — the eighth covering pane, and
/// the second whose subject is the aimed wall (`login`; DESIGN §4.24). A
/// struct rather than a flag because it holds two questions of its own:
/// which row a sign-in is being followed on, and which was asked what it
/// offers.
pub login: Option<Login>,
/// **What the aimed wall can sign in to**, or `None` while nobody has been
/// answered about it — the one-option reading [`Self::roles`] gets, and
/// filed here rather than on the pane because the rows are the engine's.
pub providers: Option<Vec<crate::reply::providers::ProviderRow>>,
/// **What the last row asked answered with** — the posted read's answer,
/// dropped by the act that asks another (`login`). Which row it is about
/// is the pane's `asking`, because the reply carries no name.
pub offered: Option<Vec<String>>,
/// **The sign-in run this seat is following**, as the lane has folded it —
/// the login pane's held read, and [`Self::live`]'s shape one noun over
/// (`login`).
pub signin: Option<crate::reply::login::Signin>,
/// **Which of the window's own three panes is standing**, if any — the
/// sixth, seventh and tenth covering panes, and the three whose subject is
/// every channel and which are opened from the roster's own ops row
/// (`window`, `trail`; bl-40ec, bl-4c48). One field rather than three
/// flags, because no two panes ever stand together and a set of bools
/// would make *all three* representable — which is also the reframe
/// clippy's `struct_excessive_bools` asks for by name, taken rather than
/// suppressed.
///
/// It is a second field beside [`Self::listing`] and not one with it,
/// because the two name different axes: these three are the WINDOW's own —
/// reached from the ops row, about every channel, and one of them holds a
/// needle — while a listing is a pane about one thing on the glass that
/// holds nothing at all. DESIGN §4.28 records the fold that would make
/// them one.
pub lookup: Option<Lookup>,
/// **An unmaking, while it stands** — the fifth covering pane, and the only
/// one this window has whose act cannot be undone by doing the other thing
/// (`unmake`; DESIGN §4.20). It carries the wall it was opened on rather
/// than following the aim, because the roster stays live under it.
pub unmaking: Option<Unmaking>,
/// **What each channel last said is asking for the operator**, one section
/// per channel and the union across them. A `Vec` rather than an option
/// because the emptiness that matters is per channel: nothing here at all
/// is nobody answered yet, and a section holding no row is an engine that
/// answered and holds nothing waiting (`queue`).
pub waiting: Vec<Asking>,
/// **What each channel last said has crossed its boundary** — the same
/// per-channel reading, one noun over (`trail`; bl-4c48).
pub trails: Vec<Trail>,
/// **What each channel last said its board is** — every live ball in its
/// column and the loops running them, on the trail's own per-channel
/// reading (`board`; bl-d2af).
pub columns: Vec<Columns>,
/// **What each channel last said its ball⇄workspace bindings are**, on the
/// same terms (`board`).
pub bindings: Vec<Bindings>,
/// **What the aimed wall last said it holds**, or `None` while nobody has
/// been answered about it — the one-option reading [`Self::roles`] gets,
/// and retired with the aim for the same reason (`board`).
pub holding: Option<Vec<crate::reply::balls::BoundBall>>,
/// **The branch the aimed wall tracks its tasks on**, on the same standing
/// (`board`).
pub marks: Option<String>,
/// **A ball's text being authored, while the block is open** (`board::
/// acts`; DESIGN §4.35, bl-f7ae). A struct rather than a flag because it
/// holds the wall it was opened on and the name that wall's engine knows
/// it by, and because one block serves two subjects — a ball that does not
/// exist yet, and one this wall holds.
pub authoring: Option<Authoring>,
/// **The fleet pane, while it is open** — the thirteenth covering pane,
/// and the fifth whose subject is the aimed wall (`fleet`; DESIGN §4.33).
/// A struct rather than a flag because three of its five acts carry a word
/// nothing on the glass can derive, and because it holds the wall it was
/// opened on rather than following the aim.
pub fleet: Option<Fleet>,
/// **The aimed wall's delivery attempts**, or `None` while nobody has been
/// answered — the one-option reading [`Self::roles`] gets (`fleet`).
pub attempts: Option<Vec<crate::reply::science::Attempt>>,
/// **What its agents changed**, on the same standing (`fleet`).
pub work: Option<Vec<crate::reply::diff::Diff>>,
/// **What each channel last said it answers to** — the same per-channel
/// reading, one noun over (`window`; bl-40ec).
pub pages: Vec<Pages>,
/// **What each channel last found**, on the same terms (`window`).
pub found: Vec<Hits>,
/// **What each channel said about its own wiring** (`doctor`; bl-9bbb).
pub diagnoses: Vec<Diagnosis>,
/// **What to look for.** A box the find pane holds and does not spend on
/// firing, because refining a needle is the common act — unlike the
/// composer's draft, which was sent (`window`).
pub needle: String,
/// **The draft a fork is composed from** (`spine`): the role and the goal,
/// beside the `from` each control carries off its own notch. A bare field
/// and not an option, exactly as the composer's two parameter boxes are —
/// the boxes are on the glass whenever the spine is.
pub forking: Forking,
/// **The arming for the cascade** (`crate::ui::records::cascade`): the
/// conversation's own name typed back, which is what admits the
/// conversations under it into a stop. It is this seat's own enablement
/// and not a wire field — `stop` carries a boolean flag and no `typed` —
/// so it is never sent, only read (DESIGN §4.20's amended scope rule).
pub cascade: String,
/// **What the records pane has been answered** — its seven reads, held
/// together because they are one pane's questions about one subject and
/// they are retired together when that subject moves (`records`).
///
/// A struct rather than seven fields, on `listing`'s own reasoning one
/// layer over: seven options on this struct would be seven places to
/// remember when a selection moves, and forgetting one paints a
/// conversation's records under another's name.
pub records: Records,
/// The selected conversation, as committed.
pub transcript: Transcript,
/// The live tail as this seat has accumulated it. It **replaces**, never
/// accretes — and since PROTOCOL 2 that is a statement about where the
/// accretion happens rather than whether it does: a follow frame is an
/// append (REMOTE §5.5), so `crate::offframe::follow` absorbs each frame
/// onto the read's own fold and what reaches here is already whole. The
/// fold's lifetime is one read, which is what keeps two reads of one
/// conversation from running into each other.
pub live: Option<Stream>,
/// What the seat last heard that was not content.
pub notice: Option<Notice>,
/// Which wall the window is aimed at.
pub aim: Option<Aim>,
/// **The edges the operator has dragged** (`dragged`; DESIGN §4.39). One
/// field rather than three, because the three are one fact — what this
/// seat holds of its own layout — and they are written down together
/// (`crate::place`).
pub dragged: Dragged,
/// **How the engines are arranged** (DESIGN §4.39, `engines`): which one
/// is open, when each was last opened here, and the wall last aimed under
/// each. One field rather than three, because the three are one subject
/// and they are written down together ([`crate::place`]).
pub engines: Engines,
/// **Which engine row the roster's walk is standing on**, or `None` where
/// the cursor is on a wall.
///
/// It is the one place in this window where the cursor is NOT the
/// selection, and DESIGN §4.39 says why: opening an engine is an act, so a
/// walk that moved through a closed engine would open every engine it
/// passed. So the walk stands on the row, the row takes the keyboard, and
/// Enter or Space fires the same click a pointer fires. It rides here and
/// not on `Engines`, because it is a cursor and nothing durable.
pub standing: Option<String>,
/// **Which column is on the glass in the narrow shape** — a navigation the
/// operator performed, so it is the one thing here no other fact can be
/// asked for. The broad shape never reads it, because every column is on
/// the glass there (`crate::ui::shell::policy`).
pub column: crate::ui::Column,
/// **Whether the list owes its selection a place on the glass**, set by a
/// keyboard walk and taken by the pane that paints it
/// ([`Model::revealing`]).
///
/// The keyboard is the only surface that can move a selection out of view:
/// a click names a row the operator is already looking at, and a scroll IS
/// the operator deciding what to look at — so a pane that revealed on every
/// frame would drag the glass back every time they scrolled away.
pub reveal: bool,
/// The selected conversation's id.
pub conversation: Option<String>,
/// **Which conversations have had their subtree opened** (`subtree`;
/// bl-00f5).
///
/// A set of what is OPEN rather than of what is folded, so the default
/// costs no state at all: a seat that has never been told otherwise shows
/// the conversations and not the machinery under them. It is a navigation
/// the operator performed, which is the one class of thing on this struct
/// no other fact can be asked for — [`Self::column`]'s own standing.
pub opened: std::collections::BTreeSet<String>,
/// What the operator has typed and not yet sent.
pub draft: String,
/// **The arming for the unmaking** (`crate::ui::composer::acts`): the name
/// typed back, which is what admits a conversation's descendants into its
/// deletion. Empty is the bare form and deletes the one conversation, so
/// this is not a second control's enablement — it is the gesture's own
/// third parameter, held where the box that fills it is.
pub typed: String,
/// **Which of the two boxes above a row menu asked for the cursor in**, or
/// `None` where nobody has asked (`fill`; bl-dbc9). A conversation row's
/// menu cannot hold either box, so the item that would need one goes to it
/// instead — and this is the request, taken by the frame that paints it.
pub fill: Option<Fill>,
/// **The words a flag is raised with** (`crate::ui::composer::acts`). The
/// wire requires them — a flag with nothing in it is a row nobody can
/// triage — so the control is disabled until there are any, and the box is
/// SPENT on firing: what a flag says is said, exactly as a deposit is.
pub reason: String,
/// **Whether the next conversation is born on the planner role** (DESIGN
/// §4.39; REMOTE §9.21, PROTOCOL 18) — the one parameter a start has, and
/// the whole of what the composer's start-mode row carries
/// (`crate::ui::composer::offers`).
///
/// It is held here and not with the start itself because it is stated
/// **between** the stage and the fire: the frame that absorbs `prepare`'s
/// receipt is what writes the field onto the body it hands back
/// (`start::Model::fire`), and that frame reads the window, not the
/// gesture. A bool rather than the role's own name, because the name is
/// `crate::verbs::start::PLANNER` and a second copy of it here would be a
/// second place for the wire's word to live.
pub plan: bool,
/// **A start, while it is happening** — the one thing this window holds
/// across a round trip, because starting is two acts and the second is
/// composed from the first's answer ([`Start`]).
pub start: Option<Start>,
/// **An enrollment, while it is happening** — the second thing this window
/// holds across a round trip, and the only thing it ever holds that is a
/// secret. It is dropped by a control and written down nowhere
/// ([`Enrolling`]).
pub enroll: Option<Enrolling>,
/// **The gestures this frame composed**, for whoever can send them. A frame
/// that posted its own would be a frame that waits.
///
/// Each carries whether it is an ACT, said by the control that composed it,
/// because a lost reply means opposite things for the two ([`Posted`]).
pub outbox: Vec<Posted>,
}