fix(Core): fixed lazy delete timeouts

This commit is contained in:
Dmitry Popov
2025-03-16 13:32:39 +01:00
parent 3028a0b1c0
commit 8db46113f4
10 changed files with 155 additions and 234 deletions

View File

@@ -1,8 +1,8 @@
import { useCallback, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { Widget } from '@/hooks/Mapper/components/mapInterface/components'; import { Widget } from '@/hooks/Mapper/components/mapInterface/components';
import { SystemSignaturesContent } from './SystemSignaturesContent'; import { SystemSignaturesContent } from './SystemSignaturesContent';
import { SystemSignatureSettingsDialog } from './SystemSignatureSettingsDialog'; import { SystemSignatureSettingsDialog } from './SystemSignatureSettingsDialog';
import { SystemSignature } from '@/hooks/Mapper/types'; import { ExtendedSystemSignature, SystemSignature } from '@/hooks/Mapper/types';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider'; import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { useHotkey } from '@/hooks/Mapper/hooks'; import { useHotkey } from '@/hooks/Mapper/hooks';
import { SystemSignaturesHeader } from './SystemSignatureHeader'; import { SystemSignaturesHeader } from './SystemSignatureHeader';
@@ -10,15 +10,19 @@ import useLocalStorageState from 'use-local-storage-state';
import { import {
SETTINGS_KEYS, SETTINGS_KEYS,
SETTINGS_VALUES, SETTINGS_VALUES,
SIGNATURE_DELETION_TIMEOUTS,
SIGNATURE_SETTING_STORE_KEY, SIGNATURE_SETTING_STORE_KEY,
SIGNATURE_WINDOW_ID, SIGNATURE_WINDOW_ID,
SIGNATURES_DELETION_TIMING,
SignatureSettingsType, SignatureSettingsType,
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts'; } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts';
import { calculateTimeRemaining } from './helpers';
export const SystemSignatures = () => { export const SystemSignatures = () => {
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [sigCount, setSigCount] = useState<number>(0); const [sigCount, setSigCount] = useState<number>(0);
const [pendingSigs, setPendingSigs] = useState<SystemSignature[]>([]); const [pendingSigs, setPendingSigs] = useState<SystemSignature[]>([]);
const [pendingTimeRemaining, setPendingTimeRemaining] = useState<number | undefined>();
const undoPendingFnRef = useRef<() => void>(() => {}); const undoPendingFnRef = useRef<() => void>(() => {});
const { const {
@@ -51,27 +55,45 @@ export const SystemSignatures = () => {
event.stopPropagation(); event.stopPropagation();
undoPendingFnRef.current(); undoPendingFnRef.current();
setPendingSigs([]); setPendingSigs([]);
setPendingTimeRemaining(undefined);
} }
}); });
const handleUndoClick = useCallback(() => { const handleUndoClick = useCallback(() => {
undoPendingFnRef.current(); undoPendingFnRef.current();
setPendingSigs([]); setPendingSigs([]);
setPendingTimeRemaining(undefined);
}, []); }, []);
const handleSettingsButtonClick = useCallback(() => { const handleSettingsButtonClick = useCallback(() => {
setVisible(true); setVisible(true);
}, []); }, []);
const handlePendingChange = useCallback((newPending: SystemSignature[], newUndo: () => void) => { const handlePendingChange = useCallback(
setPendingSigs(prev => { (pending: React.MutableRefObject<Record<string, ExtendedSystemSignature>>, newUndo: () => void) => {
if (newPending.length === prev.length && newPending.every(np => prev.some(pp => pp.eve_id === np.eve_id))) { setPendingSigs(() => {
return prev; return Object.values(pending.current).filter(sig => sig.pendingDeletion);
}
return newPending;
}); });
undoPendingFnRef.current = newUndo; undoPendingFnRef.current = newUndo;
}, []); },
[],
);
// Calculate the minimum time remaining for any pending signature
useEffect(() => {
if (pendingSigs.length === 0) {
setPendingTimeRemaining(undefined);
return;
}
const calculate = () => {
setPendingTimeRemaining(() => calculateTimeRemaining(pendingSigs));
};
calculate();
const interval = setInterval(calculate, 1000);
return () => clearInterval(interval);
}, [pendingSigs]);
return ( return (
<Widget <Widget
@@ -79,8 +101,8 @@ export const SystemSignatures = () => {
<SystemSignaturesHeader <SystemSignaturesHeader
sigCount={sigCount} sigCount={sigCount}
lazyDeleteValue={currentSettings[SETTINGS_KEYS.LAZY_DELETE_SIGNATURES] as boolean} lazyDeleteValue={currentSettings[SETTINGS_KEYS.LAZY_DELETE_SIGNATURES] as boolean}
// lazyDeleteValue={lazyDeleteValue}
pendingCount={pendingSigs.length} pendingCount={pendingSigs.length}
pendingTimeRemaining={pendingTimeRemaining}
onLazyDeleteChange={handleLazyDeleteChange} onLazyDeleteChange={handleLazyDeleteChange}
onUndoClick={handleUndoClick} onUndoClick={handleUndoClick}
onSettingsClick={handleSettingsButtonClick} onSettingsClick={handleSettingsButtonClick}
@@ -96,6 +118,12 @@ export const SystemSignatures = () => {
<SystemSignaturesContent <SystemSignaturesContent
systemId={systemId} systemId={systemId}
settings={currentSettings} settings={currentSettings}
deletionTiming={
SIGNATURE_DELETION_TIMEOUTS[
(currentSettings[SETTINGS_KEYS.DELETION_TIMING] as keyof typeof SIGNATURE_DELETION_TIMEOUTS) ||
SIGNATURES_DELETION_TIMING.DEFAULT
] as number
}
onLazyDeleteChange={handleLazyDeleteChange} onLazyDeleteChange={handleLazyDeleteChange}
onCountChange={handleSigCountChange} onCountChange={handleSigCountChange}
onPendingChange={handlePendingChange} onPendingChange={handlePendingChange}

View File

@@ -132,6 +132,8 @@ export enum SIGNATURES_DELETION_TIMING {
EXTENDED, EXTENDED,
} }
export type SignatureDeletionTimingType = { [key in SIGNATURES_DELETION_TIMING]?: unknown };
export const SIGNATURE_SETTINGS = { export const SIGNATURE_SETTINGS = {
filterFlags: [ filterFlags: [
{ type: SettingsTypes.flag, key: SETTINGS_KEYS.COSMIC_ANOMALY, name: 'Show Anomalies' }, { type: SettingsTypes.flag, key: SETTINGS_KEYS.COSMIC_ANOMALY, name: 'Show Anomalies' },
@@ -200,3 +202,9 @@ export const SETTINGS_VALUES: SignatureSettingsType = {
[SETTINGS_KEYS.GAS_SITE]: true, [SETTINGS_KEYS.GAS_SITE]: true,
[SETTINGS_KEYS.COMBAT_SITE]: true, [SETTINGS_KEYS.COMBAT_SITE]: true,
}; };
export const SIGNATURE_DELETION_TIMEOUTS: SignatureDeletionTimingType = {
[SIGNATURES_DELETION_TIMING.DEFAULT]: 10_000,
[SIGNATURES_DELETION_TIMING.IMMEDIATE]: 0,
[SIGNATURES_DELETION_TIMING.EXTENDED]: 30_000,
};

View File

@@ -1,4 +1,4 @@
import { ExtendedSystemSignature } from '@/hooks/Mapper/types'; import { ExtendedSystemSignature, SystemSignature } from '@/hooks/Mapper/types';
import { FINAL_DURATION_MS } from '../constants'; import { FINAL_DURATION_MS } from '../constants';
export function prepareUpdatePayload( export function prepareUpdatePayload(
@@ -49,40 +49,56 @@ export function schedulePendingAdditionForSig(
); );
} }
export function mergeLocalPendingAdditions( export function mergeLocalPending(
pendingMapRef: React.MutableRefObject<Record<string, ExtendedSystemSignature>>,
serverSigs: ExtendedSystemSignature[], serverSigs: ExtendedSystemSignature[],
localSigs: ExtendedSystemSignature[],
): ExtendedSystemSignature[] { ): ExtendedSystemSignature[] {
const now = Date.now(); const now = Date.now();
const pendingAdditions = localSigs.filter(sig => sig.pendingAddition && sig.pendingUntil && sig.pendingUntil > now); const pendingDeletions = Object.values(pendingMapRef.current).filter(
sig => sig.pendingDeletion && sig.pendingUntil && sig.pendingUntil > now,
);
const mergedMap = new Map<string, ExtendedSystemSignature>(); const mergedMap = new Map<string, ExtendedSystemSignature>();
serverSigs.forEach(sig => mergedMap.set(sig.eve_id, sig)); serverSigs.forEach(sig => mergedMap.set(sig.eve_id, sig));
pendingAdditions.forEach(sig => {
if (!mergedMap.has(sig.eve_id)) { pendingDeletions.forEach(sig => {
if (mergedMap.has(sig.eve_id)) {
mergedMap.set(sig.eve_id, sig); mergedMap.set(sig.eve_id, sig);
} }
}); });
return Array.from(mergedMap.values()); return Array.from(mergedMap.values());
} }
export function scheduleLazyDeletionTimers( export function scheduleLazyTimers(
toRemove: ExtendedSystemSignature[], signatures: ExtendedSystemSignature[],
setPendingMap: React.Dispatch<React.SetStateAction<Record<string, { finalUntil: number; finalTimeoutId: number }>>>, pendingMapRef: React.MutableRefObject<Record<string, ExtendedSystemSignature>>,
finalizeRemoval: (sig: ExtendedSystemSignature) => Promise<void>, finalizeFn: (sig: ExtendedSystemSignature) => Promise<void>,
finalDuration = FINAL_DURATION_MS, finalDuration = FINAL_DURATION_MS,
) { ) {
const now = Date.now(); signatures.forEach(sig => {
toRemove.forEach(sig => {
const finalTimeoutId = window.setTimeout(async () => { const finalTimeoutId = window.setTimeout(async () => {
await finalizeRemoval(sig); await finalizeFn(sig);
}, finalDuration); }, finalDuration);
setPendingMap(prev => ({ pendingMapRef.current = {
...prev, ...pendingMapRef.current,
[sig.eve_id]: { [sig.eve_id]: {
finalUntil: now + finalDuration, ...sig,
finalTimeoutId, finalTimeoutId,
}, },
})); };
}); });
} }
export const calculateTimeRemaining = (pendingSigs: SystemSignature[]) => {
const now = Date.now();
let minTime: number | undefined = undefined;
pendingSigs.forEach(sig => {
const extendedSig = sig as unknown as { pendingUntil?: number };
if (extendedSig.pendingUntil && (minTime === undefined || extendedSig.pendingUntil - now < minTime)) {
minTime = extendedSig.pendingUntil - now;
}
});
return minTime && minTime > 0 ? minTime : undefined;
};

View File

@@ -6,7 +6,10 @@ export interface UseSystemSignaturesDataProps {
settings: SignatureSettingsType; settings: SignatureSettingsType;
hideLinkedSignatures?: boolean; hideLinkedSignatures?: boolean;
onCountChange?: (count: number) => void; onCountChange?: (count: number) => void;
onPendingChange?: (pending: ExtendedSystemSignature[], undo: () => void) => void; onPendingChange?: (
pending: React.MutableRefObject<Record<string, ExtendedSystemSignature>>,
undo: () => void,
) => void;
onLazyDeleteChange?: (value: boolean) => void; onLazyDeleteChange?: (value: boolean) => void;
deletionTiming?: number; deletionTiming?: number;
} }
@@ -15,16 +18,21 @@ export interface UseFetchingParams {
systemId: string; systemId: string;
signaturesRef: React.MutableRefObject<ExtendedSystemSignature[]>; signaturesRef: React.MutableRefObject<ExtendedSystemSignature[]>;
setSignatures: React.Dispatch<React.SetStateAction<ExtendedSystemSignature[]>>; setSignatures: React.Dispatch<React.SetStateAction<ExtendedSystemSignature[]>>;
localPendingDeletions: ExtendedSystemSignature[]; pendingDeletionMapRef: React.MutableRefObject<Record<string, ExtendedSystemSignature>>;
} }
export interface UsePendingDeletionParams { export interface UsePendingDeletionParams {
systemId: string; systemId: string;
setSignatures: React.Dispatch<React.SetStateAction<ExtendedSystemSignature[]>>;
deletionTiming?: number; deletionTiming?: number;
setSignatures: React.Dispatch<React.SetStateAction<ExtendedSystemSignature[]>>;
onPendingChange?: (
pending: React.MutableRefObject<Record<string, ExtendedSystemSignature>>,
undo: () => void,
) => void;
} }
export interface UsePendingAdditionParams { export interface UsePendingAdditionParams {
systemId: string;
setSignatures: React.Dispatch<React.SetStateAction<ExtendedSystemSignature[]>>; setSignatures: React.Dispatch<React.SetStateAction<ExtendedSystemSignature[]>>;
deletionTiming?: number; deletionTiming?: number;
} }

View File

@@ -1,70 +0,0 @@
import { useCallback, useRef, useState } from 'react';
import { UsePendingAdditionParams } from './types';
import { FINAL_DURATION_MS } from '../constants';
import { ExtendedSystemSignature } from '@/hooks/Mapper/types';
import { schedulePendingAdditionForSig } from '../helpers/contentHelpers';
export const usePendingAdditions = ({ setSignatures, deletionTiming }: UsePendingAdditionParams) => {
const [pendingUndoAdditions, setPendingUndoAdditions] = useState<ExtendedSystemSignature[]>([]);
const pendingAdditionMapRef = useRef<Record<string, { finalUntil: number; finalTimeoutId: number }>>({});
// Use the provided deletion timing or fall back to the default
const finalDuration = deletionTiming !== undefined ? deletionTiming : FINAL_DURATION_MS;
const processAddedSignatures = useCallback(
(added: ExtendedSystemSignature[]) => {
if (!added.length) return;
// If duration is 0, don't show pending state
if (finalDuration === 0) {
setSignatures(prev => [
...prev,
...added.map(sig => ({
...sig,
pendingAddition: false,
})),
]);
return;
}
const now = Date.now();
setSignatures(prev => [
...prev,
...added.map(sig => ({
...sig,
pendingAddition: true,
pendingUntil: now + finalDuration,
})),
]);
added.forEach(sig => {
schedulePendingAdditionForSig(
sig,
finalDuration,
setSignatures,
pendingAdditionMapRef,
setPendingUndoAdditions,
);
});
},
[setSignatures, finalDuration],
);
const clearPendingAdditions = useCallback(() => {
Object.values(pendingAdditionMapRef.current).forEach(({ finalTimeoutId }) => {
clearTimeout(finalTimeoutId);
});
pendingAdditionMapRef.current = {};
setSignatures(prev =>
prev.map(x => (x.pendingAddition ? { ...x, pendingAddition: false, pendingUntil: undefined } : x)),
);
setPendingUndoAdditions([]);
}, [setSignatures]);
return {
pendingUndoAdditions,
setPendingUndoAdditions,
pendingAdditionMapRef,
processAddedSignatures,
clearPendingAdditions,
};
};

View File

@@ -1,17 +1,19 @@
import { useState, useCallback } from 'react'; import { useCallback, useRef, useEffect } from 'react';
import { OutCommand } from '@/hooks/Mapper/types/mapHandlers'; import { OutCommand } from '@/hooks/Mapper/types/mapHandlers';
import { prepareUpdatePayload, scheduleLazyDeletionTimers } from '../helpers'; import { prepareUpdatePayload, scheduleLazyTimers } from '../helpers';
import { UsePendingDeletionParams } from './types'; import { UsePendingDeletionParams } from './types';
import { FINAL_DURATION_MS } from '../constants'; import { FINAL_DURATION_MS } from '../constants';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider'; import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { ExtendedSystemSignature } from '@/hooks/Mapper/types'; import { ExtendedSystemSignature } from '@/hooks/Mapper/types';
export function usePendingDeletions({ systemId, setSignatures, deletionTiming }: UsePendingDeletionParams) { export function usePendingDeletions({
systemId,
setSignatures,
deletionTiming,
onPendingChange,
}: UsePendingDeletionParams) {
const { outCommand } = useMapRootState(); const { outCommand } = useMapRootState();
const [localPendingDeletions, setLocalPendingDeletions] = useState<ExtendedSystemSignature[]>([]); const pendingDeletionMapRef = useRef<Record<string, ExtendedSystemSignature>>({});
const [pendingDeletionMap, setPendingDeletionMap] = useState<
Record<string, { finalUntil: number; finalTimeoutId: number }>
>({});
// Use the provided deletion timing or fall back to the default // Use the provided deletion timing or fall back to the default
const finalDuration = deletionTiming !== undefined ? deletionTiming : FINAL_DURATION_MS; const finalDuration = deletionTiming !== undefined ? deletionTiming : FINAL_DURATION_MS;
@@ -37,15 +39,17 @@ export function usePendingDeletions({ systemId, setSignatures, deletionTiming }:
const processedRemoved = removed.map(r => ({ const processedRemoved = removed.map(r => ({
...r, ...r,
pendingDeletion: true, pendingDeletion: true,
pendingAddition: false,
pendingUntil: now + finalDuration, pendingUntil: now + finalDuration,
})); }));
setLocalPendingDeletions(prev => [...prev, ...processedRemoved]); pendingDeletionMapRef.current = {
...pendingDeletionMapRef.current,
...processedRemoved.reduce((acc: any, sig) => {
acc[sig.eve_id] = sig;
return acc;
}, {}),
};
outCommand({ onPendingChange?.(pendingDeletionMapRef, clearPendingDeletions);
type: OutCommand.updateSignatures,
data: prepareUpdatePayload(systemId, added, updated, []),
});
setSignatures(prev => setSignatures(prev =>
prev.map(sig => { prev.map(sig => {
@@ -56,37 +60,34 @@ export function usePendingDeletions({ systemId, setSignatures, deletionTiming }:
}), }),
); );
scheduleLazyDeletionTimers( scheduleLazyTimers(
processedRemoved, processedRemoved,
setPendingDeletionMap, pendingDeletionMapRef,
async sig => { async sig => {
await outCommand({ await outCommand({
type: OutCommand.updateSignatures, type: OutCommand.updateSignatures,
data: prepareUpdatePayload(systemId, [], [], [sig]), data: prepareUpdatePayload(systemId, [], [], [sig]),
}); });
setLocalPendingDeletions(prev => prev.filter(x => x.eve_id !== sig.eve_id)); delete pendingDeletionMapRef.current[sig.eve_id];
setSignatures(prev => prev.filter(x => x.eve_id !== sig.eve_id)); setSignatures(prev => prev.filter(x => x.eve_id !== sig.eve_id));
}, },
finalDuration, finalDuration,
); );
}, },
[systemId, outCommand, setSignatures, finalDuration], [systemId, outCommand, finalDuration],
); );
const clearPendingDeletions = useCallback(() => { const clearPendingDeletions = useCallback(() => {
Object.values(pendingDeletionMap).forEach(({ finalTimeoutId }) => clearTimeout(finalTimeoutId)); Object.values(pendingDeletionMapRef.current).forEach(({ finalTimeoutId }) => {
setPendingDeletionMap({}); clearTimeout(finalTimeoutId);
setSignatures(prev => });
prev.map(x => (x.pendingDeletion ? { ...x, pendingDeletion: false, pendingUntil: undefined } : x)), pendingDeletionMapRef.current = {};
); setSignatures(prev => prev.map(x => (x.pendingDeletion ? { ...x, pendingDeletion: false } : x)));
setLocalPendingDeletions([]); onPendingChange?.(pendingDeletionMapRef, clearPendingDeletions);
}, [pendingDeletionMap, setSignatures]); }, []);
return { return {
localPendingDeletions, pendingDeletionMapRef,
setLocalPendingDeletions,
pendingDeletionMap,
setPendingDeletionMap,
processRemovedSignatures, processRemovedSignatures,
clearPendingDeletions, clearPendingDeletions,
}; };

View File

@@ -1,16 +1,15 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import { ExtendedSystemSignature, SystemSignature } from '@/hooks/Mapper/types'; import { ExtendedSystemSignature, SystemSignature } from '@/hooks/Mapper/types';
import { OutCommand } from '@/hooks/Mapper/types/mapHandlers'; import { OutCommand } from '@/hooks/Mapper/types/mapHandlers';
import { prepareUpdatePayload, getActualSigs, mergeLocalPendingAdditions } from '../helpers'; import { prepareUpdatePayload, getActualSigs, mergeLocalPending } from '../helpers';
import { UseFetchingParams } from './types'; import { UseFetchingParams } from './types';
import { FINAL_DURATION_MS } from '../constants';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider'; import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
export const useSignatureFetching = ({ export const useSignatureFetching = ({
systemId, systemId,
signaturesRef, signaturesRef,
setSignatures, setSignatures,
localPendingDeletions, pendingDeletionMapRef,
}: UseFetchingParams) => { }: UseFetchingParams) => {
const { const {
data: { characters }, data: { characters },
@@ -22,9 +21,6 @@ export const useSignatureFetching = ({
setSignatures([]); setSignatures([]);
return; return;
} }
if (localPendingDeletions.length) {
return;
}
const resp = await outCommand({ const resp = await outCommand({
type: OutCommand.getSignatures, type: OutCommand.getSignatures,
data: { system_id: systemId }, data: { system_id: systemId },
@@ -36,8 +32,8 @@ export const useSignatureFetching = ({
character_name: characters.find(c => c.eve_id === s.character_eve_id)?.name, character_name: characters.find(c => c.eve_id === s.character_eve_id)?.name,
})) as ExtendedSystemSignature[]; })) as ExtendedSystemSignature[];
setSignatures(prev => mergeLocalPendingAdditions(extended, prev)); setSignatures(() => mergeLocalPending(pendingDeletionMapRef, extended));
}, [characters, systemId, localPendingDeletions, outCommand, setSignatures]); }, [characters, systemId, outCommand]);
const handleUpdateSignatures = useCallback( const handleUpdateSignatures = useCallback(
async (newList: ExtendedSystemSignature[], updateOnly: boolean, skipUpdateUntouched?: boolean) => { async (newList: ExtendedSystemSignature[], updateOnly: boolean, skipUpdateUntouched?: boolean) => {
@@ -48,24 +44,12 @@ export const useSignatureFetching = ({
skipUpdateUntouched, skipUpdateUntouched,
); );
if (added.length > 0) {
const now = Date.now();
setSignatures(prev => [
...prev,
...added.map(a => ({
...a,
pendingAddition: true,
pendingUntil: now + FINAL_DURATION_MS,
})),
]);
}
await outCommand({ await outCommand({
type: OutCommand.updateSignatures, type: OutCommand.updateSignatures,
data: prepareUpdatePayload(systemId, added, updated, removed), data: prepareUpdatePayload(systemId, added, updated, removed),
}); });
}, },
[systemId, outCommand, signaturesRef, setSignatures], [systemId, outCommand, signaturesRef],
); );
return { return {

View File

@@ -1,13 +1,12 @@
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import useRefState from 'react-usestateref'; import useRefState from 'react-usestateref';
import { useMapEventListener } from '@/hooks/Mapper/events'; import { useMapEventListener } from '@/hooks/Mapper/events';
import { Commands, ExtendedSystemSignature, SignatureKind, SystemSignature } from '@/hooks/Mapper/types'; import { Commands, ExtendedSystemSignature, SignatureKind } from '@/hooks/Mapper/types';
import { OutCommand } from '@/hooks/Mapper/types/mapHandlers'; import { OutCommand } from '@/hooks/Mapper/types/mapHandlers';
import { parseSignatures } from '@/hooks/Mapper/helpers'; import { parseSignatures } from '@/hooks/Mapper/helpers';
import { getActualSigs, mergeLocalPendingAdditions } from '../helpers'; import { getActualSigs } from '../helpers';
import { useSignatureFetching } from './useSignatureFetching'; import { useSignatureFetching } from './useSignatureFetching';
import { usePendingAdditions } from './usePendingAdditions';
import { usePendingDeletions } from './usePendingDeletions'; import { usePendingDeletions } from './usePendingDeletions';
import { UseSystemSignaturesDataProps } from './types'; import { UseSystemSignaturesDataProps } from './types';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider'; import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
@@ -25,24 +24,18 @@ export const useSystemSignaturesData = ({
const [signatures, setSignatures, signaturesRef] = useRefState<ExtendedSystemSignature[]>([]); const [signatures, setSignatures, signaturesRef] = useRefState<ExtendedSystemSignature[]>([]);
const [selectedSignatures, setSelectedSignatures] = useState<ExtendedSystemSignature[]>([]); const [selectedSignatures, setSelectedSignatures] = useState<ExtendedSystemSignature[]>([]);
const { localPendingDeletions, setLocalPendingDeletions, processRemovedSignatures, clearPendingDeletions } = const { pendingDeletionMapRef, processRemovedSignatures, clearPendingDeletions } = usePendingDeletions({
usePendingDeletions({
systemId, systemId,
setSignatures, setSignatures,
deletionTiming, deletionTiming,
}); onPendingChange,
const { pendingUndoAdditions, setPendingUndoAdditions, processAddedSignatures, clearPendingAdditions } =
usePendingAdditions({
setSignatures,
deletionTiming,
}); });
const { handleGetSignatures, handleUpdateSignatures } = useSignatureFetching({ const { handleGetSignatures, handleUpdateSignatures } = useSignatureFetching({
systemId, systemId,
signaturesRef, signaturesRef,
setSignatures, setSignatures,
localPendingDeletions, pendingDeletionMapRef,
}); });
const handlePaste = useCallback( const handlePaste = useCallback(
@@ -56,18 +49,16 @@ export const useSystemSignaturesData = ({
const currentNonPending = lazyDeleteValue const currentNonPending = lazyDeleteValue
? signaturesRef.current.filter(sig => !sig.pendingDeletion) ? signaturesRef.current.filter(sig => !sig.pendingDeletion)
: signaturesRef.current.filter(sig => !sig.pendingDeletion && !sig.pendingAddition); : signaturesRef.current.filter(sig => !sig.pendingDeletion || !sig.pendingAddition);
const { added, updated, removed } = getActualSigs(currentNonPending, incomingSignatures, !lazyDeleteValue, true); const { added, updated, removed } = getActualSigs(currentNonPending, incomingSignatures, !lazyDeleteValue, true);
if (added.length > 0) {
processAddedSignatures(added);
}
if (removed.length > 0) { if (removed.length > 0) {
await processRemovedSignatures(removed, added, updated); await processRemovedSignatures(removed, added, updated);
} else { }
const resp = await outCommand({
if (updated.length !== 0 || added.length !== 0) {
await outCommand({
type: OutCommand.updateSignatures, type: OutCommand.updateSignatures,
data: { data: {
system_id: systemId, system_id: systemId,
@@ -76,16 +67,6 @@ export const useSystemSignaturesData = ({
removed: [], removed: [],
}, },
}); });
if (resp) {
const finalSigs = (resp.signatures ?? []) as SystemSignature[];
setSignatures(prev =>
mergeLocalPendingAdditions(
finalSigs.map(x => ({ ...x })),
prev,
),
);
}
} }
const keepLazy = settings[SETTINGS_KEYS.KEEP_LAZY_DELETE] as boolean; const keepLazy = settings[SETTINGS_KEYS.KEEP_LAZY_DELETE] as boolean;
@@ -93,16 +74,7 @@ export const useSystemSignaturesData = ({
onLazyDeleteChange?.(false); onLazyDeleteChange?.(false);
} }
}, },
[ [settings, signaturesRef, processRemovedSignatures, outCommand, systemId, onLazyDeleteChange],
settings,
signaturesRef,
processAddedSignatures,
processRemovedSignatures,
outCommand,
systemId,
setSignatures,
onLazyDeleteChange,
],
); );
const handleDeleteSelected = useCallback(async () => { const handleDeleteSelected = useCallback(async () => {
@@ -112,7 +84,7 @@ export const useSystemSignaturesData = ({
await handleUpdateSignatures(finalList, false, true); await handleUpdateSignatures(finalList, false, true);
setSelectedSignatures([]); setSelectedSignatures([]);
}, [selectedSignatures, signatures, handleUpdateSignatures]); }, [selectedSignatures, signatures]);
const handleSelectAll = useCallback(() => { const handleSelectAll = useCallback(() => {
setSelectedSignatures(signatures); setSelectedSignatures(signatures);
@@ -120,42 +92,7 @@ export const useSystemSignaturesData = ({
const undoPending = useCallback(() => { const undoPending = useCallback(() => {
clearPendingDeletions(); clearPendingDeletions();
clearPendingAdditions(); }, [clearPendingDeletions]);
setSignatures(prev =>
prev.map(x => (x.pendingDeletion ? { ...x, pendingDeletion: false, pendingUntil: undefined } : x)),
);
if (pendingUndoAdditions.length) {
pendingUndoAdditions.forEach(async sig => {
await outCommand({
type: OutCommand.updateSignatures,
data: {
system_id: systemId,
added: [],
updated: [],
removed: [sig],
},
});
});
setSignatures(prev => prev.filter(x => !pendingUndoAdditions.some(u => u.eve_id === x.eve_id)));
setPendingUndoAdditions([]);
}
setLocalPendingDeletions([]);
}, [
clearPendingDeletions,
clearPendingAdditions,
pendingUndoAdditions,
setPendingUndoAdditions,
setLocalPendingDeletions,
setSignatures,
outCommand,
systemId,
]);
useEffect(() => {
const combined = [...localPendingDeletions, ...pendingUndoAdditions];
onPendingChange?.(combined, undoPending);
}, [localPendingDeletions, pendingUndoAdditions, onPendingChange, undoPending]);
useMapEventListener(event => { useMapEventListener(event => {
if (event.name === Commands.signaturesUpdated && String(event.data) === String(systemId)) { if (event.name === Commands.signaturesUpdated && String(event.data) === String(systemId)) {
@@ -167,14 +104,15 @@ export const useSystemSignaturesData = ({
useEffect(() => { useEffect(() => {
if (!systemId) { if (!systemId) {
setSignatures([]); setSignatures([]);
undoPending();
return; return;
} }
handleGetSignatures(); handleGetSignatures();
}, [systemId, handleGetSignatures, setSignatures]); }, [systemId]);
useEffect(() => { useEffect(() => {
onCountChange?.(signatures.length); onCountChange?.(signatures.length);
}, [signatures, onCountChange]); }, [signatures]);
return { return {
signatures, signatures,

View File

@@ -52,6 +52,7 @@ export interface ExtendedSystemSignature extends SystemSignature {
pendingDeletion?: boolean; pendingDeletion?: boolean;
pendingAddition?: boolean; pendingAddition?: boolean;
pendingUntil?: number; pendingUntil?: number;
finalTimeoutId?: number;
} }
export enum SignatureKindENG { export enum SignatureKindENG {

View File

@@ -3850,6 +3850,11 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
dependencies: dependencies:
brace-expansion "^1.1.7" brace-expansion "^1.1.7"
morphdom@2.7.4:
version "2.7.4"
resolved "https://registry.yarnpkg.com/morphdom/-/morphdom-2.7.4.tgz#c61d511e935cc25ca588dfaa752461f27865865e"
integrity sha512-ATTbWMgGa+FaMU3FhnFYB6WgulCqwf6opOll4CBzmVDTLvPMmUPrEv8CudmLPK0MESa64+6B89fWOxP3+YIlxQ==
ms@2.1.2: ms@2.1.2:
version "2.1.2" version "2.1.2"
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
@@ -4061,7 +4066,9 @@ path-type@^5.0.0:
version "4.2.1" version "4.2.1"
"phoenix_live_view@file:../deps/phoenix_live_view": "phoenix_live_view@file:../deps/phoenix_live_view":
version "0.20.17" version "1.0.5"
dependencies:
morphdom "2.7.4"
picocolors@^1, picocolors@^1.0.0: picocolors@^1, picocolors@^1.0.0:
version "1.0.0" version "1.0.0"