mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-16 17:31:24 +01:00
feat(obsidian): add FMG ID index for instant note lookups
Problem: Every time you click on a burg/marker, it had to scan through all 13,496 vault files looking for a matching fmg-id. This was extremely slow and made the feature unusable for large vaults. Solution: Implement a smart index that maps fmg-id to file paths. How it works: - Index stored in memory (fmgIdIndex object) - Persisted to localStorage (survives page reloads) - Loaded on init, saved on changes - When looking up by fmg-id: 1. Check index first (instant!) 2. If found, verify file still exists and ID matches 3. If not in index, search vault and add to index - Automatically updates when notes are created/saved through FMG - Handles stale entries (file deleted/modified) Performance improvement: - Before: O(n) - scan all 13k files (very slow) - After: O(1) - instant lookup from index - First click on burg: May need to search (builds index) - Second click on same burg: Instant! Opens note directly This makes the Obsidian integration actually usable. Create a note once for a burg, and every time you click that burg again, it opens instantly.
This commit is contained in:
parent
a22b40e7ca
commit
f575631e30
2 changed files with 98 additions and 2 deletions
|
|
@ -20,6 +20,9 @@ const ObsidianBridge = (() => {
|
|||
ttl: 5 * 60 * 1000 // 5 minutes cache
|
||||
};
|
||||
|
||||
// Index: fmg-id → file path for fast lookups
|
||||
let fmgIdIndex = {};
|
||||
|
||||
// Initialize from localStorage
|
||||
function init() {
|
||||
const stored = localStorage.getItem("obsidianConfig");
|
||||
|
|
@ -31,6 +34,18 @@ const ObsidianBridge = (() => {
|
|||
ERROR && console.error("Failed to load Obsidian config:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Load FMG ID index from localStorage
|
||||
const storedIndex = localStorage.getItem("obsidianFmgIdIndex");
|
||||
if (storedIndex) {
|
||||
try {
|
||||
fmgIdIndex = JSON.parse(storedIndex);
|
||||
INFO && console.log(`Loaded FMG ID index with ${Object.keys(fmgIdIndex).length} entries`);
|
||||
} catch (error) {
|
||||
ERROR && console.error("Failed to load FMG ID index:", error);
|
||||
fmgIdIndex = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save configuration
|
||||
|
|
@ -108,6 +123,29 @@ const ObsidianBridge = (() => {
|
|||
INFO && console.log("Vault file cache cleared");
|
||||
}
|
||||
|
||||
// Save FMG ID index to localStorage
|
||||
function saveFmgIdIndex() {
|
||||
try {
|
||||
localStorage.setItem("obsidianFmgIdIndex", JSON.stringify(fmgIdIndex));
|
||||
DEBUG && console.log(`Saved FMG ID index with ${Object.keys(fmgIdIndex).length} entries`);
|
||||
} catch (error) {
|
||||
ERROR && console.error("Failed to save FMG ID index:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Add entry to FMG ID index
|
||||
function addToFmgIdIndex(fmgId, filePath) {
|
||||
if (!fmgId) return;
|
||||
fmgIdIndex[fmgId] = filePath;
|
||||
saveFmgIdIndex();
|
||||
DEBUG && console.log(`Added to index: ${fmgId} → ${filePath}`);
|
||||
}
|
||||
|
||||
// Get file path from FMG ID index
|
||||
function getFromFmgIdIndex(fmgId) {
|
||||
return fmgIdIndex[fmgId] || null;
|
||||
}
|
||||
|
||||
// Get all markdown files from vault (recursively, with caching)
|
||||
async function getVaultFiles(forceRefresh = false) {
|
||||
if (!config.enabled) {
|
||||
|
|
@ -374,9 +412,43 @@ const ObsidianBridge = (() => {
|
|||
}
|
||||
}
|
||||
|
||||
// Find note by FMG ID in frontmatter
|
||||
// Find note by FMG ID in frontmatter (with index for fast lookup)
|
||||
async function findNoteByFmgId(fmgId) {
|
||||
if (!fmgId) return null;
|
||||
|
||||
try {
|
||||
// First, check the index for instant lookup
|
||||
const indexedPath = getFromFmgIdIndex(fmgId);
|
||||
if (indexedPath) {
|
||||
INFO && console.log(`Found note in index: ${fmgId} → ${indexedPath}`);
|
||||
try {
|
||||
const content = await getNote(indexedPath);
|
||||
const {frontmatter} = parseFrontmatter(content);
|
||||
|
||||
// Verify the fmg-id still matches (file might have been modified)
|
||||
if (frontmatter["fmg-id"] === fmgId || frontmatter.fmgId === fmgId) {
|
||||
return {
|
||||
path: indexedPath,
|
||||
name: indexedPath.replace(/\.md$/, "").split("/").pop(),
|
||||
content,
|
||||
frontmatter
|
||||
};
|
||||
} else {
|
||||
// Index is stale, remove the entry
|
||||
WARN && console.warn(`Index entry stale for ${fmgId}, removing`);
|
||||
delete fmgIdIndex[fmgId];
|
||||
saveFmgIdIndex();
|
||||
}
|
||||
} catch (error) {
|
||||
// File no longer exists, remove from index
|
||||
WARN && console.warn(`Indexed file not found: ${indexedPath}, removing from index`);
|
||||
delete fmgIdIndex[fmgId];
|
||||
saveFmgIdIndex();
|
||||
}
|
||||
}
|
||||
|
||||
// Not in index or index was stale, search all files
|
||||
INFO && console.log(`Searching vault for fmg-id: ${fmgId}`);
|
||||
const files = await getVaultFiles();
|
||||
const mdFiles = files.filter(f => f.endsWith(".md"));
|
||||
|
||||
|
|
@ -386,6 +458,10 @@ const ObsidianBridge = (() => {
|
|||
const {frontmatter} = parseFrontmatter(content);
|
||||
|
||||
if (frontmatter["fmg-id"] === fmgId || frontmatter.fmgId === fmgId) {
|
||||
// Found it! Add to index for next time
|
||||
addToFmgIdIndex(fmgId, filePath);
|
||||
INFO && console.log(`Found note and added to index: ${fmgId} → ${filePath}`);
|
||||
|
||||
return {
|
||||
path: filePath,
|
||||
name: filePath.replace(/\.md$/, "").split("/").pop(),
|
||||
|
|
@ -560,7 +636,9 @@ Add your lore here...
|
|||
generateNoteTemplate,
|
||||
searchNotes,
|
||||
listAllNotes,
|
||||
listAllNotePaths
|
||||
listAllNotePaths,
|
||||
addToFmgIdIndex,
|
||||
getFromFmgIdIndex
|
||||
};
|
||||
})();
|
||||
|
||||
|
|
|
|||
|
|
@ -216,6 +216,13 @@ async function promptCreateNewNote(elementId, elementType, coordinates) {
|
|||
|
||||
const {frontmatter} = ObsidianBridge.parseFrontmatter(template);
|
||||
|
||||
// Add to FMG ID index for instant future lookups
|
||||
const fmgId = frontmatter["fmg-id"] || frontmatter.fmgId;
|
||||
if (fmgId) {
|
||||
ObsidianBridge.addToFmgIdIndex(fmgId, notePath);
|
||||
INFO && console.log(`New note added to index: ${fmgId} → ${notePath}`);
|
||||
}
|
||||
|
||||
resolve({
|
||||
path: notePath,
|
||||
name,
|
||||
|
|
@ -590,6 +597,17 @@ async function saveObsidianNote() {
|
|||
|
||||
try {
|
||||
await ObsidianBridge.updateNote(path, content);
|
||||
|
||||
// Update the FMG ID index if this note has an fmg-id
|
||||
if (elementId) {
|
||||
const {frontmatter} = ObsidianBridge.parseFrontmatter(content);
|
||||
const fmgId = frontmatter["fmg-id"] || frontmatter.fmgId;
|
||||
if (fmgId) {
|
||||
// Add to index using internal method
|
||||
ObsidianBridge.addToFmgIdIndex(fmgId, path);
|
||||
}
|
||||
}
|
||||
|
||||
showMarkdownEditor.originalContent = content;
|
||||
// Update the editor to show the new frontmatter
|
||||
byId("obsidianMarkdownEditor").value = content;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue