diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignatures.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignatures.tsx index 3800b871..3e880623 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignatures.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignatures.tsx @@ -16,6 +16,7 @@ import { SIGNATURE_DELETION_TIMEOUTS, } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts'; import { OutCommand, OutCommandHandler } from '@/hooks/Mapper/types/mapHandlers'; +import { ExtendedSystemSignature } from '@/hooks/Mapper/types'; /** * Custom hook for managing pending signature deletions and undo countdown. @@ -27,16 +28,32 @@ function useSignatureUndo( ) { const [countdown, setCountdown] = useState(0); const [pendingIds, setPendingIds] = useState>(new Set()); + const [deletedSignatures, setDeletedSignatures] = useState([]); const intervalRef = useRef(null); - const addDeleted = useCallback((ids: string[]) => { + const addDeleted = useCallback((signatures: ExtendedSystemSignature[]) => { + const newIds = signatures.map(sig => sig.eve_id); setPendingIds(prev => { const next = new Set(prev); - ids.forEach(id => next.add(id)); + newIds.forEach(id => next.add(id)); return next; }); + setDeletedSignatures(prev => [...prev, ...signatures]); }, []); + // Clear deleted signatures when system changes + useEffect(() => { + if (systemId) { + setDeletedSignatures([]); + setPendingIds(new Set()); + setCountdown(0); + if (intervalRef.current != null) { + clearInterval(intervalRef.current); + intervalRef.current = null; + } + } + }, [systemId]); + // kick off or clear countdown whenever pendingIds changes useEffect(() => { // clear any existing timer @@ -47,6 +64,7 @@ function useSignatureUndo( if (pendingIds.size === 0) { setCountdown(0); + setDeletedSignatures([]); return; } @@ -63,6 +81,7 @@ function useSignatureUndo( clearInterval(intervalRef.current!); intervalRef.current = null; setPendingIds(new Set()); + setDeletedSignatures([]); return 0; } return prev - 1; @@ -85,6 +104,7 @@ function useSignatureUndo( data: { system_id: systemId, eve_ids: Array.from(pendingIds) }, }); setPendingIds(new Set()); + setDeletedSignatures([]); setCountdown(0); if (intervalRef.current != null) { clearInterval(intervalRef.current); @@ -95,6 +115,7 @@ function useSignatureUndo( return { pendingIds, countdown, + deletedSignatures, addDeleted, handleUndo, }; @@ -118,7 +139,11 @@ export const SystemSignatures = () => { const [systemId] = selectedSystems; const isSystemSelected = useMemo(() => selectedSystems.length === 1, [selectedSystems.length]); - const { pendingIds, countdown, addDeleted, handleUndo } = useSignatureUndo(systemId, currentSettings, outCommand); + const { pendingIds, countdown, deletedSignatures, addDeleted, handleUndo } = useSignatureUndo( + systemId, + currentSettings, + outCommand, + ); useHotkey(true, ['z', 'Z'], (event: KeyboardEvent) => { if (pendingIds.size > 0 && countdown > 0) { @@ -175,6 +200,7 @@ export const SystemSignatures = () => { void; onCountChange?: (count: number) => void; filterSignature?: (signature: SystemSignature) => boolean; - onSignatureDeleted?: (deletedIds: string[]) => void; + onSignatureDeleted?: (deletedSignatures: ExtendedSystemSignature[]) => void; + deletedSignatures?: ExtendedSystemSignature[]; } export const SystemSignaturesContent = ({ @@ -71,6 +72,7 @@ export const SystemSignaturesContent = ({ onCountChange, filterSignature, onSignatureDeleted, + deletedSignatures = [], }: SystemSignaturesContentProps) => { const [selectedSignatureForDialog, setSelectedSignatureForDialog] = useState(null); const [showSignatureSettings, setShowSignatureSettings] = useState(false); @@ -127,8 +129,7 @@ export const SystemSignaturesContent = ({ event.preventDefault(); event.stopPropagation(); if (onSignatureDeleted && selectedSignatures.length > 0) { - const deletedIds = selectedSignatures.map(s => s.eve_id); - onSignatureDeleted(deletedIds); + onSignatureDeleted(selectedSignatures); } handleDeleteSelected(); }); @@ -158,9 +159,16 @@ export const SystemSignaturesContent = ({ const handleSelectSignatures = useCallback( (e: { value: SystemSignature[] }) => { - selectable ? onSelect?.(e.value[0]) : setSelectedSignatures(e.value as ExtendedSystemSignature[]); + // Filter out deleted signatures from selection + const selectableSignatures = e.value.filter( + sig => !deletedSignatures.some(deleted => deleted.eve_id === sig.eve_id), + ); + + selectable + ? onSelect?.(selectableSignatures[0]) + : setSelectedSignatures(selectableSignatures as ExtendedSystemSignature[]); }, - [onSelect, selectable, setSelectedSignatures], + [onSelect, selectable, setSelectedSignatures, deletedSignatures], ); const { showDescriptionColumn, showUpdatedColumn, showCharacterColumn, showCharacterPortrait } = useMemo( @@ -174,7 +182,11 @@ export const SystemSignaturesContent = ({ ); const filteredSignatures = useMemo(() => { - return signatures.filter(sig => { + // Get the set of deleted signature IDs for quick lookup + const deletedIds = new Set(deletedSignatures.map(sig => sig.eve_id)); + + // Common filter function + const shouldShowSignature = (sig: ExtendedSystemSignature): boolean => { if (filterSignature && !filterSignature(sig)) { return false; } @@ -203,9 +215,27 @@ export const SystemSignaturesContent = ({ return true; } - return settings[sig.kind]; + return settings[sig.kind] as boolean; + }; + + // Filter active signatures, excluding any that are in the deleted list + const activeSignatures = signatures.filter(sig => { + // Skip if this signature is in the deleted list + if (deletedIds.has(sig.eve_id)) { + return false; + } + + return shouldShowSignature(sig); }); - }, [signatures, hideLinkedSignatures, settings, filterSignature]); + + // Add deleted signatures with pending deletion flag, applying the same filters + const deletedWithPendingFlag = deletedSignatures.filter(shouldShowSignature).map(sig => ({ + ...sig, + pendingDeletion: true, + })); + + return [...activeSignatures, ...deletedWithPendingFlag]; + }, [signatures, hideLinkedSignatures, settings, filterSignature, deletedSignatures]); const onRowMouseEnter = useCallback((e: DataTableRowMouseEvent) => { setHoveredSignature(e.data as SystemSignature); @@ -249,7 +279,8 @@ export const SystemSignaturesContent = ({ {hasUnsupportedLanguage && (
- Non-English signatures detected. Some signatures may not display correctly. Double-click to edit signature details. + Non-English signatures detected. Some signatures may not display correctly. Double-click to edit signature + details.
)} & { - onSignatureDeleted?: (deletedIds: string[]) => void; + onSignatureDeleted?: (deletedSignatures: ExtendedSystemSignature[]) => void; }) => { const { outCommand } = useMapRootState(); const [signatures, setSignatures, signaturesRef] = useRefState([]); @@ -75,8 +75,7 @@ export const useSystemSignaturesData = ({ if (removed.length > 0) { await processRemovedSignatures(removed, added, updated); if (onSignatureDeleted) { - const deletedIds = removed.map(sig => sig.eve_id); - onSignatureDeleted(deletedIds); + onSignatureDeleted(removed); } } @@ -102,11 +101,23 @@ export const useSystemSignaturesData = ({ const handleDeleteSelected = useCallback(async () => { if (!selectedSignatures.length) return; + + // Call onSignatureDeleted with the full signature objects for visual feedback + if (onSignatureDeleted) { + onSignatureDeleted(selectedSignatures); + } + const selectedIds = selectedSignatures.map(s => s.eve_id); const finalList = signatures.filter(s => !selectedIds.includes(s.eve_id)); + + // IMPORTANT: Send deletion to server BEFORE updating local state + // Otherwise signaturesRef.current will be updated and getActualSigs won't detect removals await handleUpdateSignatures(finalList, false, true); + + // Update local state after server call + setSignatures(finalList); setSelectedSignatures([]); - }, [handleUpdateSignatures, selectedSignatures, signatures]); + }, [handleUpdateSignatures, selectedSignatures, signatures, onSignatureDeleted, setSignatures]); const handleSelectAll = useCallback(() => { setSelectedSignatures(signatures); @@ -130,11 +141,11 @@ export const useSystemSignaturesData = ({ return; } handleGetSignatures(); - }, [systemId]); + }, [handleGetSignatures, setSignatures, systemId, undoPending]); useEffect(() => { onCountChange?.(signatures.length); - }, [signatures]); + }, [onCountChange, signatures]); return { signatures: signatures.filter(sig => !sig.deleted),