feat: support german and french signatures

This commit is contained in:
Guarzo
2025-05-14 09:44:38 -04:00
parent cb318aa6c6
commit 1364779f81
8 changed files with 344 additions and 168 deletions

View File

@@ -25,12 +25,16 @@ function useSignatureUndo(
settings: SignatureSettingsType, settings: SignatureSettingsType,
outCommand: OutCommandHandler, outCommand: OutCommandHandler,
) { ) {
const [pendingIds, setPendingIds] = useState<string[]>([]); const [countdown, setCountdown] = useState<number>(0);
const [countdown, setCountdown] = useState(0); const [pendingIds, setPendingIds] = useState<Set<string>>(new Set());
const intervalRef = useRef<number | null>(null); const intervalRef = useRef<number | null>(null);
const addDeleted = useCallback((ids: string[]) => { const addDeleted = useCallback((ids: string[]) => {
setPendingIds(prev => [...prev, ...ids]); setPendingIds(prev => {
const next = new Set(prev);
ids.forEach(id => next.add(id));
return next;
});
}, []); }, []);
// kick off or clear countdown whenever pendingIds changes // kick off or clear countdown whenever pendingIds changes
@@ -41,7 +45,7 @@ function useSignatureUndo(
intervalRef.current = null; intervalRef.current = null;
} }
if (pendingIds.length === 0) { if (pendingIds.size === 0) {
setCountdown(0); setCountdown(0);
return; return;
} }
@@ -58,7 +62,7 @@ function useSignatureUndo(
if (prev <= 1) { if (prev <= 1) {
clearInterval(intervalRef.current!); clearInterval(intervalRef.current!);
intervalRef.current = null; intervalRef.current = null;
setPendingIds([]); setPendingIds(new Set());
return 0; return 0;
} }
return prev - 1; return prev - 1;
@@ -71,16 +75,16 @@ function useSignatureUndo(
intervalRef.current = null; intervalRef.current = null;
} }
}; };
}, [pendingIds, settings]); }, [pendingIds, settings[SETTINGS_KEYS.DELETION_TIMING]]);
// undo handler // undo handler
const handleUndo = useCallback(async () => { const handleUndo = useCallback(async () => {
if (!systemId || pendingIds.length === 0) return; if (!systemId || pendingIds.size === 0) return;
await outCommand({ await outCommand({
type: OutCommand.undoDeleteSignatures, type: OutCommand.undoDeleteSignatures,
data: { system_id: systemId, eve_ids: pendingIds }, data: { system_id: systemId, eve_ids: Array.from(pendingIds) },
}); });
setPendingIds([]); setPendingIds(new Set());
setCountdown(0); setCountdown(0);
if (intervalRef.current != null) { if (intervalRef.current != null) {
clearInterval(intervalRef.current); clearInterval(intervalRef.current);
@@ -117,7 +121,7 @@ export const SystemSignatures = () => {
const { pendingIds, countdown, addDeleted, handleUndo } = useSignatureUndo(systemId, currentSettings, outCommand); const { pendingIds, countdown, addDeleted, handleUndo } = useSignatureUndo(systemId, currentSettings, outCommand);
useHotkey(true, ['z', 'Z'], (event: KeyboardEvent) => { useHotkey(true, ['z', 'Z'], (event: KeyboardEvent) => {
if (pendingIds.length > 0 && countdown > 0) { if (pendingIds.size > 0 && countdown > 0) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
handleUndo(); handleUndo();
@@ -154,7 +158,7 @@ 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}
pendingCount={pendingIds.length} pendingCount={pendingIds.size}
undoCountdown={countdown} undoCountdown={countdown}
onLazyDeleteChange={handleLazyDeleteToggle} onLazyDeleteChange={handleLazyDeleteToggle}
onUndoClick={handleUndo} onUndoClick={handleUndo}

View File

@@ -90,14 +90,21 @@ export const SystemSignaturesContent = ({
{ defaultValue: SORT_DEFAULT_VALUES }, { defaultValue: SORT_DEFAULT_VALUES },
); );
const { signatures, selectedSignatures, setSelectedSignatures, handleDeleteSelected, handleSelectAll, handlePaste } = const {
useSystemSignaturesData({ signatures,
systemId, selectedSignatures,
settings, setSelectedSignatures,
onCountChange, handleDeleteSelected,
onLazyDeleteChange, handleSelectAll,
onSignatureDeleted, handlePaste,
}); hasUnsupportedLanguage,
} = useSystemSignaturesData({
systemId,
settings,
onCountChange,
onLazyDeleteChange,
onSignatureDeleted,
});
useEffect(() => { useEffect(() => {
if (selectable) return; if (selectable) return;
@@ -186,7 +193,11 @@ export const SystemSignaturesContent = ({
x => GROUPS_LIST.includes(x as SignatureGroup) && settings[x as SETTINGS_KEYS], x => GROUPS_LIST.includes(x as SignatureGroup) && settings[x as SETTINGS_KEYS],
); );
return enabledGroups.includes(getGroupIdByRawGroup(sig.group)); const mappedGroup = getGroupIdByRawGroup(sig.group);
if (!mappedGroup) {
return true; // If we can't determine the group, still show it
}
return enabledGroups.includes(mappedGroup);
} }
return true; return true;
@@ -234,113 +245,121 @@ export const SystemSignaturesContent = ({
No signatures No signatures
</div> </div>
) : ( ) : (
<DataTable <>
value={filteredSignatures} {hasUnsupportedLanguage && (
size="small" <div className="w-full flex justify-center items-center text-amber-500 text-xs p-1 bg-amber-950/20 border-b border-amber-800/30">
selectionMode="multiple" <i className={PrimeIcons.EXCLAMATION_TRIANGLE + ' mr-1'} />
selection={selectedSignatures} Non-English signatures detected. Some signatures may not display correctly. Double-click to edit signature details.
metaKeySelection </div>
onSelectionChange={handleSelectSignatures}
dataKey="eve_id"
className="w-full select-none"
resizableColumns={false}
rowHover
selectAll
onRowDoubleClick={handleRowClick}
sortField={sortSettings.sortField}
sortOrder={sortSettings.sortOrder}
onSort={handleSortSettings}
onRowMouseEnter={onRowMouseEnter}
onRowMouseLeave={onRowMouseLeave}
// @ts-ignore
rowClassName={getRowClassName}
>
<Column
field="icon"
header=""
body={renderColIcon}
bodyClassName="p-0 px-1"
style={{ maxWidth: 26, minWidth: 26, width: 26 }}
/>
<Column
field="eve_id"
header="Id"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
style={{ maxWidth: 72, minWidth: 72, width: 72 }}
sortable
/>
<Column
field="group"
header="Group"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
style={{ maxWidth: 110, minWidth: 110, width: 110 }}
body={sig => sig.group ?? ''}
hidden={isCompact}
sortable
/>
<Column
field="info"
header="Info"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
style={{ maxWidth: nameColumnWidth }}
hidden={isCompact || isMedium}
body={renderInfoColumn}
/>
{showDescriptionColumn && (
<Column
field="description"
header="Description"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
hidden={isCompact}
body={renderDescription}
sortable
/>
)} )}
<Column <DataTable
field="inserted_at" value={filteredSignatures}
header="Added" size="small"
dataType="date" selectionMode="multiple"
body={renderAddedTimeLeft} selection={selectedSignatures}
style={{ minWidth: 70, maxWidth: 80 }} metaKeySelection
bodyClassName="ssc-header text-ellipsis overflow-hidden whitespace-nowrap" onSelectionChange={handleSelectSignatures}
sortable dataKey="eve_id"
/> className="w-full select-none"
{showUpdatedColumn && ( resizableColumns={false}
<Column rowHover
field="updated_at" selectAll
header="Updated" onRowDoubleClick={handleRowClick}
dataType="date" sortField={sortSettings.sortField}
body={renderUpdatedTimeLeft} sortOrder={sortSettings.sortOrder}
style={{ minWidth: 70, maxWidth: 80 }} onSort={handleSortSettings}
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap" onRowMouseEnter={onRowMouseEnter}
sortable onRowMouseLeave={onRowMouseLeave}
/> // @ts-ignore
)} rowClassName={getRowClassName}
>
{showCharacterColumn && (
<Column
field="character_name"
header="Character"
bodyClassName="w-[70px] text-ellipsis overflow-hidden whitespace-nowrap"
sortable
></Column>
)}
{!selectable && (
<Column <Column
field="icon"
header="" header=""
body={() => ( body={renderColIcon}
<div className="flex justify-end items-center gap-2 mr-[4px]"> bodyClassName="p-0 px-1"
<WdTooltipWrapper content="Double-click a row to edit signature">
<span className={PrimeIcons.PENCIL + ' text-[10px]'} />
</WdTooltipWrapper>
</div>
)}
style={{ maxWidth: 26, minWidth: 26, width: 26 }} style={{ maxWidth: 26, minWidth: 26, width: 26 }}
bodyClassName="p-0 pl-1 pr-2"
/> />
)} <Column
</DataTable> field="eve_id"
header="Id"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
style={{ maxWidth: 72, minWidth: 72, width: 72 }}
sortable
/>
<Column
field="group"
header="Group"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
style={{ maxWidth: 110, minWidth: 110, width: 110 }}
body={sig => sig.group ?? ''}
hidden={isCompact}
sortable
/>
<Column
field="info"
header="Info"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
style={{ maxWidth: nameColumnWidth }}
hidden={isCompact || isMedium}
body={renderInfoColumn}
/>
{showDescriptionColumn && (
<Column
field="description"
header="Description"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
hidden={isCompact}
body={renderDescription}
sortable
/>
)}
<Column
field="inserted_at"
header="Added"
dataType="date"
body={renderAddedTimeLeft}
style={{ minWidth: 70, maxWidth: 80 }}
bodyClassName="ssc-header text-ellipsis overflow-hidden whitespace-nowrap"
sortable
/>
{showUpdatedColumn && (
<Column
field="updated_at"
header="Updated"
dataType="date"
body={renderUpdatedTimeLeft}
style={{ minWidth: 70, maxWidth: 80 }}
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
sortable
/>
)}
{showCharacterColumn && (
<Column
field="character_name"
header="Character"
bodyClassName="w-[70px] text-ellipsis overflow-hidden whitespace-nowrap"
sortable
></Column>
)}
{!selectable && (
<Column
header=""
body={() => (
<div className="flex justify-end items-center gap-2 mr-[4px]">
<WdTooltipWrapper content="Double-click a row to edit signature">
<span className={PrimeIcons.PENCIL + ' text-[10px]'} />
</WdTooltipWrapper>
</div>
)}
style={{ maxWidth: 26, minWidth: 26, width: 26 }}
bodyClassName="p-0 pl-1 pr-2"
/>
)}
</DataTable>
</>
)} )}
<WdTooltip <WdTooltip

View File

@@ -1,10 +1,14 @@
import { import {
GroupType, GroupType,
SignatureGroup, SignatureGroup,
SignatureGroupDE,
SignatureGroupENG, SignatureGroupENG,
SignatureGroupFR,
SignatureGroupRU, SignatureGroupRU,
SignatureKind, SignatureKind,
SignatureKindDE,
SignatureKindENG, SignatureKindENG,
SignatureKindFR,
SignatureKindRU, SignatureKindRU,
} from '@/hooks/Mapper/types'; } from '@/hooks/Mapper/types';
@@ -40,46 +44,58 @@ export const GROUPS: Record<SignatureGroup, GroupType> = {
[SignatureGroup.CosmicSignature]: { id: SignatureGroup.CosmicSignature, icon: '/icons/x_close14.png', w: 9, h: 9 }, [SignatureGroup.CosmicSignature]: { id: SignatureGroup.CosmicSignature, icon: '/icons/x_close14.png', w: 9, h: 9 },
}; };
export const MAPPING_GROUP_TO_ENG = { export const LANGUAGE_GROUP_MAPPINGS = {
// ENGLISH EN: {
[SignatureGroupENG.GasSite]: SignatureGroup.GasSite, [SignatureGroupENG.GasSite]: SignatureGroup.GasSite,
[SignatureGroupENG.RelicSite]: SignatureGroup.RelicSite, [SignatureGroupENG.RelicSite]: SignatureGroup.RelicSite,
[SignatureGroupENG.DataSite]: SignatureGroup.DataSite, [SignatureGroupENG.DataSite]: SignatureGroup.DataSite,
[SignatureGroupENG.OreSite]: SignatureGroup.OreSite, [SignatureGroupENG.OreSite]: SignatureGroup.OreSite,
[SignatureGroupENG.CombatSite]: SignatureGroup.CombatSite, [SignatureGroupENG.CombatSite]: SignatureGroup.CombatSite,
[SignatureGroupENG.Wormhole]: SignatureGroup.Wormhole, [SignatureGroupENG.Wormhole]: SignatureGroup.Wormhole,
[SignatureGroupENG.CosmicSignature]: SignatureGroup.CosmicSignature, [SignatureGroupENG.CosmicSignature]: SignatureGroup.CosmicSignature,
},
// RUSSIAN RU: {
[SignatureGroupRU.GasSite]: SignatureGroup.GasSite, [SignatureGroupRU.GasSite]: SignatureGroup.GasSite,
[SignatureGroupRU.RelicSite]: SignatureGroup.RelicSite, [SignatureGroupRU.RelicSite]: SignatureGroup.RelicSite,
[SignatureGroupRU.DataSite]: SignatureGroup.DataSite, [SignatureGroupRU.DataSite]: SignatureGroup.DataSite,
[SignatureGroupRU.OreSite]: SignatureGroup.OreSite, [SignatureGroupRU.OreSite]: SignatureGroup.OreSite,
[SignatureGroupRU.CombatSite]: SignatureGroup.CombatSite, [SignatureGroupRU.CombatSite]: SignatureGroup.CombatSite,
[SignatureGroupRU.Wormhole]: SignatureGroup.Wormhole, [SignatureGroupRU.Wormhole]: SignatureGroup.Wormhole,
[SignatureGroupRU.CosmicSignature]: SignatureGroup.CosmicSignature, [SignatureGroupRU.CosmicSignature]: SignatureGroup.CosmicSignature,
},
FR: {
[SignatureGroupFR.GasSite]: SignatureGroup.GasSite,
[SignatureGroupFR.RelicSite]: SignatureGroup.RelicSite,
[SignatureGroupFR.DataSite]: SignatureGroup.DataSite,
[SignatureGroupFR.OreSite]: SignatureGroup.OreSite,
[SignatureGroupFR.CombatSite]: SignatureGroup.CombatSite,
[SignatureGroupFR.Wormhole]: SignatureGroup.Wormhole,
[SignatureGroupFR.CosmicSignature]: SignatureGroup.CosmicSignature,
},
DE: {
[SignatureGroupDE.GasSite]: SignatureGroup.GasSite,
[SignatureGroupDE.RelicSite]: SignatureGroup.RelicSite,
[SignatureGroupDE.DataSite]: SignatureGroup.DataSite,
[SignatureGroupDE.OreSite]: SignatureGroup.OreSite,
[SignatureGroupDE.CombatSite]: SignatureGroup.CombatSite,
[SignatureGroupDE.Wormhole]: SignatureGroup.Wormhole,
[SignatureGroupDE.CosmicSignature]: SignatureGroup.CosmicSignature,
},
}; };
export const MAPPING_TYPE_TO_ENG = { // Flatten the structure for backward compatibility
// ENGLISH export const MAPPING_GROUP_TO_ENG: Record<string, SignatureGroup> = (() => {
[SignatureKindENG.CosmicSignature]: SignatureKind.CosmicSignature, const flattened: Record<string, SignatureGroup> = {};
[SignatureKindENG.CosmicAnomaly]: SignatureKind.CosmicAnomaly, for (const [, mappings] of Object.entries(LANGUAGE_GROUP_MAPPINGS)) {
[SignatureKindENG.Structure]: SignatureKind.Structure, Object.assign(flattened, mappings);
[SignatureKindENG.Ship]: SignatureKind.Ship, }
[SignatureKindENG.Deployable]: SignatureKind.Deployable, return flattened;
[SignatureKindENG.Drone]: SignatureKind.Drone, })();
// RUSSIAN export const getGroupIdByRawGroup = (val: string): SignatureGroup | undefined => {
[SignatureKindRU.CosmicSignature]: SignatureKind.CosmicSignature, return MAPPING_GROUP_TO_ENG[val] || undefined;
[SignatureKindRU.CosmicAnomaly]: SignatureKind.CosmicAnomaly,
[SignatureKindRU.Structure]: SignatureKind.Structure,
[SignatureKindRU.Ship]: SignatureKind.Ship,
[SignatureKindRU.Deployable]: SignatureKind.Deployable,
[SignatureKindRU.Drone]: SignatureKind.Drone,
}; };
export const getGroupIdByRawGroup = (val: string) => MAPPING_GROUP_TO_ENG[val as SignatureGroup];
export const SIGNATURE_WINDOW_ID = 'system_signatures_window'; export const SIGNATURE_WINDOW_ID = 'system_signatures_window';
export const SIGNATURE_SETTING_STORE_KEY = 'wanderer_system_signature_settings_v6_5'; export const SIGNATURE_SETTING_STORE_KEY = 'wanderer_system_signature_settings_v6_5';
@@ -123,7 +139,7 @@ export type Setting = {
name: string; name: string;
type: SettingsTypes; type: SettingsTypes;
isSeparator?: boolean; isSeparator?: boolean;
options?: { label: string; value: any }[]; options?: { label: string; value: number | string | boolean }[];
}; };
export enum SIGNATURES_DELETION_TIMING { export enum SIGNATURES_DELETION_TIMING {
@@ -208,3 +224,52 @@ export const SIGNATURE_DELETION_TIMEOUTS: SignatureDeletionTimingType = {
[SIGNATURES_DELETION_TIMING.IMMEDIATE]: 0, [SIGNATURES_DELETION_TIMING.IMMEDIATE]: 0,
[SIGNATURES_DELETION_TIMING.EXTENDED]: 30_000, [SIGNATURES_DELETION_TIMING.EXTENDED]: 30_000,
}; };
// Replace the flat structure with a nested structure by language
export const LANGUAGE_TYPE_MAPPINGS = {
EN: {
[SignatureKindENG.CosmicSignature]: SignatureKind.CosmicSignature,
[SignatureKindENG.CosmicAnomaly]: SignatureKind.CosmicAnomaly,
[SignatureKindENG.Structure]: SignatureKind.Structure,
[SignatureKindENG.Ship]: SignatureKind.Ship,
[SignatureKindENG.Deployable]: SignatureKind.Deployable,
[SignatureKindENG.Drone]: SignatureKind.Drone,
[SignatureKindENG.Starbase]: SignatureKind.Starbase,
},
RU: {
[SignatureKindRU.CosmicSignature]: SignatureKind.CosmicSignature,
[SignatureKindRU.CosmicAnomaly]: SignatureKind.CosmicAnomaly,
[SignatureKindRU.Structure]: SignatureKind.Structure,
[SignatureKindRU.Ship]: SignatureKind.Ship,
[SignatureKindRU.Deployable]: SignatureKind.Deployable,
[SignatureKindRU.Drone]: SignatureKind.Drone,
[SignatureKindRU.Starbase]: SignatureKind.Starbase,
},
FR: {
[SignatureKindFR.CosmicSignature]: SignatureKind.CosmicSignature,
[SignatureKindFR.CosmicAnomaly]: SignatureKind.CosmicAnomaly,
[SignatureKindFR.Structure]: SignatureKind.Structure,
[SignatureKindFR.Ship]: SignatureKind.Ship,
[SignatureKindFR.Deployable]: SignatureKind.Deployable,
[SignatureKindFR.Drone]: SignatureKind.Drone,
[SignatureKindFR.Starbase]: SignatureKind.Starbase,
},
DE: {
[SignatureKindDE.CosmicSignature]: SignatureKind.CosmicSignature,
[SignatureKindDE.CosmicAnomaly]: SignatureKind.CosmicAnomaly,
[SignatureKindDE.Structure]: SignatureKind.Structure,
[SignatureKindDE.Ship]: SignatureKind.Ship,
[SignatureKindDE.Deployable]: SignatureKind.Deployable,
[SignatureKindDE.Drone]: SignatureKind.Drone,
[SignatureKindDE.Starbase]: SignatureKind.Starbase,
},
};
// Flatten the structure for backward compatibility
export const MAPPING_TYPE_TO_ENG: Record<string, SignatureKind> = (() => {
const flattened: Record<string, SignatureKind> = {};
for (const [, mappings] of Object.entries(LANGUAGE_TYPE_MAPPINGS)) {
Object.assign(flattened, mappings);
}
return flattened;
})();

View File

@@ -19,10 +19,13 @@ export const useSystemSignaturesData = ({
onPendingChange, onPendingChange,
onLazyDeleteChange, onLazyDeleteChange,
onSignatureDeleted, onSignatureDeleted,
}: Omit<UseSystemSignaturesDataProps, 'deletionTiming'> & { onSignatureDeleted?: (deletedIds: string[]) => void }) => { }: Omit<UseSystemSignaturesDataProps, 'deletionTiming'> & {
onSignatureDeleted?: (deletedIds: string[]) => void;
}) => {
const { outCommand } = useMapRootState(); const { outCommand } = useMapRootState();
const [signatures, setSignatures, signaturesRef] = useRefState<ExtendedSystemSignature[]>([]); const [signatures, setSignatures, signaturesRef] = useRefState<ExtendedSystemSignature[]>([]);
const [selectedSignatures, setSelectedSignatures] = useState<ExtendedSystemSignature[]>([]); const [selectedSignatures, setSelectedSignatures] = useState<ExtendedSystemSignature[]>([]);
const [hasUnsupportedLanguage, setHasUnsupportedLanguage] = useState<boolean>(false);
const { pendingDeletionMapRef, processRemovedSignatures, clearPendingDeletions } = usePendingDeletions({ const { pendingDeletionMapRef, processRemovedSignatures, clearPendingDeletions } = usePendingDeletions({
systemId, systemId,
@@ -41,6 +44,7 @@ export const useSystemSignaturesData = ({
async (clipboardString: string) => { async (clipboardString: string) => {
const lazyDeleteValue = settings[SETTINGS_KEYS.LAZY_DELETE_SIGNATURES] as boolean; const lazyDeleteValue = settings[SETTINGS_KEYS.LAZY_DELETE_SIGNATURES] as boolean;
// Parse the incoming signatures
const incomingSignatures = parseSignatures( const incomingSignatures = parseSignatures(
clipboardString, clipboardString,
Object.keys(settings).filter(skey => skey in SignatureKind), Object.keys(settings).filter(skey => skey in SignatureKind),
@@ -50,6 +54,18 @@ export const useSystemSignaturesData = ({
return; return;
} }
// Check if any signatures might be using unsupported languages
// This is a basic heuristic: if we have signatures where the original group wasn't mapped
const clipboardRows = clipboardString.split('\n').filter(row => row.trim() !== '');
const detectedSignatureCount = clipboardRows.filter(row => row.match(/^[A-Z]{3}-\d{3}/)).length;
// If we detected valid IDs but got fewer parsed signatures, we might have language issues
if (detectedSignatureCount > 0 && incomingSignatures.length < detectedSignatureCount) {
setHasUnsupportedLanguage(true);
} else {
setHasUnsupportedLanguage(false);
}
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);
@@ -127,5 +143,6 @@ export const useSystemSignaturesData = ({
handleDeleteSelected, handleDeleteSelected,
handleSelectAll, handleSelectAll,
handlePaste, handlePaste,
hasUnsupportedLanguage,
}; };
}; };

View File

@@ -1,5 +1,8 @@
import { SignatureGroup, SignatureKind, SystemSignature } from '@/hooks/Mapper/types'; import { SignatureGroup, SignatureKind, SystemSignature } from '@/hooks/Mapper/types';
import { MAPPING_TYPE_TO_ENG } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts'; import {
MAPPING_GROUP_TO_ENG,
MAPPING_TYPE_TO_ENG,
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts';
export const parseSignatures = (value: string, availableKeys: string[]): SystemSignature[] => { export const parseSignatures = (value: string, availableKeys: string[]): SystemSignature[] => {
const outArr: SystemSignature[] = []; const outArr: SystemSignature[] = [];
@@ -14,13 +17,37 @@ export const parseSignatures = (value: string, availableKeys: string[]): SystemS
continue; continue;
} }
const kind = MAPPING_TYPE_TO_ENG[sigArrInfo[1] as SignatureKind]; // Extract the signature ID and check if it's valid (XXX-XXX format)
const sigId = sigArrInfo[0];
if (!sigId || !sigId.match(/^[A-Z]{3}-\d{3}$/)) {
continue;
}
// Try to map the kind, or fall back to CosmicSignature if unknown
const typeString = sigArrInfo[1];
let kind = SignatureKind.CosmicSignature;
// Try to map the kind using the flattened mapping
const mappedKind = MAPPING_TYPE_TO_ENG[typeString];
if (mappedKind && availableKeys.includes(mappedKind)) {
kind = mappedKind;
}
// Try to map the group, or fall back to CosmicSignature if unknown
const rawGroup = sigArrInfo[2];
let group = SignatureGroup.CosmicSignature;
// Try to map the group using the flattened mapping
const mappedGroup = MAPPING_GROUP_TO_ENG[rawGroup];
if (mappedGroup) {
group = mappedGroup;
}
const signature: SystemSignature = { const signature: SystemSignature = {
eve_id: sigArrInfo[0], eve_id: sigId,
kind: availableKeys.includes(kind) ? kind : SignatureKind.CosmicSignature, kind,
group: sigArrInfo[2] as SignatureGroup, group,
name: sigArrInfo[3], name: sigArrInfo[3] || 'Unknown',
type: '', type: '',
}; };

View File

@@ -78,6 +78,26 @@ export enum SignatureKindRU {
Starbase = 'Starbase', Starbase = 'Starbase',
} }
export enum SignatureKindFR {
CosmicSignature = 'Signature cosmique (type)',
CosmicAnomaly = 'Anomalie cosmique',
Structure = 'Structure',
Ship = 'Vaisseau',
Deployable = 'Déployable',
Drone = 'Drone',
Starbase = 'Base stellaire',
}
export enum SignatureKindDE {
CosmicSignature = 'Kosmische Signatur (typ)',
CosmicAnomaly = 'Kosmische Anomalie',
Structure = 'Struktur',
Ship = 'Schiff',
Deployable = 'Mobile Struktur',
Drone = 'Drohne',
Starbase = 'Sternenbasis',
}
export enum SignatureGroupENG { export enum SignatureGroupENG {
CosmicSignature = 'Cosmic Signature', CosmicSignature = 'Cosmic Signature',
Wormhole = 'Wormhole', Wormhole = 'Wormhole',
@@ -97,3 +117,23 @@ export enum SignatureGroupRU {
OreSite = 'Астероидный район', OreSite = 'Астероидный район',
CombatSite = 'Боевой район', CombatSite = 'Боевой район',
} }
export enum SignatureGroupFR {
CosmicSignature = 'Signature cosmique (groupe)',
Wormhole = 'Trou de ver',
GasSite = 'Site de gaz',
RelicSite = 'Site de reliques',
DataSite = 'Site de données',
OreSite = 'Site de minerai',
CombatSite = 'Site de combat',
}
export enum SignatureGroupDE {
CosmicSignature = 'Kosmische Signatur (gruppe)',
Wormhole = 'Wurmloch',
GasSite = 'Gasgebiet',
RelicSite = 'Reliktgebiet',
DataSite = 'Datengebiet',
OreSite = 'Mineraliengebiet',
CombatSite = 'Kampfgebiet',
}

View File

@@ -204,7 +204,7 @@ defmodule WandererApp.Api.MapSystemSignature do
:kind, :kind,
:group, :group,
:custom_info, :custom_info,
:updated, :deleted,
:inserted_at, :inserted_at,
:updated_at :updated_at
] ]

View File

@@ -97,7 +97,7 @@ defmodule WandererApp.Map.Server.SignaturesImpl do
%MapSystemSignature{deleted: true} = deleted_sig -> %MapSystemSignature{deleted: true} = deleted_sig ->
MapSystemSignature.update!( MapSystemSignature.update!(
deleted_sig, deleted_sig,
%{sig | deleted: false} Map.take(sig, [:name, :description, :kind, :group, :type, :custom_info, :deleted])
) )
_ -> _ ->
@@ -152,7 +152,11 @@ defmodule WandererApp.Map.Server.SignaturesImpl do
defp apply_update_signature(%MapSystemSignature{} = existing, update_params) defp apply_update_signature(%MapSystemSignature{} = existing, update_params)
when not is_nil(update_params) do when not is_nil(update_params) do
MapSystemSignature.update(existing, update_params) case MapSystemSignature.update(existing, update_params) do
{:ok, _} -> :ok
{:error, reason} ->
Logger.error("Failed to update signature #{existing.id}: #{inspect(reason)}")
end
end end
defp track_activity(event, map_id, solar_system_id, user_id, character_id, signatures) do defp track_activity(event, map_id, solar_system_id, user_id, character_id, signatures) do