fix: keep reading bookmarks bound to route
This commit is contained in:
@@ -43,7 +43,7 @@
|
||||
import { computed, nextTick, ref, onMounted, onUnmounted, watch } from 'vue'
|
||||
import { useRoute } from 'vitepress'
|
||||
import {
|
||||
createReadingBookmark,
|
||||
createReadingBookmarkSnapshot,
|
||||
readReadingBookmark,
|
||||
writeReadingBookmark
|
||||
} from '../utils/readingBookmark.js'
|
||||
@@ -125,24 +125,40 @@ const progressTitle = computed(() =>
|
||||
: `${bookmarkTitle.value} · 阅读进度 ${progress.value}%`
|
||||
)
|
||||
|
||||
const saveBookmark = () => {
|
||||
const clearBookmarkSaveTimer = () => {
|
||||
if (saveTimer) {
|
||||
window.clearTimeout(saveTimer)
|
||||
saveTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
const clearClickSaveTimer = () => {
|
||||
if (clickSaveTimer) {
|
||||
window.clearTimeout(clickSaveTimer)
|
||||
clickSaveTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
const saveBookmark = (path = currentPath()) => {
|
||||
writeReadingBookmark(
|
||||
getClientStorage(),
|
||||
createReadingBookmark({
|
||||
path: currentPath(),
|
||||
title: articleTitle.value,
|
||||
section: activeSection.value,
|
||||
scrollY: window.scrollY,
|
||||
progress: progress.value
|
||||
createReadingBookmarkSnapshot({
|
||||
path,
|
||||
getTitle: () => articleTitle.value,
|
||||
getSection: () => activeSection.value,
|
||||
getScrollY: () => window.scrollY,
|
||||
getProgress: () => progress.value
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const scheduleBookmarkSave = () => {
|
||||
if (saveTimer) {
|
||||
window.clearTimeout(saveTimer)
|
||||
}
|
||||
saveTimer = window.setTimeout(saveBookmark, 180)
|
||||
const path = currentPath()
|
||||
clearBookmarkSaveTimer()
|
||||
saveTimer = window.setTimeout(() => {
|
||||
saveTimer = null
|
||||
saveBookmark(path)
|
||||
}, 180)
|
||||
}
|
||||
|
||||
const updateProgress = () => {
|
||||
@@ -325,12 +341,12 @@ const handleClick = () => {
|
||||
behavior: 'smooth'
|
||||
})
|
||||
|
||||
if (clickSaveTimer) {
|
||||
window.clearTimeout(clickSaveTimer)
|
||||
}
|
||||
const path = currentPath()
|
||||
clearClickSaveTimer()
|
||||
clickSaveTimer = window.setTimeout(() => {
|
||||
clickSaveTimer = null
|
||||
updateProgress()
|
||||
saveBookmark()
|
||||
saveBookmark(path)
|
||||
}, 400)
|
||||
}
|
||||
|
||||
@@ -344,15 +360,11 @@ onUnmounted(() => {
|
||||
if (scrollTimer) {
|
||||
clearTimeout(scrollTimer)
|
||||
}
|
||||
if (saveTimer) {
|
||||
clearTimeout(saveTimer)
|
||||
}
|
||||
clearBookmarkSaveTimer()
|
||||
if (restoreTimer) {
|
||||
clearTimeout(restoreTimer)
|
||||
}
|
||||
if (clickSaveTimer) {
|
||||
clearTimeout(clickSaveTimer)
|
||||
}
|
||||
clearClickSaveTimer()
|
||||
// 清理拖拽事件
|
||||
document.removeEventListener('mousemove', onDrag)
|
||||
document.removeEventListener('mouseup', endDrag)
|
||||
@@ -366,6 +378,8 @@ onUnmounted(() => {
|
||||
watch(
|
||||
() => route.path,
|
||||
() => {
|
||||
clearBookmarkSaveTimer()
|
||||
clearClickSaveTimer()
|
||||
resetRouteState()
|
||||
restoreBookmark()
|
||||
}
|
||||
|
||||
@@ -27,6 +27,24 @@ export const createReadingBookmark = ({
|
||||
updatedAt: now()
|
||||
})
|
||||
|
||||
|
||||
export const createReadingBookmarkSnapshot = ({
|
||||
path,
|
||||
getTitle = () => '',
|
||||
getSection = () => '',
|
||||
getScrollY = () => 0,
|
||||
getProgress = () => 0,
|
||||
now = () => Date.now()
|
||||
}) =>
|
||||
createReadingBookmark({
|
||||
path,
|
||||
title: getTitle(),
|
||||
section: getSection(),
|
||||
scrollY: getScrollY(),
|
||||
progress: getProgress(),
|
||||
now
|
||||
})
|
||||
|
||||
const normalizeBookmark = (
|
||||
value,
|
||||
expectedPath,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { describe, it } from 'node:test'
|
||||
|
||||
import {
|
||||
createReadingBookmark,
|
||||
createReadingBookmarkSnapshot,
|
||||
getReadingBookmarkKey,
|
||||
readReadingBookmark,
|
||||
writeReadingBookmark
|
||||
@@ -62,6 +63,44 @@ describe('reading bookmarks', () => {
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
it('keeps delayed saves bound to the path captured before navigation', () => {
|
||||
const storage = createStorage()
|
||||
let currentPath = '/easy-vibe/zh-cn/page-a/'
|
||||
|
||||
const scheduledPath = currentPath
|
||||
currentPath = '/easy-vibe/zh-cn/page-b/'
|
||||
|
||||
writeReadingBookmark(
|
||||
storage,
|
||||
createReadingBookmarkSnapshot({
|
||||
path: scheduledPath,
|
||||
getTitle: () => '页面 A',
|
||||
getSection: () => '小节 A',
|
||||
getScrollY: () => 240,
|
||||
getProgress: () => 32,
|
||||
now: () => 777
|
||||
})
|
||||
)
|
||||
|
||||
assert.equal(
|
||||
readReadingBookmark(storage, currentPath, 1000),
|
||||
null
|
||||
)
|
||||
assert.deepEqual(
|
||||
readReadingBookmark(storage, scheduledPath, 1000),
|
||||
{
|
||||
version: 1,
|
||||
path: scheduledPath,
|
||||
title: '页面 A',
|
||||
section: '小节 A',
|
||||
scrollY: 240,
|
||||
progress: 32,
|
||||
updatedAt: 777
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it('normalizes invalid numeric values', () => {
|
||||
assert.deepEqual(
|
||||
createReadingBookmark({
|
||||
|
||||
Reference in New Issue
Block a user