Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/647-phone-dock.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
On a phone the whole session dock is now touch-sized, not only the held-reply card: every button in it (invite by link, approve all held replies, accept or decline a notice, close a room) is 40px tall instead of the desktop 26–30px, the Auto-send and Copy link links get a real hit area, and the dock clears the phone's home indicator, so a decision can be made one-handed (#647).
2 changes: 1 addition & 1 deletion docs/subsystems/social.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ Creating a group opens its Session with zero turns, and the host draws no sessio
- Status chips on room details and Past rooms (`data-flybot=face-status`) read **Open** / **Closed** in sentence case with readable contrast, and the past row keeps its own spacing between avatars, title, time and chip (#170).
- One card-placement rule (#418): a held message's decision sits where that message is. A Bot's reply to a friend has its buttons on the held reply bubble in place (no copy in the dock of that chat or the friend's chat); a message with no bubble of its own (a Bot's `message_friend_bot`, a typed composer line held by policy, a face-room line) has its card in the dock of the chat it belongs to, as below.
- In-chat approval cards (`flybot.session.dock`) are right-aligned bubbles capped at ~460px: **Waiting for approval**, one `from → to` line, a word-wrapped preview with **Show more**, and **Approve** / **Reject** (one right-hand group) with a quiet **Always approve** link at the left of the same row, alone above them when the card is narrow (#166, #260, #271). One place per approval (#278): a Bot's direct message to a friend is drawn in the friend's chat once that chat exists (the sending Bot's own chat only until then), never in a Face-to-face room that has the friend in it; a Face-to-face room shows, counts as waiting, and gets a "Waiting for the owner's approval" notice for just the lines held for its own room id. The client also hides that old notice in a Face-to-face room's history. The held text shows once (#306): a Bot line held in a Face-to-face room keeps its text in the card, and the room draws no bubble for it until it is approved (`GroupMessage`, `core/src/client/cells.js`, matched by `room.heldLines`, #456, and by `room.pendingApprovals` as a fallback); a line the owner typed is never held and stays a plain bubble. A Bot's message to a friend (`message_friend_bot`) has no bubble in either chat, so the card is already its only place. #456: the held room line lives only on its card (greyed preview) until **Approve**: `onFaceLine` answers `{ held: true, approvalId }` for a Bot line Bot Social holds, `social/decide-approval` calls `flybot.rooms.settleHeld`, Approve makes it a room bubble and Reject a grey `<Bot> · Not sent` line, with no `Rejected.` note in the face room. A decided card leaves the dock at once (no **Approved** / **Rejected** stub, any card kind). A face card's `from` is the room's own #384 label for that local Bot (`Researcher (Alice) → the room`, `faceFromLabel`). `applyFaceSnapshot` posts a human or system event for a round only when the core room logged it now (`applyFaceLine` refuses an event id it has), so an event read twice starts no second round.
- On a phone-width screen (below 640px, #362) the hold card's **Approve** / **Reject** are 40px touch targets at the right of their row; wider screens keep the compact 28px buttons.
- On a phone-width screen (below 640px, #362) the hold card's **Approve** / **Reject** are 40px touch targets at the right of their row; wider screens keep the compact 28px buttons. The same media query carries the rest of the session dock (#647): every button in that slot is 40px — **Invite by link**, **Approve all**, the notice **Accept** / **Decline**, **Close** — because below 640px those are the only way to answer on a touch screen and they were left at the desktop 30px `.fs-btn` / 26px `.fs-btn-sm`; the **Auto-send** and **Copy link** links get a 32px hit area instead of their 12px text run, and the dock pads its bottom by `env(safe-area-inset-bottom)`. That value is 0 on today's shell — its viewport is `width=device-width, initial-scale=1` with no `viewport-fit=cover` (`dsh-web-frontend`, DSH's file, #647) — so the rule costs nothing until a shell sets it, and no other inset rule is worth adding before then. The rules key off the dock's container class `.bt-flybot-session-dock` (`core/src/client/flybot-slots.js`), so no component changed and nothing outside that query moved. The install half of #647 — a manifest of our own, raster icons, a service worker — stays DSH's (`core-client.md`): this page changes only what FlyBot draws.
- The composer **Message {name}** label is held by core `HeaderPill` through `composer-label.js` (placeholder CSS var plus `aria-label` and `data-placeholder` on `[data-composer-input]`, from the first paint, restored on cleanup; #419, #499); chat-header tok jargon stays in pristine DSH / ds-bot.

### Face-room poll identity (#122)
Expand Down
2 changes: 1 addition & 1 deletion plugins/social/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ window.__ModuleLoader__.load({
.fs-hold .fs-hold-decide{display:flex;gap:8px;flex:none}
.fs-hold .fs-actions .fs-hold-always{order:-1;margin-right:auto;white-space:nowrap;flex:0 0 auto}
.fs-hold[data-state] .fs-name{font-size:13px;line-height:18px;font-weight:500;color:var(--bt-ink-2,rgba(20,20,20,.6))}
@media (max-width:640px){.fs-hold .fs-btn{height:40px;padding:0 16px;font-size:14px}.fs-hold .fs-hold-decide{flex:1 1 auto;justify-content:flex-end}}
@media (max-width:640px){.fs-hold .fs-btn{height:40px;padding:0 16px;font-size:14px}.fs-hold .fs-hold-decide{flex:1 1 auto;justify-content:flex-end}.bt-flybot-session-dock{padding-bottom:calc(6px + env(safe-area-inset-bottom,0px))}.bt-flybot-session-dock .fs-btn,.bt-flybot-session-dock .fs-btn-sm{height:40px;padding:0 14px;font-size:14px}.bt-flybot-session-dock .fs-link{display:inline-flex;align-items:center;min-height:32px;padding:0 4px;font-size:13px}.fs-group-strip{margin:6px 8px}}
.fs-row-wrap{position:relative;display:flex;align-items:center;gap:2px;min-width:0}
.fs-row-wrap .fs-row,.fs-row-wrap > :first-child{flex:1 1 auto;min-width:0}
.fs-remove{flex:none;width:20px;height:20px;padding:0;border:0;border-radius:6px;background:transparent;color:var(--bt-ink-3,rgba(20,20,20,.36));font:inherit;font-size:14px;line-height:1;cursor:pointer;opacity:0}
Expand Down
18 changes: 18 additions & 0 deletions plugins/social/test/social.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10301,6 +10301,24 @@ test('on a phone-width screen the hold card keeps Approve/Reject touch-sized (#3
assert.match(phone, /\.fs-hold \.fs-hold-decide\{[^}]*justify-content:flex-end/)
})

test('at phone width the rest of the session dock is touch-sized too, not only the held card (#647)', () => {
const src = readFileSync(new URL('../client.js', import.meta.url), 'utf8')
assert.equal((src.match(/@media \(max-width:640px\)\{/g) ?? []).length, 1, 'still one phone-width block')
const phone = src.match(/@media \(max-width:640px\)\{([^\n]*)\}\n/)?.[1]
assert.ok(phone, 'the block stays on one line, so it closes where it opened')
// The dock was left at desktop sizes: `.fs-btn` 30px and `.fs-btn-sm` 26px. On a phone those are
// the only way to invite by link, approve all held replies, accept a notice or close a room.
assert.match(phone, /\.bt-flybot-session-dock \.fs-btn,\.bt-flybot-session-dock \.fs-btn-sm\{height:40px;padding:0 14px;font-size:14px\}/)
// Auto-send and Copy link are 12px text runs with no box: give them a hit area.
assert.match(phone, /\.bt-flybot-session-dock \.fs-link\{[^}]*min-height:32px/)
// The dock is the last row above the composer, so it has to clear the phone's home indicator.
assert.match(phone, /\.bt-flybot-session-dock\{padding-bottom:calc\(6px \+ env\(safe-area-inset-bottom,0px\)\)\}/)
// Wider screens are unchanged: the desktop sizes stay outside the media query.
assert.match(src, /\n\.fs-btn\{flex:none;height:30px/)
assert.match(src, /\n\.fs-btn-sm\{height:26px/)
assert.match(src, /\n\.fs-group-strip\{[^}]*margin:6px 12px/)
})

// Bot Social with the room lead (#476): POST /lead and PUT /roles answer the room, as the server does.
function leadFaceServer(features) {
const server = attestingFaceServer({ features })
Expand Down
Loading