Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { useInboxReportSelectionStore } from "@features/inbox/stores/inboxReport
import { useInboxSignalsFilterStore } from "@features/inbox/stores/inboxSignalsFilterStore";
import { useInboxSignalsSidebarStore } from "@features/inbox/stores/inboxSignalsSidebarStore";
import { useInboxSourcesDialogStore } from "@features/inbox/stores/inboxSourcesDialogStore";
import { getEffectiveBulkSelectionIds } from "@features/inbox/utils/bulkSelection";
import {
buildSignalReportListOrdering,
buildStatusFilterParam,
Expand Down Expand Up @@ -110,11 +111,26 @@ export function InboxSignalsTab() {
const selectedReportIds = useInboxReportSelectionStore(
(s) => s.selectedReportIds ?? [],
);
const setSelectedReportIds = useInboxReportSelectionStore(
(s) => s.setSelectedReportIds,
);
const toggleReportSelection = useInboxReportSelectionStore(
(s) => s.toggleReportSelection,
);
const pruneSelection = useInboxReportSelectionStore((s) => s.pruneSelection);

// When true, an empty store means "nothing selected" — no virtual fallback.
// Set once the user first explicitly interacts with any checkbox.
// Resets when the open report changes while the store is still empty (fresh report).
const [selectionExplicitlyActivated, setSelectionExplicitlyActivated] =
useState(false);

// Stable refs so callbacks don't need re-registration on every render
const selectedReportIdsRef = useRef(selectedReportIds);
selectedReportIdsRef.current = selectedReportIds;
const selectionExplicitlyActivatedRef = useRef(false);
selectionExplicitlyActivatedRef.current = selectionExplicitlyActivated;

useEffect(() => {
if (reports.length === 0) {
setSelectedReportId(null);
Expand All @@ -135,11 +151,79 @@ export function InboxSignalsTab() {
pruneSelection(reports.map((report) => report.id));
}, [reports, pruneSelection]);

// Reset to virtual mode when a different report is opened while the store is empty.
// selectedReportIdsRef is read (not declared) in the callback — biome can't see it
// depends on selectedReportId, so the dep is intentional.
// biome-ignore lint/correctness/useExhaustiveDependencies: selectedReportId is the trigger; store length is read via a ref to avoid adding it as a dep
useEffect(() => {
if (selectedReportIdsRef.current.length === 0) {
setSelectionExplicitlyActivated(false);
}
}, [selectedReportId]);

const selectedReport = useMemo(
() => reports.find((report) => report.id === selectedReportId) ?? null,
[reports, selectedReportId],
);

const effectiveBulkIds = useMemo(
() =>
getEffectiveBulkSelectionIds(
selectedReportIds,
selectedReportId,
selectionExplicitlyActivated,
),
[selectedReportIds, selectedReportId, selectionExplicitlyActivated],
);

// Toggle a report's checkbox, handling the virtual → explicit mode transition.
// When the first explicit toggle happens in virtual mode (store empty, a report is open):
// - toggling a DIFFERENT report: seed the open report into the store too (keep it checked)
// - toggling the OPEN report itself: transition to explicit-empty (uncheck it)
const handleToggleReportSelection = useCallback(
(reportId: string) => {
if (
!selectionExplicitlyActivatedRef.current &&
selectedReportIdsRef.current.length === 0
) {
setSelectionExplicitlyActivated(true);
if (
selectedReportIdRef.current !== null &&
reportId !== selectedReportIdRef.current
) {
// Seed the open report + add the newly toggled one
setSelectedReportIds([selectedReportIdRef.current, reportId]);
}
// If toggling the open report's own checkbox, the store stays empty
// and explicit = true → effective = [] (it becomes unchecked)
} else {
toggleReportSelection(reportId);
}
},
[setSelectedReportIds, toggleReportSelection],
);

// Handle the select-all checkbox. Parent owns all state transitions.
const handleToggleSelectAll = useCallback(
(checked: boolean) => {
if (checked) {
setSelectedReportIds(reportsRef.current.map((r) => r.id));
setSelectionExplicitlyActivated(true);
} else {
setSelectedReportIds([]);
if (!selectionExplicitlyActivatedRef.current) {
// Was in virtual mode (open report only virtually selected):
// close the report so there is truly nothing selected.
setSelectedReportId(null);
setSelectionExplicitlyActivated(false);
}
// If already in explicit mode, keep the flag true so the empty store
// means nothing selected — no fallback to the virtual open report.
}
},
[setSelectedReportIds],
);

// ── Sidebar resize ─────────────────────────────────────────────────────
const sidebarWidth = useInboxSignalsSidebarStore((state) => state.width);
const sidebarIsResizing = useInboxSignalsSidebarStore(
Expand Down Expand Up @@ -279,14 +363,17 @@ export function InboxSignalsTab() {
} else if (e.key === "ArrowUp") {
e.preventDefault();
navigateReport(-1);
} else if (e.key === " " && selectedReportIdRef.current) {
} else if (
(e.key === " " || e.key === "Enter") &&
selectedReportIdRef.current
) {
e.preventDefault();
toggleReportSelection(selectedReportIdRef.current);
handleToggleReportSelection(selectedReportIdRef.current);
}
};
window.addEventListener("keydown", handler);
return () => window.removeEventListener("keydown", handler);
}, [navigateReport, toggleReportSelection]);
}, [navigateReport, handleToggleReportSelection]);

const searchDisabledReason =
!hasReports && !searchQuery.trim()
Expand Down Expand Up @@ -381,6 +468,8 @@ export function InboxSignalsTab() {
readyCount={readyCount}
processingCount={processingCount}
reports={reports}
effectiveBulkIds={effectiveBulkIds}
onToggleSelectAll={handleToggleSelectAll}
/>
</Box>
<ReportListPane
Expand All @@ -397,9 +486,9 @@ export function InboxSignalsTab() {
searchQuery={searchQuery}
hasActiveFilters={hasActiveFilters}
selectedReportId={selectedReportId}
selectedReportIds={selectedReportIds}
selectedReportIds={effectiveBulkIds}
onSelectReport={setSelectedReportId}
onToggleReportSelection={toggleReportSelection}
onToggleReportSelection={handleToggleReportSelection}
/>
</Flex>
</ScrollArea>
Expand Down
Loading
Loading