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 <[email protected]>
This commit is contained in:
1 parent
2a966c533c
commit
ccf86fe5ec
4 files changed
+33
-4
No files matched your search
+1
-1
Submodule nobilis updated: 9cc8e8b4d2...9945800375.
@@ -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
|
||||
|
||||
@@ -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. */}
|
||||
<div className="staged-actions">
|
||||
{(service === 'discord' || service === 'steam' || service === 'telegram') && (
|
||||
{(service === 'discord' || service === 'steam' || service === 'telegram' || service === 'stoat') && (
|
||||
<button
|
||||
type="button"
|
||||
className={classes('staged-action', att.spoiler && 'on')}
|
||||
|
||||
@@ -2734,11 +2734,28 @@ export class ChatStore {
|
||||
ackIfReading(bufferId: string): void {
|
||||
if (bufferId !== this.state.activeBufferId || !this.windowIsActive()) return
|
||||
const now = Date.now()
|
||||
if (now - (this.ackedAt.get(bufferId) ?? 0) < 5000) return
|
||||
const wait = 5000 - (now - (this.ackedAt.get(bufferId) ?? 0))
|
||||
if (wait > 0) {
|
||||
// Too soon after the last: said when the few seconds are up instead of never. A message that arrived inside them is
|
||||
// the newest, and without this it was left unread on the phone until another one came.
|
||||
if (!this.ackLater.has(bufferId)) {
|
||||
this.ackLater.set(
|
||||
bufferId,
|
||||
setTimeout(() => {
|
||||
this.ackLater.delete(bufferId)
|
||||
this.ackIfReading(bufferId)
|
||||
}, wait + 50)
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
this.ackedAt.set(bufferId, now)
|
||||
bestEffort(this.ackRead(bufferId), 'ack read')
|
||||
}
|
||||
|
||||
/** A conversation's turn to be told is read that came too soon after the last, waiting for it. */
|
||||
private ackLater = new Map<string, ReturnType<typeof setTimeout>>()
|
||||
|
||||
private windowIsActive(): boolean {
|
||||
return document.visibilityState === 'visible' && document.hasFocus()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user