From ccf86fe5ec9985b45fb74393ca8428efc6fa6c32 Mon Sep 17 00:00:00 2001 From: Salastil Date: Sat, 24 Oct 2026 18:19:35 -0400 Subject: [PATCH] Stoat: a read told soon after another is told when the wait is up, not dropped; the spoiler mark in the file tray; the probe; nobilis pointer Co-Authored-By: Claude Sonnet 5.5 --- nobilis | 2 +- scripts/probe-stoat-manage.mjs | 12 ++++++++++++ src/renderer/src/components/Composer.tsx | 4 ++-- src/renderer/src/state/store.ts | 19 ++++++++++++++++++- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/nobilis b/nobilis index 9cc8e8b..9945800 160000 --- a/nobilis +++ b/nobilis @@ -1 +1 @@ -Subproject commit 9cc8e8b4d2079e7b778a4f8a60489ca446f2ae76 +Subproject commit 9945800375e78c2b7c24690b7bb9407a90dbc98f diff --git a/scripts/probe-stoat-manage.mjs b/scripts/probe-stoat-manage.mjs index d31114d..6429018 100644 --- a/scripts/probe-stoat-manage.mjs +++ b/scripts/probe-stoat-manage.mjs @@ -259,6 +259,18 @@ try { check('and bob’s alongside it, and taken away again, leave the count right', (await tally())?.count === 1 && (await tally())?.me === false, JSON.stringify(await tally())) await as('bob', 'DELETE', `/channels/${channelId.General}/messages/${counted._id}`).catch(() => {}) + // --- Reading here is reading there: what arrives in the channel on screen is told to Stoat as read, even two in a few seconds. + await page.call('Emulation.setFocusEmulationEnabled', { enabled: true }) + await ev(`window.__mohoShots.store.selectBuffer(${JSON.stringify(general)})`) + await sleep(2500) + const lastRead = async () => (await as('alice', 'GET', '/sync/unreads')).find((u) => u._id.channel === channelId.General)?.last_id + const first = await as('bob', 'POST', `/channels/${channelId.General}/messages`, { content: 'read me once' }) + await sleep(2000) + const second = await as('bob', 'POST', `/channels/${channelId.General}/messages`, { content: 'read me twice' }) + check('a message that arrives in the open channel is told to Stoat as read, and a second soon after is too', !!(await until(async () => (await lastRead()) === second._id, 15000)), JSON.stringify([first._id, second._id, await lastRead()])) + await as('bob', 'DELETE', `/channels/${channelId.General}/messages/${first._id}`).catch(() => {}) + await as('bob', 'DELETE', `/channels/${channelId.General}/messages/${second._id}`).catch(() => {}) + // --- An emoji from a server this account is not in is still a picture. const away = await as('bob', 'POST', '/servers/create', { name: `Elsewhere ${Date.now().toString(36).slice(-4)}` }) const awayServer = away.server?._id ?? away._id diff --git a/src/renderer/src/components/Composer.tsx b/src/renderer/src/components/Composer.tsx index af7064b..27f22ee 100644 --- a/src/renderer/src/components/Composer.tsx +++ b/src/renderer/src/components/Composer.tsx @@ -39,7 +39,7 @@ interface StagedAttachment { preview?: string /** In bytes, once it has been asked. */ size?: number | null - /** Sent hidden behind a spoiler: Discord and Steam. */ + /** Sent hidden behind a spoiler: Discord, Steam, Telegram and Stoat. */ spoiler: boolean } @@ -1105,7 +1105,7 @@ export function Composer({ thread = false }: { thread?: boolean } = {}): JSX.Ele {/* On the card's corner, and there only while it is pointed at or focused - they would be a dozen buttons otherwise. */}
- {(service === 'discord' || service === 'steam' || service === 'telegram') && ( + {(service === 'discord' || service === 'steam' || service === 'telegram' || service === 'stoat') && (