mirror of
https://github.com/alexkurowski/solo-toolkit.git
synced 2026-07-22 10:10:32 +00:00
Store default cards inside config folder for pasting into notes
This commit is contained in:
parent
9566e4916c
commit
5ea59eedc3
6 changed files with 121 additions and 36 deletions
File diff suppressed because one or more lines are too long
|
|
@ -7,6 +7,9 @@ import {
|
|||
} from "./settings";
|
||||
import { SoloToolkitView, VIEW_TYPE } from "./view";
|
||||
import { soloToolkitExtension } from "./extension";
|
||||
import { exportDeck } from "./utils/deck";
|
||||
import deckImages from "./icons/deck";
|
||||
import tarotImages from "./icons/tarot";
|
||||
|
||||
export default class SoloToolkitPlugin extends Plugin {
|
||||
settings: SoloToolkitSettings;
|
||||
|
|
@ -15,6 +18,8 @@ export default class SoloToolkitPlugin extends Plugin {
|
|||
await this.loadSettings();
|
||||
|
||||
registerIcons();
|
||||
await exportDeck(this.app.vault, "standard", deckImages);
|
||||
await exportDeck(this.app.vault, "tarot", tarotImages);
|
||||
|
||||
this.registerView(
|
||||
VIEW_TYPE,
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export class CustomDeck {
|
|||
if (this.supportedExtensions.includes(child.extension)) {
|
||||
this.deckCards.push(child);
|
||||
} else if (child.extension === "md") {
|
||||
this.vault.cachedRead(child).then((content: string) => {
|
||||
this.vault.read(child).then((content: string) => {
|
||||
if (!content) return;
|
||||
|
||||
const lines = content.split("\n").map(trim).filter(identity);
|
||||
|
|
@ -67,9 +67,10 @@ export class CustomDeck {
|
|||
});
|
||||
}
|
||||
}
|
||||
if (child instanceof TFolder) {
|
||||
this.parseFolder(child);
|
||||
}
|
||||
// NOTE: Commented out to skip nested folders
|
||||
// if (child instanceof TFolder) {
|
||||
// this.parseFolder(child);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +93,7 @@ export class CustomDeck {
|
|||
} catch (error) {
|
||||
return {
|
||||
image: "",
|
||||
flip: randomFrom(this.flip),
|
||||
flip: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
import { TFile } from "obsidian";
|
||||
import {
|
||||
arrayBufferToBase64,
|
||||
base64ToArrayBuffer,
|
||||
TFile,
|
||||
Vault,
|
||||
} from "obsidian";
|
||||
import { randomFrom } from "./dice";
|
||||
import { shuffle } from "./helpers";
|
||||
|
||||
|
|
@ -6,41 +11,107 @@ export interface Card {
|
|||
image: string;
|
||||
flip?: number;
|
||||
file?: TFile;
|
||||
path?: string;
|
||||
}
|
||||
|
||||
type Path = string;
|
||||
|
||||
const deckMemo: Record<string, string[]> = {};
|
||||
|
||||
export class DefaultDeck {
|
||||
vault: Vault;
|
||||
type: string;
|
||||
cards: string[];
|
||||
deckCards: string[];
|
||||
excludedKeys: string[];
|
||||
cards: Path[];
|
||||
deckCards: Path[];
|
||||
cardsLength: number = 0;
|
||||
flip: number[] = [0, 2];
|
||||
|
||||
constructor(type: string, data: Record<string, string>) {
|
||||
constructor(type: string, vault: Vault, excludedKeys: string[] = []) {
|
||||
this.vault = vault;
|
||||
this.type = type;
|
||||
|
||||
this.excludedKeys = excludedKeys;
|
||||
this.cards = [];
|
||||
this.deckCards = Object.values(data);
|
||||
this.deckCards = [];
|
||||
this.parseFolder();
|
||||
this.shuffle();
|
||||
}
|
||||
|
||||
update(data: Record<string, string>) {
|
||||
this.deckCards = Object.values(data);
|
||||
update(excludedKeys: string[] = []) {
|
||||
this.excludedKeys = excludedKeys;
|
||||
this.deckCards = [];
|
||||
this.parseFolder();
|
||||
}
|
||||
|
||||
parseFolder() {
|
||||
const folderName = this.type.toLowerCase();
|
||||
const folderPath =
|
||||
this.vault.configDir + "/plugins/solo-rpg-toolkit/decks/" + folderName;
|
||||
if (deckMemo[folderName]) {
|
||||
for (const key of deckMemo[folderName]) {
|
||||
if (this.excludedKeys.includes(key)) continue;
|
||||
const fileName = `${key}.png`;
|
||||
this.deckCards.push(folderPath + "/" + fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async draw(): Promise<Card> {
|
||||
if (!this.cards.length) this.shuffle();
|
||||
const value = this.cards.pop() || "";
|
||||
return {
|
||||
image: "data:image/jpeg;base64," + value,
|
||||
flip: randomFrom(this.flip),
|
||||
};
|
||||
const path = this.cards.pop() || "";
|
||||
|
||||
try {
|
||||
if (!path) throw "No cards";
|
||||
const bytes = await this.vault.adapter.readBinary(path);
|
||||
const contentType = "image/png";
|
||||
const image = `data:${contentType};base64,` + arrayBufferToBase64(bytes);
|
||||
return {
|
||||
image,
|
||||
flip: randomFrom(this.flip),
|
||||
path,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
image: "",
|
||||
flip: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
shuffle() {
|
||||
this.cards = [...this.deckCards];
|
||||
shuffle(this.cards);
|
||||
this.cardsLength = this.cards.length;
|
||||
}
|
||||
|
||||
size(): [number, number] {
|
||||
return [this.cards.length, this.deckCards.length];
|
||||
return [this.cards.length, this.cardsLength];
|
||||
}
|
||||
}
|
||||
|
||||
export const exportDeck = async (
|
||||
vault: Vault,
|
||||
folderName: string,
|
||||
data: Record<string, string>
|
||||
) => {
|
||||
const adapter = vault.adapter;
|
||||
const basePath =
|
||||
vault.configDir + "/plugins/solo-rpg-toolkit/decks/" + folderName;
|
||||
|
||||
try {
|
||||
await adapter.mkdir(basePath);
|
||||
await Promise.all(
|
||||
Object.keys(data).map((key) => {
|
||||
const filename = `${key}.png`;
|
||||
return adapter.writeBinary(
|
||||
basePath + "/" + filename,
|
||||
base64ToArrayBuffer(data[key].trim())
|
||||
);
|
||||
})
|
||||
);
|
||||
deckMemo[folderName] = Object.keys(data);
|
||||
} catch (error) {
|
||||
// Failed to export deck images
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ import { SoloToolkitView as View } from "./index";
|
|||
import { Card, DefaultDeck, clickToCopyImage, clickToCopy } from "../utils";
|
||||
import { TabSelect } from "./shared/tabselect";
|
||||
import { CustomDeck } from "src/utils/customdeck";
|
||||
import deckImages, { jokerImages } from "../icons/deck";
|
||||
import tarotImages from "../icons/tarot";
|
||||
|
||||
const MAX_REMEMBER_SIZE = 100;
|
||||
|
||||
|
|
@ -54,12 +52,10 @@ export class DeckView {
|
|||
|
||||
// Populate layout
|
||||
this.createDefaultDeck(
|
||||
"srt:Standard",
|
||||
this.view.settings.deckJokers
|
||||
? { ...deckImages, ...jokerImages }
|
||||
: deckImages
|
||||
"Standard",
|
||||
this.view.settings.deckJokers ? [] : ["JokerBlack", "JokerRed"]
|
||||
);
|
||||
this.createDefaultDeck("srt:Tarot", tarotImages);
|
||||
this.createDefaultDeck("Tarot", []);
|
||||
|
||||
if (this.view.settings.customDeckRoot) {
|
||||
const folder = this.view.app.vault.getFolderByPath(
|
||||
|
|
@ -107,7 +103,7 @@ export class DeckView {
|
|||
}
|
||||
|
||||
addResult(card: DrawnCard, immediate = false) {
|
||||
const { image, flip, file } = card;
|
||||
const { image, flip, file, path } = card;
|
||||
|
||||
const parentElClass = ["deck-result", "image-result-content"];
|
||||
if (flip) parentElClass.push(`deck-flip${flip}`);
|
||||
|
|
@ -141,10 +137,22 @@ export class DeckView {
|
|||
} else {
|
||||
clickToCopy(`![[${file.path}]]`)(event);
|
||||
}
|
||||
} else if (path) {
|
||||
const resourcePath =
|
||||
this.view.app.vault.adapter.getResourcePath(path);
|
||||
if (flip) {
|
||||
clickToCopy(``)(event);
|
||||
} else {
|
||||
clickToCopy(``)(event);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case "path":
|
||||
if (file) clickToCopy(file.path)(event);
|
||||
if (file) {
|
||||
clickToCopy(file.path)(event);
|
||||
} else if (path) {
|
||||
clickToCopy(path)(event);
|
||||
}
|
||||
return;
|
||||
case "png":
|
||||
clickToCopyImage(image, flip || 0)(event);
|
||||
|
|
@ -165,16 +173,19 @@ export class DeckView {
|
|||
}
|
||||
}
|
||||
|
||||
createDefaultDeck(tabName: string, data: Record<string, string>) {
|
||||
const label = tabName.replace("srt:", "");
|
||||
createDefaultDeck(tabName: string, excludedKeys: string[]) {
|
||||
this.tabContentEls[tabName] = this.tabContainerEl.createDiv("deck-buttons");
|
||||
this.tabSelect.addOption(tabName, label);
|
||||
this.tabSelect.addOption(tabName, tabName);
|
||||
|
||||
const deck = this.decks[tabName];
|
||||
if (deck && deck instanceof DefaultDeck) {
|
||||
deck.update(data);
|
||||
deck.update(excludedKeys);
|
||||
} else {
|
||||
this.decks[tabName] = new DefaultDeck(tabName, data);
|
||||
this.decks[tabName] = new DefaultDeck(
|
||||
tabName,
|
||||
this.view.app.vault,
|
||||
excludedKeys
|
||||
);
|
||||
}
|
||||
|
||||
new ButtonComponent(this.tabContentEls[tabName])
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ export class WordView {
|
|||
const templates: string[] = [];
|
||||
const values: CustomTable = { [DEFAULT]: [] };
|
||||
|
||||
this.view.app.vault.cachedRead(file).then((content: string) => {
|
||||
this.view.app.vault.read(file).then((content: string) => {
|
||||
if (!content) return;
|
||||
|
||||
const lines = content.split("\n").map(trim).filter(identity);
|
||||
|
|
|
|||
Loading…
Reference in a new issue