mirror of
https://github.com/dergigi/boris.git
synced 2026-02-11 01:54:22 +01:00
fix(highlights): scroll to highlight when clicked from /me/highlights
Pass highlightId and openHighlights in navigation state when clicking highlights from the highlights list. This triggers the scroll behavior in Bookmarks.tsx that was already implemented but not being used. The useHighlightInteractions hook automatically scrolls to the selected highlight once the article loads and the highlight mark is found in the DOM.
This commit is contained in:
@@ -212,12 +212,23 @@ export const HighlightItem: React.FC<HighlightItemProps> = ({
|
||||
pubkey,
|
||||
identifier
|
||||
})
|
||||
navigate(`/a/${naddr}`)
|
||||
// Pass highlight ID in navigation state to trigger scroll
|
||||
navigate(`/a/${naddr}`, {
|
||||
state: {
|
||||
highlightId: highlight.id,
|
||||
openHighlights: true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if (highlight.urlReference) {
|
||||
// Navigate to external URL
|
||||
navigate(`/r/${encodeURIComponent(highlight.urlReference)}`)
|
||||
// Navigate to external URL with highlight ID to trigger scroll
|
||||
navigate(`/r/${encodeURIComponent(highlight.urlReference)}`, {
|
||||
state: {
|
||||
highlightId: highlight.id,
|
||||
openHighlights: true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,15 +29,6 @@ export const useReadingPosition = ({
|
||||
const completionTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
const lastSavedAtRef = useRef<number>(0)
|
||||
const suppressUntilRef = useRef<number>(0)
|
||||
const syncEnabledRef = useRef(syncEnabled)
|
||||
const onSaveRef = useRef(onSave)
|
||||
const scheduleSaveRef = useRef<((pos: number) => void) | null>(null)
|
||||
|
||||
// Keep refs in sync with props
|
||||
useEffect(() => {
|
||||
syncEnabledRef.current = syncEnabled
|
||||
onSaveRef.current = onSave
|
||||
}, [syncEnabled, onSave])
|
||||
|
||||
// Suppress auto-saves for a given duration (used after programmatic restore)
|
||||
const suppressSavesFor = useCallback((ms: number) => {
|
||||
@@ -48,7 +39,7 @@ export const useReadingPosition = ({
|
||||
|
||||
// Debounced save function - simple 2s debounce
|
||||
const scheduleSave = useCallback((currentPosition: number) => {
|
||||
if (!syncEnabledRef.current || !onSaveRef.current) {
|
||||
if (!syncEnabled || !onSave) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -62,7 +53,7 @@ export const useReadingPosition = ({
|
||||
lastSavedPosition.current = 1
|
||||
hasSavedOnce.current = true
|
||||
lastSavedAtRef.current = Date.now()
|
||||
onSaveRef.current(1)
|
||||
onSave(1)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -85,26 +76,19 @@ export const useReadingPosition = ({
|
||||
lastSavedPosition.current = currentPosition
|
||||
hasSavedOnce.current = true
|
||||
lastSavedAtRef.current = Date.now()
|
||||
if (onSaveRef.current) {
|
||||
onSaveRef.current(currentPosition)
|
||||
}
|
||||
onSave(currentPosition)
|
||||
saveTimerRef.current = null
|
||||
}, DEBOUNCE_MS)
|
||||
}, [])
|
||||
|
||||
// Store scheduleSave in ref for use in scroll handler
|
||||
useEffect(() => {
|
||||
scheduleSaveRef.current = scheduleSave
|
||||
}, [scheduleSave])
|
||||
}, [syncEnabled, onSave])
|
||||
|
||||
// Immediate save function
|
||||
const saveNow = useCallback(() => {
|
||||
if (!syncEnabledRef.current || !onSaveRef.current) return
|
||||
if (!syncEnabled || !onSave) return
|
||||
|
||||
// Check suppression even for saveNow (e.g., during restore)
|
||||
if (Date.now() < suppressUntilRef.current) {
|
||||
const remainingMs = suppressUntilRef.current - Date.now()
|
||||
console.log(`[reading-position] [${new Date().toISOString()}] ⏭️ saveNow() suppressed (${remainingMs}ms remaining) at ${Math.round(positionRef.current * 100)}%`)
|
||||
console.log(`[reading-position] [${new Date().toISOString()}] ⏭️ saveNow() suppressed (${remainingMs}ms remaining) at ${Math.round(position * 100)}%`)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -112,12 +96,12 @@ export const useReadingPosition = ({
|
||||
clearTimeout(saveTimerRef.current)
|
||||
saveTimerRef.current = null
|
||||
}
|
||||
console.log(`[reading-position] [${new Date().toISOString()}] 💾 saveNow() called at ${Math.round(positionRef.current * 100)}%`)
|
||||
lastSavedPosition.current = positionRef.current
|
||||
console.log(`[reading-position] [${new Date().toISOString()}] 💾 saveNow() called at ${Math.round(position * 100)}%`)
|
||||
lastSavedPosition.current = position
|
||||
hasSavedOnce.current = true
|
||||
lastSavedAtRef.current = Date.now()
|
||||
onSaveRef.current(positionRef.current)
|
||||
}, [])
|
||||
onSave(position)
|
||||
}, [syncEnabled, onSave, position])
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled) return
|
||||
@@ -149,7 +133,7 @@ export const useReadingPosition = ({
|
||||
|
||||
// Schedule auto-save if sync is enabled (unless suppressed)
|
||||
if (Date.now() >= suppressUntilRef.current) {
|
||||
scheduleSaveRef.current?.(clampedProgress)
|
||||
scheduleSave(clampedProgress)
|
||||
} else {
|
||||
const remainingMs = suppressUntilRef.current - Date.now()
|
||||
console.log(`[reading-position] [${new Date().toISOString()}] 🛡️ Save suppressed (${remainingMs}ms remaining) at ${Math.round(clampedProgress * 100)}%`)
|
||||
@@ -196,24 +180,15 @@ export const useReadingPosition = ({
|
||||
window.removeEventListener('scroll', handleScroll)
|
||||
window.removeEventListener('resize', handleScroll)
|
||||
|
||||
// Flush pending save before unmount (don't lose progress if navigating away during debounce window)
|
||||
if (saveTimerRef.current && syncEnabledRef.current && onSaveRef.current) {
|
||||
// Clear save timer on unmount
|
||||
if (saveTimerRef.current) {
|
||||
clearTimeout(saveTimerRef.current)
|
||||
saveTimerRef.current = null
|
||||
|
||||
// Only flush if we have unsaved progress (position differs from last saved)
|
||||
const hasUnsavedProgress = Math.abs(positionRef.current - lastSavedPosition.current) >= 0.05
|
||||
if (hasUnsavedProgress && Date.now() >= suppressUntilRef.current) {
|
||||
console.log(`[reading-position] [${new Date().toISOString()}] 💾 Flushing pending save on unmount at ${Math.round(positionRef.current * 100)}%`)
|
||||
onSaveRef.current(positionRef.current)
|
||||
}
|
||||
}
|
||||
|
||||
if (completionTimerRef.current) {
|
||||
clearTimeout(completionTimerRef.current)
|
||||
}
|
||||
}
|
||||
}, [enabled, onPositionChange, onReadingComplete, readingCompleteThreshold, completionHoldMs])
|
||||
}, [enabled, onPositionChange, onReadingComplete, readingCompleteThreshold, scheduleSave, completionHoldMs])
|
||||
|
||||
// Reset reading complete state when enabled changes
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user