A pin you click is a pin you get to
Clicking a pinned message jumped straight to a row that was usually not on screen - a pin is the oldest thing in most conversations, so it was the one click in the panel that did nothing at all. It now takes the path a search result takes, and says so when it cannot get there rather than going quiet. That path no longer stops at the end of local history either: where paging back runs out, it asks the service for the part of the conversation the message is in and pages once more. Nothing exists between that window and what is already on screen, so one page reaches it however old it is. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
+1
-1
Submodule nobilis updated: 70911bbd03...b5cc7fd50a
@@ -306,8 +306,16 @@ function PinnedMessages({ buffer }: { buffer: BufferEntry }): JSX.Element | null
|
||||
type="button"
|
||||
className="history-row"
|
||||
onClick={() => {
|
||||
store.setJumpTarget(message.id)
|
||||
setOpen(false)
|
||||
// Through the same path a search result takes, rather than
|
||||
// straight to the jump: a pin is usually the oldest thing in
|
||||
// the conversation, so it is the least likely message to
|
||||
// already be on screen - and it used to be the one click that
|
||||
// did nothing at all.
|
||||
void store.jumpToMessage(buffer.id, message.id).then((there) => {
|
||||
if (there) store.setJumpTarget(message.id)
|
||||
else store.toast('info', 'That message could not be reached')
|
||||
})
|
||||
}}
|
||||
>
|
||||
<span className="small">
|
||||
|
||||
@@ -2324,12 +2324,40 @@ export class ChatStore {
|
||||
const before = (this.state.messagesByBuffer[bufferId] || []).length
|
||||
await this.loadMoreHistory(bufferId)
|
||||
if (loaded()) return true
|
||||
// Nothing came back, so there is nothing older to find it in.
|
||||
if ((this.state.messagesByBuffer[bufferId] || []).length === before) return false
|
||||
// Nothing came back: either the store has been read to its beginning, or
|
||||
// the message is far enough back that paging to it is not a wait but a
|
||||
// refusal. Both are the moment to ask the service for that one part of
|
||||
// the conversation instead - a pin is routinely years older than
|
||||
// anything kept here, and it was still worth listing.
|
||||
if ((this.state.messagesByBuffer[bufferId] || []).length === before) {
|
||||
return await this.fetchAround(bufferId, messageId)
|
||||
}
|
||||
}
|
||||
return loaded()
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks the service for the part of the conversation one message is in.
|
||||
*
|
||||
* Then pages once more rather than rendering the fetched window directly:
|
||||
* the daemon has put those messages in the same store everything else is
|
||||
* read from, so the ordinary load-more path picks them up - and because
|
||||
* nothing exists between them and what is already on screen, one page
|
||||
* reaches them however old they are.
|
||||
*/
|
||||
private async fetchAround(bufferId: string, messageId: string): Promise<boolean> {
|
||||
try {
|
||||
await window.moho.rpc<{ ts: number }>('loadMessageContext', { bufferId, messageId })
|
||||
} catch (e) {
|
||||
// Said rather than swallowed: "nothing happened when I clicked it" is
|
||||
// the complaint this whole path exists to answer.
|
||||
this.toast('error', `Couldn't reach that message: ${(e as Error).message}`)
|
||||
return false
|
||||
}
|
||||
await this.loadMoreHistory(bufferId)
|
||||
return (this.state.messagesByBuffer[bufferId] || []).some((m) => m.id === messageId)
|
||||
}
|
||||
|
||||
async loadMoreHistory(bufferId: string): Promise<void> {
|
||||
if (this.state.loadingMore[bufferId]) return
|
||||
const list = this.state.messagesByBuffer[bufferId] || []
|
||||
|
||||
Reference in New Issue
Block a user