From b68ca02af40b42f153049de06923e9ee1856f781 Mon Sep 17 00:00:00 2001 From: Danyang Chen <15378933+Birfy@users.noreply.github.com> Date: Sat, 17 Oct 2026 16:22:47 +0000 Subject: [PATCH 1/2] fix(social): read-only face rooms hide the composer, readable own handle, no Friends' Bots wording (#197) --- changelog.d/197-social-ui-nits.fixed.md | 1 + plugins/social/client.js | 6 ++++-- plugins/social/src/social.js | 4 ++-- plugins/social/test/social.test.js | 13 +++++++++++++ 4 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 changelog.d/197-social-ui-nits.fixed.md diff --git a/changelog.d/197-social-ui-nits.fixed.md b/changelog.d/197-social-ui-nits.fixed.md new file mode 100644 index 00000000..1738a67b --- /dev/null +++ b/changelog.d/197-social-ui-nits.fixed.md @@ -0,0 +1 @@ +Social: a face-to-face room you left or that closed no longer shows a message box under "You left this room."; your own handle in the account menu is in normal, readable ink; messages no longer point to a "Friends' Bots" section that no longer exists, and a held message to a friend's Bot names the Auto-send setting the UI actually shows. diff --git a/plugins/social/client.js b/plugins/social/client.js index cba950f5..6df40d3d 100644 --- a/plugins/social/client.js +++ b/plugins/social/client.js @@ -27,7 +27,7 @@ window.__ModuleLoader__.load({ return 'Social is not running: the plugin did not start. See Settings → Feedback.' } const message = String(e?.message ?? e ?? '') - if (/relationship_exists/i.test(message)) return "You're already friends. That Bot is in Friends' Bots again." + if (/relationship_exists/i.test(message)) return "You're already friends. Their Bot is back in your list." if (/invite_unavailable|invite is used|invite_used|already used/i.test(message)) return 'This invite was already used. Ask your friend for a new one.' return message } @@ -94,8 +94,10 @@ window.__ModuleLoader__.load({ .fs-pending-tag{background:var(--bt-accent,#4d6bfe);color:#fff} .fs-refresh{flex:none;font-size:11px;line-height:14px;color:var(--bt-ink-3,rgba(20,20,20,.36));font-weight:400} .fs-room-end{margin:6px 12px;padding:8px 10px;border-radius:8px;background:var(--bt-hover,rgba(119,119,119,.09));color:var(--bt-ink-2,rgba(20,20,20,.6));font-size:12px;line-height:16px} +/* A left or closed face room is read-only (#197): its end line replaces the composer. */ +[class*="_composerStack"]:has([data-flybot="face-room-end"]) [class*="_root"]:has(> [data-composer-card]){display:none!important} .fs-me{display:flex;align-items:center;gap:6px;padding:0 10px 4px;justify-content:space-between;font-size:11px;line-height:14px;color:var(--bt-ink-3,rgba(20,20,20,.36))} -.fs-me-handle{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--bt-ink-2,rgba(20,20,20,.6));font-size:12px} +.fs-me-handle{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--bt-ink,#141414);font-size:13px} .bt-menu .fs-me button.fs-link{display:inline;flex:none;width:auto;min-height:0;padding:0 2px;border-radius:4px;font-size:12px;line-height:16px} .fs-me .fs-link{flex:none} .fs-pending{margin:4px 4px 6px;padding:6px 8px;border:1px solid var(--bt-line-2,rgba(20,20,20,.15));border-radius:10px;background:var(--bt-card,#fff);display:flex;flex-direction:column;gap:4px;min-width:0;max-width:100%} diff --git a/plugins/social/src/social.js b/plugins/social/src/social.js index f1473d17..1c0f7ce1 100644 --- a/plugins/social/src/social.js +++ b/plugins/social/src/social.js @@ -238,7 +238,7 @@ export function mapJoinInviteError(error) { const code = String(error?.code ?? '') const blob = `${code} ${msg}` if (/relationship_exists/i.test(blob)) { - return Object.assign(new Error("You're already friends. That Bot is in Friends' Bots again."), { + return Object.assign(new Error("You're already friends. Their Bot is back in your list."), { code: 'relationship_exists', ...(error?.peer ? { peer: error.peer } : {}), ...(error?.bot ? { bot: error.bot } : {}), @@ -1129,7 +1129,7 @@ export function createSocial(service, config = {}, { client: given, api: givenAp if (settings.via[target] !== bot.id) { settings.via[target] = bot.id; saveSettings() } if (sent?.message?.status === 'pending_approval') { pendingCache.at = 0 - return `Sent, but Bot Social holds it until you approve it in Friends' Bots. Turn on Auto-accept for this friend to skip the hold on later messages.` + return `Sent, but it waits for your approval in this chat. Turn on Auto-send for this friend to skip that next time.` } return '' } catch (error) { diff --git a/plugins/social/test/social.test.js b/plugins/social/test/social.test.js index 7c16f710..c380e9d8 100644 --- a/plugins/social/test/social.test.js +++ b/plugins/social/test/social.test.js @@ -4399,3 +4399,16 @@ test('#192: Open on a room the user left shows that room with its transcript, re assert.equal(room.face.status, 'left') assert.ok(room.log.some(line => /earlier line/.test(line.text)), 'the transcript is kept') }) + +test('#197: a read-only face room hides the composer, the own handle uses normal ink, no Friends\' Bots section is named', () => { + const source = readFileSync(new URL('../client.js', import.meta.url), 'utf8') + // The end line of a left/closed room sits in the composer stack; the composer itself goes. + assert.match(source, /\[class\*="_composerStack"\]:has\(\[data-flybot="face-room-end"\]\) \[class\*="_root"\]:has\(> \[data-composer-card\]\)\{display:none!important\}/) + assert.match(source, /\.fs-me-handle\{[^}]*color:var\(--bt-ink,[^}]*\}/) + assert.doesNotMatch(source.match(/\.fs-me-handle\{[^}]*\}/)[0], /--bt-ink-2/) + const server = readFileSync(new URL('../src/social.js', import.meta.url), 'utf8') + for (const text of [source, server]) { + assert.doesNotMatch(text, /(?:return|Error\()[^\n]*in Friends' Bots/) + } + assert.equal(mapJoinInviteError(Object.assign(new Error('relationship_exists'), { code: 'relationship_exists' })).message, "You're already friends. Their Bot is back in your list.") +}) From 1c7f4482343eea14438d825d567613ed2f60e487 Mon Sep 17 00:00:00 2001 From: Danyang Chen <15378933+Birfy@users.noreply.github.com> Date: Sat, 17 Oct 2026 16:24:47 +0000 Subject: [PATCH 2/2] docs(social): note #197 read-only face room composer and wording --- docs/subsystems/social.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/subsystems/social.md b/docs/subsystems/social.md index ae02d366..a518c76d 100644 --- a/docs/subsystems/social.md +++ b/docs/subsystems/social.md @@ -62,6 +62,7 @@ Everything in `plugins/social/` (entry `plugins/social/index.js` and any helpers - #194: a face room title shows one time: Bot Social's `created_at`, else the joining deadline minus the 10-minute window (`faceRoomCreatedAt`), the same before and after Enter chat and on every home. - #195: the Add friend paste button reads **Accept invite**; an accepted Bot invite posts a toast and closes the panel at once. - #191: a peer's leave reads `Bob left the room` (the person, from the member's owner name; the Bot label only when there is no owner name), and an ended face room shows a plain status line above the composer (`FaceRoomStatus` on `flybot.session.dock`, `data-flybot=face-room-end`: `Bob left the room. This room is closed.` / `You left this room.`). Joining by number opens the new room in the main pane at once, so the top bar never keeps the previous room's title. +- #197: while that status line shows, the composer is hidden (a CSS rule on the composer stack that has `data-flybot=face-room-end`), so a left or closed room is read-only. The account-menu handle uses normal ink. User-facing text no longer names a Friends' Bots section: `relationship_exists` reads `You're already friends. Their Bot is back in your list.`, and a held message to a friend's Bot says it waits for approval in this chat and names the Auto-send setting. - My own handle (`@name.home`) shows with a **Copy** link at the top of the account menu (slot `flybot.account.header`, `MyHandle`) as well as in Add friend (#181). - Sidebar **+** is a short action menu, not the To:/composer. Add friend has one-click **Copy invite link** (mint + clipboard) with a Bot picker when there is more than one Bot, and a `You are @your.home` line (#181). **Talk through** stays on one line (nowrap label). Bot Sharing puts the invite link on its own full-width row above **Copy link** / **Copy with instructions**. The social strip keeps the **N to approve** badge and opens that chat; the stacked jump list stays out of the column. Held `face_room_message` drafts show in that face chat with readable names (`Chief → the room`), never raw `bot_01…` or a `FLYBOT-FACE-HUMAN` envelope.