Adds new letter-based and chained-letter variables for automatic bookmark name formatting. The bookmark index calculation is updated to support this and correctly identify parent systems.

- feat(bookmarks): Add letter-based and chained-letter format variables
- feat(signatures): Calculate and store chained letter-based bookmark index
- refactor(bookmarks): Update index calculation to use both system UUID and solar system ID
- docs(settings): Update bookmark format placeholder and helper text with new variables
This commit is contained in:
Drew Bonasera
2026-04-27 22:53:20 -04:00
parent 46849238d9
commit f4fc3a48e0
5 changed files with 53 additions and 15 deletions
@@ -138,10 +138,13 @@ export const SystemLinkSignatureDialog = ({ data, setVisible }: SystemLinkSignat
let bookmarkIndex = info.bookmark_index;
if (!bookmarkIndex) {
const calculated = calculateBookmarkIndex(systemSignatures, data.solar_system_source.toString(), signature.eve_id);
const sourceSystem = systems.find((s: any) => s.system_static_info?.solar_system_id === data.solar_system_source);
const systemUuid = sourceSystem?.id || data.solar_system_source.toString();
const calculated = calculateBookmarkIndex(systemSignatures, systemUuid, data.solar_system_source.toString(), signature.eve_id);
bookmarkIndex = calculated.index;
info.bookmark_index = calculated.index;
info.bookmark_index_chained = calculated.chained;
info.bookmark_index_chained_letters = calculated.chainedLetters;
updatedSignature = { ...signature, custom_info: JSON.stringify(info) };
}
@@ -52,8 +52,8 @@ export const SIGNATURES_CHECKBOXES_PROPS: SettingsListItem[] = [
prop: UserSettingsRemoteProps.bookmark_name_format,
label: 'Bookmark Name Format',
type: 'text',
placeholder: 'e.g. {i} {sig_letters} {dest_type} {size} {time_status} {mass_status}',
helperText: 'Variables: {i}, {I}, {sig_letters}, {sig}, {dest_type}, {type}, {size}, {mass}, {time_status}, {mass_status}, {temporary_name}, {description}',
placeholder: 'e.g. {chain_index_letters} {sig_letters} {dest_type} {size} {time_status} {mass_status}',
helperText: 'Variables: {index}, {chain_index}, {index_letter}, {chain_index_letters}, {sig_letters}, {sig}, {dest_type}, {type}, {size}, {mass}, {time_status}, {mass_status}, {temporary_name}, {description}',
},
];
@@ -131,10 +131,13 @@ export const SignatureSettings = ({ systemId, show, onHide, signatureData }: Map
let bookmarkIndex = info.bookmark_index;
if (!bookmarkIndex) {
const calculated = calculateBookmarkIndex(systemSignatures, systemId, out.eve_id);
const currentSystem = systems.find((s: any) => s.id === systemId);
const solarSystemIdStr = currentSystem?.system_static_info?.solar_system_id?.toString() || systemId;
const calculated = calculateBookmarkIndex(systemSignatures, systemId, solarSystemIdStr, out.eve_id);
bookmarkIndex = calculated.index;
info.bookmark_index = calculated.index;
info.bookmark_index_chained = calculated.chained;
info.bookmark_index_chained_letters = calculated.chainedLetters;
out.custom_info = JSON.stringify(info);
}
@@ -69,17 +69,29 @@ const formatDestString = (dest: string | null | undefined): string => {
return dest.charAt(0).toUpperCase() + dest.slice(1);
};
const numberToLetters = (num: number): string => {
let letters = '';
while (num > 0) {
const mod = (num - 1) % 26;
letters = String.fromCharCode(65 + mod) + letters;
num = Math.floor((num - mod) / 26);
}
return letters;
};
export const calculateBookmarkIndex = (
systemSignatures: Record<string, SystemSignature[]>,
currentSystemId: string,
currentSystemUuid: string,
currentSolarSystemId: string,
currentEveId: string,
): { index: number; chained: string } => {
): { index: number; chained: string; chainedLetters: string } => {
let parentBookmarkIndex: string | undefined;
let parentBookmarkIndexLetters: string | undefined;
for (const [sysId, sigs] of Object.entries(systemSignatures)) {
if (sysId === currentSystemId.toString()) continue;
if (sysId === currentSystemUuid || sysId === currentSolarSystemId) continue;
const parentSigs = sigs.filter(sig => sig.linked_system?.solar_system_id?.toString() === currentSystemId.toString());
const parentSigs = sigs.filter(sig => sig.linked_system?.solar_system_id?.toString() === currentSolarSystemId);
for (const parentSig of parentSigs) {
const parentInfo = parseSignatureCustomInfo(parentSig.custom_info);
if (parentInfo.bookmark_index_chained != null) {
@@ -91,12 +103,24 @@ export const calculateBookmarkIndex = (
parentBookmarkIndex = String(parentInfo.bookmark_index);
}
}
if (parentInfo.bookmark_index_chained_letters != null) {
if (!parentBookmarkIndexLetters || String(parentInfo.bookmark_index_chained_letters).length < parentBookmarkIndexLetters.length) {
parentBookmarkIndexLetters = String(parentInfo.bookmark_index_chained_letters);
}
}
}
}
const currentSigs = systemSignatures[currentSystemId.toString()] || [];
const currentSigsRaw = [
...(systemSignatures[currentSystemUuid] || []),
...(systemSignatures[currentSolarSystemId] || [])
];
const existingIndices = currentSigs
// Deduplicate in case both keys map to the same or overlapping arrays
const uniqueCurrentSigs = Array.from(new Map(currentSigsRaw.map(sig => [sig.eve_id, sig])).values());
const existingIndices = uniqueCurrentSigs
.filter(sig => sig.eve_id !== currentEveId)
.map(sig => parseSignatureCustomInfo(sig.custom_info).bookmark_index)
.filter((i): i is number => typeof i === 'number' && i > 0);
@@ -107,8 +131,9 @@ export const calculateBookmarkIndex = (
}
const chained = parentBookmarkIndex !== undefined ? `${parentBookmarkIndex}${i}` : `${i}`;
const chainedLetters = parentBookmarkIndexLetters !== undefined ? `${parentBookmarkIndexLetters}${i}` : numberToLetters(i);
return { index: i, chained };
return { index: i, chained, chainedLetters };
};
export const formatBookmarkName = (
@@ -121,11 +146,17 @@ export const formatBookmarkName = (
let result = formatStr;
const info = parseSignatureCustomInfo(signature.custom_info);
// Replace {i}
result = result.replace(/\{i\}/g, () => bookmarkIndex.toString());
// Replace {index}
result = result.replace(/\{index\}/g, () => bookmarkIndex.toString());
// Replace {I}
result = result.replace(/\{I\}/g, () => info.bookmark_index_chained || bookmarkIndex.toString());
// Replace {chain_index}
result = result.replace(/\{chain_index\}/g, () => info.bookmark_index_chained || bookmarkIndex.toString());
// Replace {index_letter}
result = result.replace(/\{index_letter\}/g, () => numberToLetters(bookmarkIndex));
// Replace {chain_index_letters}
result = result.replace(/\{chain_index_letters\}/g, () => info.bookmark_index_chained_letters || info.bookmark_index_chained || bookmarkIndex.toString());
// Replace {sig_letters} (first 3 chars of eve_id)
const sigLetters = signature.eve_id.substring(0, 3).toUpperCase();
@@ -35,6 +35,7 @@ export type SignatureCustomInfo = {
mass_status?: number;
bookmark_index?: number;
bookmark_index_chained?: string;
bookmark_index_chained_letters?: string;
};
export type SystemSignature = {