fix: include room ID in message permalink for cross-room navigation
Links now use #roomId/messageHash format so the app can load the correct room before scrolling to the target message. Handles hashchange events and auto-navigates on page load. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2e1a0ac858
commit
7210acf032
@ -190,10 +190,9 @@
|
||||
// Register global 401 handler so any expired-token API call triggers logout
|
||||
setOnUnauthorized(() => this.handleLogout())
|
||||
|
||||
// Listen for hash changes to scroll to linked messages
|
||||
// Listen for hash changes to navigate to linked messages
|
||||
this._onHashChange = () => {
|
||||
const hash = window.location.hash?.slice(1)
|
||||
if (hash) this.scrollToHash(hash)
|
||||
this.navigateToMessageLink()
|
||||
}
|
||||
window.addEventListener('hashchange', this._onHashChange)
|
||||
|
||||
@ -365,6 +364,9 @@
|
||||
|
||||
// Process any pending invite token
|
||||
await this.processInviteToken()
|
||||
|
||||
// Check for a message permalink in the URL hash (e.g. #roomId/messageHash)
|
||||
this.navigateToMessageLink()
|
||||
},
|
||||
|
||||
handleLogin(data) {
|
||||
@ -408,14 +410,7 @@
|
||||
typingUsers: [],
|
||||
})
|
||||
ws.joinRoom(roomId)
|
||||
|
||||
// Check for hash in URL to scroll to a specific message
|
||||
const targetHash = window.location.hash?.slice(1)
|
||||
if (targetHash) {
|
||||
this.scrollToHash(targetHash)
|
||||
} else {
|
||||
this.scrollToBottom()
|
||||
}
|
||||
this.scrollToBottom()
|
||||
} catch (e) {
|
||||
console.error('Failed to load room:', e)
|
||||
}
|
||||
@ -504,12 +499,35 @@
|
||||
})
|
||||
},
|
||||
|
||||
/** Parse #roomId/messageHash from URL, load the room, and scroll to the message */
|
||||
async navigateToMessageLink() {
|
||||
const fragment = window.location.hash?.slice(1)
|
||||
if (!fragment) return
|
||||
const slashIdx = fragment.indexOf('/')
|
||||
if (slashIdx === -1) return // not a room/hash link
|
||||
|
||||
const roomId = fragment.slice(0, slashIdx)
|
||||
const msgHash = fragment.slice(slashIdx + 1)
|
||||
if (!roomId || !msgHash) return
|
||||
|
||||
// Store the target hash before selecting the room
|
||||
this._pendingScrollHash = msgHash
|
||||
|
||||
// Select the room if not already active
|
||||
if (this.state.activeRoomId !== roomId) {
|
||||
await this.selectRoom(roomId)
|
||||
}
|
||||
|
||||
// Scroll to the message after render
|
||||
this.scrollToHash(this._pendingScrollHash)
|
||||
this._pendingScrollHash = null
|
||||
},
|
||||
|
||||
scrollToHash(hash) {
|
||||
requestAnimationFrame(() => {
|
||||
const el = document.getElementById('msg-' + hash)
|
||||
if (el) {
|
||||
el.scrollIntoView({ behavior: 'smooth', block: 'center' })
|
||||
// Briefly highlight the message
|
||||
el.classList.add('hash-highlight')
|
||||
setTimeout(() => el.classList.remove('hash-highlight'), 3000)
|
||||
}
|
||||
|
||||
@ -478,7 +478,9 @@
|
||||
e.stopPropagation()
|
||||
const hash = this.props.message?.hash
|
||||
if (!hash) return
|
||||
const url = `${window.location.origin}${window.location.pathname}#${hash}`
|
||||
const roomId = this.props.message?.room_id
|
||||
if (!roomId) return
|
||||
const url = `${window.location.origin}${window.location.pathname}#${roomId}/${hash}`
|
||||
const btn = e.currentTarget
|
||||
navigator.clipboard.writeText(url).then(() => {
|
||||
btn.classList.add('copied')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user