Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion app/(dashboard)/browser/content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ObjectUploadPicker } from "@/components/object/upload-picker"
import { useBucket } from "@/hooks/use-bucket"
import { useMessage } from "@/lib/feedback/message"
import { buildBucketPath } from "@/lib/bucket-path"
import { useTasks } from "@/contexts/task-context"

interface BrowserContentProps {
bucketName: string
Expand Down Expand Up @@ -100,6 +101,37 @@ export function BrowserContent({ bucketName, keyPath = "", preview = false, prev
setRefreshTrigger((n) => n + 1)
}

const tasks = useTasks()
const debounceTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)
const prevCompletedIdsRef = React.useRef(new Set<string>())

React.useEffect(() => {
const currentIds = new Set(tasks.map((t) => t.id))
for (const id of prevCompletedIdsRef.current) {
if (!currentIds.has(id)) prevCompletedIdsRef.current.delete(id)
}
const completedForBucket = tasks.filter(
(t) =>
(t.kind === "upload" || t.kind === "delete") &&
t.bucketName === bucketName &&
t.status === "completed",
)
const newCompletions = completedForBucket.filter((t) => !prevCompletedIdsRef.current.has(t.id))
if (newCompletions.length > 0) {
newCompletions.forEach((t) => prevCompletedIdsRef.current.add(t.id))
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current)
debounceTimerRef.current = setTimeout(() => {
setRefreshTrigger((n) => n + 1)
}, 1500)
}
}, [tasks, bucketName, setRefreshTrigger])

React.useEffect(() => {
return () => {
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current)
}
}, [])
Comment on lines +127 to +133
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The debounce timer is only cleared on unmount (separate effect). If bucketName changes while a timer is pending (e.g., navigation within the same component instance), the scheduled callback can still fire and trigger a refresh unrelated to the new bucket state. Consider clearing any existing debounceTimerRef.current in the main effect cleanup (or whenever bucketName changes) so pending timers don’t leak across bucket switches/rerenders.

Suggested change
}, [tasks, bucketName, setRefreshTrigger])
React.useEffect(() => {
return () => {
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current)
}
}, [])
return () => {
if (debounceTimerRef.current) {
clearTimeout(debounceTimerRef.current)
debounceTimerRef.current = null
}
}
}, [tasks, bucketName, setRefreshTrigger])

Copilot uses AI. Check for mistakes.

return (
<Page>
<PageHeader>
Expand Down Expand Up @@ -152,7 +184,6 @@ export function BrowserContent({ bucketName, keyPath = "", preview = false, prev
onShowChange={setUploadPickerOpen}
bucketName={bucketName}
prefix={prefix}
onSuccess={handleRefresh}
/>
</Page>
)
Expand Down
2 changes: 0 additions & 2 deletions components/object/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,6 @@ export function ObjectList({
message.success(t("Delete task created"))
}
table.resetRowSelection()
;(onRefresh ?? fetchObjects)()
} catch (err) {
message.error((err as Error)?.message ?? t("Delete Failed"))
}
Expand All @@ -454,7 +453,6 @@ export function ObjectList({
message.success(t("Delete task created"))
}
table.resetRowSelection()
;(onRefresh ?? fetchObjects)()
} catch (err) {
message.error((err as Error)?.message ?? t("Delete Failed"))
}
Expand Down
1 change: 1 addition & 0 deletions contexts/task-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export type AnyTask = {
displayName: string
subInfo: string
actionLabel: string
bucketName?: string
}

const emptyTasks: AnyTask[] = []
Expand Down
Loading