scope doom scroll to current directory when no filters active
When no filters are selected, doom scroll now recursively fetches only items under the current directory instead of the entire library root. Navigating to a new directory invalidates the cached listing. Filter- based doom scroll (search or tags) continues to search library-wide. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,9 @@ export default function MixedView({ libraryId, initialPath }: Props) {
|
|||||||
const [recursiveLoaded, setRecursiveLoaded] = useState(false)
|
const [recursiveLoaded, setRecursiveLoaded] = useState(false)
|
||||||
const [doomScrollActive, setDoomScrollActive] = useState(false)
|
const [doomScrollActive, setDoomScrollActive] = useState(false)
|
||||||
const [doomScrollLoading, setDoomScrollLoading] = useState(false)
|
const [doomScrollLoading, setDoomScrollLoading] = useState(false)
|
||||||
|
const [doomScrollEntries, setDoomScrollEntries] = useState<FileEntry[]>([])
|
||||||
|
const [doomScrollEntriesLoading, setDoomScrollEntriesLoading] = useState(false)
|
||||||
|
const [doomScrollEntriesLoaded, setDoomScrollEntriesLoaded] = useState(false)
|
||||||
|
|
||||||
const toggleTag = (tagId: string) =>
|
const toggleTag = (tagId: string) =>
|
||||||
setSelectedTagIds((prev) => {
|
setSelectedTagIds((prev) => {
|
||||||
@@ -71,6 +74,14 @@ export default function MixedView({ libraryId, initialPath }: Props) {
|
|||||||
loadPath(initialPath)
|
loadPath(initialPath)
|
||||||
}, [loadPath, initialPath])
|
}, [loadPath, initialPath])
|
||||||
|
|
||||||
|
// Invalidate doom scroll entry cache when the user navigates to a different directory
|
||||||
|
useEffect(() => {
|
||||||
|
setDoomScrollEntries([])
|
||||||
|
setDoomScrollEntriesLoaded(false)
|
||||||
|
setDoomScrollEntriesLoading(false)
|
||||||
|
setDoomScrollLoading(false)
|
||||||
|
}, [currentPath])
|
||||||
|
|
||||||
const fetchAssignments = useCallback(() => {
|
const fetchAssignments = useCallback(() => {
|
||||||
fetch(`/api/tags/library-assignments?libraryId=${encodeURIComponent(libraryId)}`)
|
fetch(`/api/tags/library-assignments?libraryId=${encodeURIComponent(libraryId)}`)
|
||||||
.then((r) => r.json())
|
.then((r) => r.json())
|
||||||
@@ -95,6 +106,21 @@ export default function MixedView({ libraryId, initialPath }: Props) {
|
|||||||
.finally(() => setRecursiveLoading(false))
|
.finally(() => setRecursiveLoading(false))
|
||||||
}, [libraryId, recursiveLoaded, recursiveLoading])
|
}, [libraryId, recursiveLoaded, recursiveLoading])
|
||||||
|
|
||||||
|
const fetchDoomScrollEntries = useCallback(() => {
|
||||||
|
if (doomScrollEntriesLoaded || doomScrollEntriesLoading) return
|
||||||
|
setDoomScrollEntriesLoading(true)
|
||||||
|
fetch(
|
||||||
|
`/api/browse?libraryId=${encodeURIComponent(libraryId)}&path=${encodeURIComponent(currentPath)}&recursive=true`
|
||||||
|
)
|
||||||
|
.then((r) => r.json())
|
||||||
|
.then((data: DirectoryListing) => {
|
||||||
|
setDoomScrollEntries(data.entries)
|
||||||
|
setDoomScrollEntriesLoaded(true)
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
.finally(() => setDoomScrollEntriesLoading(false))
|
||||||
|
}, [libraryId, currentPath, doomScrollEntriesLoaded, doomScrollEntriesLoading])
|
||||||
|
|
||||||
// Fetch the full recursive listing the first time any filter becomes active
|
// Fetch the full recursive listing the first time any filter becomes active
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!filtersActive) return
|
if (!filtersActive) return
|
||||||
@@ -182,25 +208,33 @@ export default function MixedView({ libraryId, initialPath }: Props) {
|
|||||||
fetchRecursive()
|
fetchRecursive()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (recursiveLoaded) {
|
// No filters: scope to current directory
|
||||||
|
if (doomScrollEntriesLoaded) {
|
||||||
setDoomScrollActive(true)
|
setDoomScrollActive(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setDoomScrollLoading(true)
|
setDoomScrollLoading(true)
|
||||||
fetchRecursive()
|
fetchDoomScrollEntries()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activate doom scroll once the recursive listing finishes loading (when triggered by button)
|
// Activate doom scroll once the appropriate listing finishes loading (when triggered by button)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (doomScrollLoading && !recursiveLoading && recursiveLoaded) {
|
if (!doomScrollLoading) return
|
||||||
|
const filtersDone = filtersActive && !recursiveLoading && recursiveLoaded
|
||||||
|
const noFiltersDone = !filtersActive && !doomScrollEntriesLoading && doomScrollEntriesLoaded
|
||||||
|
if (filtersDone || noFiltersDone) {
|
||||||
setDoomScrollLoading(false)
|
setDoomScrollLoading(false)
|
||||||
setDoomScrollActive(true)
|
setDoomScrollActive(true)
|
||||||
}
|
}
|
||||||
}, [doomScrollLoading, recursiveLoading, recursiveLoaded])
|
}, [
|
||||||
|
doomScrollLoading, filtersActive,
|
||||||
|
recursiveLoading, recursiveLoaded,
|
||||||
|
doomScrollEntriesLoading, doomScrollEntriesLoaded,
|
||||||
|
])
|
||||||
|
|
||||||
// When filters are active, doom scroll uses filteredEntries (already filtered by search/tags).
|
// When filters are active, doom scroll uses filteredEntries (already filtered by search/tags).
|
||||||
// When no filters, doom scroll uses the full recursiveEntries.
|
// When no filters, doom scroll uses files recursively under the current directory.
|
||||||
const doomScrollItems: DoomScrollItem[] = (filtersActive ? filteredEntries : recursiveEntries)
|
const doomScrollItems: DoomScrollItem[] = (filtersActive ? filteredEntries : doomScrollEntries)
|
||||||
.filter((e) => e.type === 'file' && (e.mediaType === 'video' || e.mediaType === 'image') && e.url && isBrowserPlayable(e.name))
|
.filter((e) => e.type === 'file' && (e.mediaType === 'video' || e.mediaType === 'image') && e.url && isBrowserPlayable(e.name))
|
||||||
.map((e) => ({ url: e.url!, name: e.name, mediaType: e.mediaType as 'video' | 'image' }))
|
.map((e) => ({ url: e.url!, name: e.name, mediaType: e.mediaType as 'video' | 'image' }))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user