ai-customization #22

Merged
gpatti merged 4 commits from ai-customization into main 2026-04-13 01:13:41 +00:00
Showing only changes of commit b0d146679f - Show all commits

View File

@@ -38,6 +38,9 @@ export default function MixedView({ libraryId, initialPath }: Props) {
const [recursiveLoaded, setRecursiveLoaded] = useState(false)
const [doomScrollActive, setDoomScrollActive] = 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) =>
setSelectedTagIds((prev) => {
@@ -71,6 +74,14 @@ export default function MixedView({ libraryId, initialPath }: Props) {
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(() => {
fetch(`/api/tags/library-assignments?libraryId=${encodeURIComponent(libraryId)}`)
.then((r) => r.json())
@@ -95,6 +106,21 @@ export default function MixedView({ libraryId, initialPath }: Props) {
.finally(() => setRecursiveLoading(false))
}, [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
useEffect(() => {
if (!filtersActive) return
@@ -182,25 +208,33 @@ export default function MixedView({ libraryId, initialPath }: Props) {
fetchRecursive()
return
}
if (recursiveLoaded) {
// No filters: scope to current directory
if (doomScrollEntriesLoaded) {
setDoomScrollActive(true)
return
}
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(() => {
if (doomScrollLoading && !recursiveLoading && recursiveLoaded) {
if (!doomScrollLoading) return
const filtersDone = filtersActive && !recursiveLoading && recursiveLoaded
const noFiltersDone = !filtersActive && !doomScrollEntriesLoading && doomScrollEntriesLoaded
if (filtersDone || noFiltersDone) {
setDoomScrollLoading(false)
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 no filters, doom scroll uses the full recursiveEntries.
const doomScrollItems: DoomScrollItem[] = (filtersActive ? filteredEntries : recursiveEntries)
// When no filters, doom scroll uses files recursively under the current directory.
const doomScrollItems: DoomScrollItem[] = (filtersActive ? filteredEntries : doomScrollEntries)
.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' }))