Merge pull request #3 from Hona/fix/virtual-timeline-cache-1778638381
fix(app): restore virtual timeline cache
This commit is contained in:
commit
5c0d9ed030
1 changed files with 48 additions and 0 deletions
|
|
@ -106,6 +106,23 @@ function sameKeys(a: readonly string[] | undefined, b: readonly string[] | undef
|
||||||
return a.every((key, index) => key === b[index])
|
return a.every((key, index) => key === b[index])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const timelineCacheLimit = 16
|
||||||
|
const timelineCache = new Map<string, { keys: readonly string[]; cache: VirtualizerHandle["cache"] }>()
|
||||||
|
|
||||||
|
function readTimelineCache(id: string, keys: readonly string[]) {
|
||||||
|
const entry = timelineCache.get(id)
|
||||||
|
if (!entry) return
|
||||||
|
if (sameKeys(entry.keys, keys)) return entry.cache
|
||||||
|
timelineCache.delete(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeTimelineCache(id: string, keys: readonly string[], handle: VirtualizerHandle | undefined) {
|
||||||
|
if (!handle || keys.length === 0) return
|
||||||
|
timelineCache.delete(id)
|
||||||
|
timelineCache.set(id, { keys: keys.slice(), cache: handle.cache })
|
||||||
|
while (timelineCache.size > timelineCacheLimit) timelineCache.delete(timelineCache.keys().next().value!)
|
||||||
|
}
|
||||||
|
|
||||||
function samePartGroup(a: PartGroup, b: PartGroup) {
|
function samePartGroup(a: PartGroup, b: PartGroup) {
|
||||||
if (a === b) return true
|
if (a === b) return true
|
||||||
if (a.key !== b.key) return false
|
if (a.key !== b.key) return false
|
||||||
|
|
@ -664,6 +681,7 @@ export function MessageTimeline(props: {
|
||||||
return reuseTimelineRows(previous, [...rows, { key: "bottom-spacer", type: "bottom-spacer" }])
|
return reuseTimelineRows(previous, [...rows, { key: "bottom-spacer", type: "bottom-spacer" }])
|
||||||
})
|
})
|
||||||
const timelineRowKeys = createMemo(() => timelineRows().map((row) => row.key), [] as string[], { equals: sameKeys })
|
const timelineRowKeys = createMemo(() => timelineRows().map((row) => row.key), [] as string[], { equals: sameKeys })
|
||||||
|
const virtualCache = createMemo(() => readTimelineCache(sessionKey(), timelineRowKeys()))
|
||||||
const timelineRowByKey = createMemo(() => new Map(timelineRows().map((row) => [row.key, row] as const)))
|
const timelineRowByKey = createMemo(() => new Map(timelineRows().map((row) => [row.key, row] as const)))
|
||||||
const messageRowIndex = createMemo(() => {
|
const messageRowIndex = createMemo(() => {
|
||||||
const result = new Map<string, number>()
|
const result = new Map<string, number>()
|
||||||
|
|
@ -691,7 +709,29 @@ export function MessageTimeline(props: {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let cacheSessionKey = sessionKey()
|
||||||
|
let cacheRowKeys = timelineRowKeys()
|
||||||
|
let virtualizerSessionKey = cacheSessionKey
|
||||||
|
let virtualizerRowKeys = cacheRowKeys
|
||||||
|
|
||||||
|
createEffect(
|
||||||
|
on(
|
||||||
|
() => [sessionKey(), timelineRowKeys()] as const,
|
||||||
|
(next, prev) => {
|
||||||
|
if (prev && prev[0] !== next[0]) writeTimelineCache(prev[0], prev[1], virtualizer)
|
||||||
|
cacheSessionKey = next[0]
|
||||||
|
cacheRowKeys = next[1]
|
||||||
|
if (virtualizer) {
|
||||||
|
virtualizerSessionKey = cacheSessionKey
|
||||||
|
virtualizerRowKeys = cacheRowKeys
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ defer: true },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
onCleanup(() => {
|
onCleanup(() => {
|
||||||
|
writeTimelineCache(virtualizerSessionKey, virtualizerRowKeys, virtualizer)
|
||||||
props.setRevealMessage?.(() => {})
|
props.setRevealMessage?.(() => {})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -1628,11 +1668,19 @@ export function MessageTimeline(props: {
|
||||||
{(root) => (
|
{(root) => (
|
||||||
<Virtualizer
|
<Virtualizer
|
||||||
data={timelineRowKeys()}
|
data={timelineRowKeys()}
|
||||||
|
cache={virtualCache()}
|
||||||
scrollRef={root()}
|
scrollRef={root()}
|
||||||
shift={props.historyShift}
|
shift={props.historyShift}
|
||||||
keepMounted={keepMounted()}
|
keepMounted={keepMounted()}
|
||||||
ref={(handle) => {
|
ref={(handle) => {
|
||||||
|
if (!handle) {
|
||||||
|
writeTimelineCache(virtualizerSessionKey, virtualizerRowKeys, virtualizer)
|
||||||
|
virtualizer = undefined
|
||||||
|
return
|
||||||
|
}
|
||||||
virtualizer = handle
|
virtualizer = handle
|
||||||
|
virtualizerSessionKey = cacheSessionKey
|
||||||
|
virtualizerRowKeys = cacheRowKeys
|
||||||
scheduleContentRoot(root())
|
scheduleContentRoot(root())
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue