From 8664b8eb3c3fc19da75e1e2f370897578aab0a86 Mon Sep 17 00:00:00 2001 From: "Samir L. Boulema" Date: Sun, 12 Jul 2026 21:57:35 +0200 Subject: [PATCH] feat: Select parent folders of collection folders --- main.ts | 24 +++++++++++------------- src/collection.ts | 22 +++++++++------------- src/scryfall.ts | 26 +++++++++++++++----------- 3 files changed, 35 insertions(+), 37 deletions(-) diff --git a/main.ts b/main.ts index 5188127..3a0d521 100644 --- a/main.ts +++ b/main.ts @@ -6,9 +6,8 @@ import { DEFAULT_COLLECTION_FOLDER_PATH, DEFAULT_COLLECTION_NAME_COLUMN, hashCollectionContents, - processCollectionFiles, + mergeCollections, syncCollections, - syncCounts, } from "src/collection"; import { renderDecklist } from "src/renderer"; import { ObsidianPluginMtgSettings } from "src/settings"; @@ -54,23 +53,22 @@ export default class ObsidianPluginMtg extends Plugin { const collectionFolderPath = this.settings.collection?.folderPath || ""; if (file.parent?.path.startsWith(collectionFolderPath)) { this.collections = await syncCollections(vault, this.settings); - this.cardCounts = await syncCounts(vault, this.settings); + this.cardCounts = mergeCollections(this.collections); clearCache(); } } }); this.app.workspace.onLayoutReady(async () => { - const fileContents = await processCollectionFiles(vault, this.settings); - const hash = hashCollectionContents(fileContents); + this.collections = await syncCollections(vault, this.settings); + this.cardCounts = mergeCollections(this.collections); + + const hash = hashCollectionContents(this.collections); const savedData = await this.loadData(); if (savedData?.collectionHash === hash && savedData?.cardDataCache) { loadCache(savedData.cardDataCache); } - - this.collections = await syncCollections(vault, this.settings); - this.cardCounts = await syncCounts(vault, this.settings); }); this.addCommand({ @@ -115,11 +113,7 @@ export default class ObsidianPluginMtg extends Plugin { onunload() { void (async () => { - const fileContents = await processCollectionFiles( - this.app.vault, - this.settings - ); - const hash = hashCollectionContents(fileContents); + const hash = hashCollectionContents(this.collections); const data = await this.loadData() ?? {}; await this.saveData({ @@ -346,6 +340,10 @@ class FolderSuggestModal extends FuzzySuggestModal { this.app.vault.getFiles().forEach((file) => { if (file.extension === "csv" && file.parent) { folders.set(file.parent.path, file.parent); + + if (file.parent.parent) { + folders.set(file.parent.parent.path, file.parent.parent); + } } }); diff --git a/src/collection.ts b/src/collection.ts index 99eef79..7dc4c1f 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -90,19 +90,6 @@ export const processCollectionFiles = async ( )).filter((c): c is CardCollection => c !== null); }; -export const syncCounts = async ( - vault: Vault, - settings: ObsidianPluginMtgSettings -): Promise => { - const collections = await processCollectionFiles(vault, settings); - return collections.reduce((acc, collection) => { - Object.entries(collection.counts).forEach(([name, count]) => { - acc[name] = (acc[name] ?? 0) + count; - }); - return acc; - }, {} as CardCounts); -}; - export const syncCollections = async ( vault: Vault, settings: ObsidianPluginMtgSettings @@ -113,4 +100,13 @@ export const syncCollections = async ( export const hashCollectionContents = (contents: CardCollection[]): string => { const combined = contents.map(c => Object.entries(c.counts).join("")).join(""); return `${contents.length}-${combined.length}`; +}; + +export const mergeCollections = (collections: CardCollection[]): CardCounts => { + return collections.reduce((acc, collection) => { + Object.entries(collection.counts).forEach(([name, count]) => { + acc[name] = (acc[name] ?? 0) + count; + }); + return acc; + }, {} as CardCounts); }; \ No newline at end of file diff --git a/src/scryfall.ts b/src/scryfall.ts index b14c536..5f50b78 100644 --- a/src/scryfall.ts +++ b/src/scryfall.ts @@ -194,7 +194,8 @@ export const getMultipleCardData = async ( * @returns A record of card data indexed by normalized card name */ export const fetchCardDataFromScryfall = async ( - distinctCards: CardIdentifier[] + distinctCards: CardIdentifier[], + onProgress?: (fetched: number, total: number) => void ): Promise> => { const batches: CardIdentifier[][] = []; let currentBatch: CardIdentifier[] = []; @@ -210,14 +211,14 @@ export const fetchCardDataFromScryfall = async ( batches.push(currentBatch); - const cardDataInBatches: ScryfallResponse[] = await Promise.all( - batches.map((batch) => getMultipleCardData(batch)) - ); - const cardDataByCardId: Record = {}; + let fetched = 0; + const total = distinctCards.length; - cardDataInBatches.forEach((batch) => { - batch.data.forEach((card: CardData) => { + for (const batch of batches) { + const result: ScryfallResponse = await getMultipleCardData(batch); + + result.data.forEach((card: CardData) => { if (card.name) { cardDataByCardId[nameToId(card.name)] = card; } @@ -225,7 +226,10 @@ export const fetchCardDataFromScryfall = async ( cardDataByCardId[nameToId(card.printed_name)] = card; } }); - }); + + fetched += batch.length; + onProgress?.(fetched, total); + } return cardDataByCardId; }; @@ -252,13 +256,13 @@ export const fetchCardDataFromScryfallCached = async ( }); if (uncachedCards.length > 0) { - const freshData = await fetchCardDataFromScryfall(uncachedCards); + const freshData = await fetchCardDataFromScryfall(uncachedCards, onProgress); Object.entries(freshData).forEach(([key, data]) => { setCachedCardData(key, data); }); + } else { + onProgress?.(distinctCards.length, distinctCards.length); } - onProgress?.(distinctCards.length, distinctCards.length); - return getCachedCardData(); }; \ No newline at end of file