Skip to content

Commit

Permalink
Make entity folders configurable (#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
cwegrzyn authored May 24, 2024
1 parent 1580fd3 commit 926e091
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 58 deletions.
4 changes: 3 additions & 1 deletion src/settings/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Emittery from "emittery";
import Handlebars from "handlebars";
import { ClockFileAdapter } from "tracks/clock-file";
import { ProgressTrackFileAdapter, ProgressTrackInfo } from "tracks/progress";
import Emittery from "emittery";

export class ForgedPluginSettings {
advanceProgressTemplate: string =
Expand All @@ -14,6 +14,8 @@ export class ForgedPluginSettings {
"> [!progress] [[{{clockPath}}|{{clockInfo.name}}]] clock created\n>**Progress:** {{clockInfo.clock.progress}} out of {{clockInfo.clock.segments}} segments filled\n> \n> **Cause of Advance:**\n\n";
oraclesFolder: string = "";

defaultProgressTrackFolder: string = "Progress";

momentumResetTemplate: string =
"> [!mechanics] {{character.name}} burned momentum: {{oldValue}} -> {{newValue}}\n\n";
meterAdjTemplate: string =
Expand Down
14 changes: 14 additions & 0 deletions src/settings/ui.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ForgedPlugin from "index";
import { PluginSettingTab, Setting, type App } from "obsidian";
import { ForgedPluginSettings } from "settings";
import { FolderTextSuggest } from "utils/ui/settings/folder";

export class ForgedSettingTab extends PluginSettingTab {
plugin: ForgedPlugin;
Expand Down Expand Up @@ -34,6 +35,19 @@ export class ForgedSettingTab extends PluginSettingTab {
.onChange((value) => this.updateSetting("oraclesFolder", value)),
);

new Setting(containerEl)
.setName("Default progress track folder")
.setDesc("Create progress tracks in this folder by default.")
.addSearch((search) => {
new FolderTextSuggest(this.app, search.inputEl);
search
.setPlaceholder("Type the name of a folder")
.setValue(settings.defaultProgressTrackFolder)
.onChange((value) =>
this.updateSetting("defaultProgressTrackFolder", value),
);
});

new Setting(containerEl)
.setName("Use character system")
.setDesc(
Expand Down
21 changes: 15 additions & 6 deletions src/tracks/commands.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ForgedPlugin from "index";
import { appendNodesToMoveOrMechanicsBlock } from "mechanics/editor";
import { createClockNode, createProgressNode } from "mechanics/node-builders";
import { App, Editor, MarkdownView, TFolder, stringifyYaml } from "obsidian";
import { App, Editor, MarkdownView, stringifyYaml } from "obsidian";
import { ForgedPluginSettings, createProgressTemplate } from "settings";
import { vaultProcess } from "../utils/obsidian";
import { CustomSuggestModal } from "../utils/suggest";
Expand Down Expand Up @@ -93,21 +93,30 @@ export async function createProgressTrack(
editor: Editor,
): Promise<void> {
const trackInput: {
targetFolder: string;
fileName: string;
name: string;
tracktype: string;
track: ProgressTrack;
} = await new Promise((onAccept, onReject) => {
new ProgressTrackCreateModal(plugin.app, onAccept, onReject).open();
new ProgressTrackCreateModal(
plugin.app,
{ targetFolder: plugin.settings.defaultProgressTrackFolder },
onAccept,
onReject,
).open();
});

const track =
ProgressTrackFileAdapter.newFromTrack(trackInput).expect("invalid track");

// TODO: where these are created should be configurable
const progressFolder = plugin.app.vault.getAbstractFileByPath("Progress");
if (!(progressFolder instanceof TFolder)) {
throw new Error("Expected 'Progress' to be folder");
let progressFolder = plugin.app.vault.getFolderByPath(
trackInput.targetFolder,
);
if (!progressFolder) {
progressFolder = await plugin.app.vault.createFolder(
trackInput.targetFolder,
);
}

// TODO: figure out the templating for this
Expand Down
94 changes: 43 additions & 51 deletions src/tracks/progress-create.ts
Original file line number Diff line number Diff line change
@@ -1,85 +1,51 @@
import {
App,
FuzzyMatch,
Modal,
SearchComponent,
Setting,
TextComponent,
prepareFuzzySearch,
normalizePath,
} from "obsidian";
import { generateObsidianFilename } from "utils/filename";
import { processMatches } from "../utils/suggest";
import { TextInputSuggest } from "../utils/ui/suggest";
import { FolderTextSuggest } from "utils/ui/settings/folder";
import { GenericTextSuggest } from "utils/ui/settings/generic-text-suggest";
import { ChallengeRanks, ProgressTrack } from "./progress";

class GenericTextSuggest extends TextInputSuggest<FuzzyMatch<string>> {
constructor(
app: App,
inputEl: HTMLInputElement,
public readonly items: string[],
) {
super(app, inputEl);
}
getSuggestions(inputStr: string): FuzzyMatch<string>[] {
const searchFn = prepareFuzzySearch(inputStr);
return this.items
.flatMap((item) => {
const match = searchFn(item);
if (match) {
return [{ item, match }];
} else {
return [];
}
})
.sort((a, b) => a.match.score - b.match.score);
}
renderSuggestion({ item, match }: FuzzyMatch<string>, el: HTMLElement): void {
if (item == null) return;

el.createDiv(undefined, (div) => {
processMatches(
item,
match,
(text) => {
div.appendText(text);
},
(text) => {
div.createEl("strong", { text });
},
);
});
// if (renderExtras != null) {
// renderExtras(match, el);
// }
}
selectSuggestion({ item }: FuzzyMatch<string>): void {
this.inputEl.value = item;
this.inputEl.trigger("input");
this.close();
}
}
export type ProgressTrackCreateResultType = {
rank: ChallengeRanks;
progress: number;
name: string;
tracktype: string;
fileName: string;
targetFolder: string;
};

export class ProgressTrackCreateModal extends Modal {
public result = {
public result: ProgressTrackCreateResultType = {
rank: ChallengeRanks.Dangerous,
progress: 0,
name: "",
tracktype: "",
fileName: "",
targetFolder: "",
};

public accepted: boolean = false;

constructor(
app: App,
defaults: Partial<ProgressTrackCreateResultType> = {},
protected readonly onAccept: (arg: {
name: string;
tracktype: string;
targetFolder: string;
fileName: string;
track: ProgressTrack;
}) => void,
protected readonly onCancel: () => void,
) {
super(app);
Object.assign(this.result, defaults);
}

onOpen(): void {
Expand All @@ -105,6 +71,31 @@ export class ProgressTrackCreateModal extends Modal {
})),
);

let folderComponent!: SearchComponent;
const folderSetting = new Setting(contentEl)
.setName("Target folder")
.addSearch((search) => {
new FolderTextSuggest(this.app, search.inputEl);
folderComponent = search
.setPlaceholder("Choose a folder")
.setValue(this.result.targetFolder)
.onChange((newFolder) => {
this.result.targetFolder = newFolder;
const normalized = normalizePath(newFolder);
if (this.app.vault.getFolderByPath(normalized)) {
folderSetting.setDesc(
`Creating track in existing folder '${normalized}'`,
);
} else {
folderSetting.setDesc(
`Creating track in new folder '${normalized}`,
);
}
});
});

folderComponent.onChanged();

// TODO: since the string value equals the display string, i don't actually know if this
// is working as intended with the options
new Setting(contentEl).setName("Rank").addDropdown((dropdown) =>
Expand Down Expand Up @@ -158,6 +149,7 @@ export class ProgressTrackCreateModal extends Modal {
name: this.result.name,
tracktype: this.result.tracktype,
fileName: this.result.fileName,
targetFolder: this.result.targetFolder,
track: ProgressTrack.create_({
rank: this.result.rank,
progress: this.result.progress,
Expand Down
24 changes: 24 additions & 0 deletions src/utils/ui/settings/folder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { TFolder } from "obsidian";
import { TextInputSuggest } from "../suggest";

export class FolderTextSuggest extends TextInputSuggest<TFolder> {
getSuggestions(inputStr: string): TFolder[] {
const searchStr = inputStr.toLowerCase();

return this.app.vault
.getAllLoadedFiles()
.filter(
(file): file is TFolder =>
file instanceof TFolder &&
file.path.toLowerCase().contains(searchStr),
);
}
renderSuggestion(folder: TFolder, el: HTMLElement): void {
el.setText(folder.path);
}
selectSuggestion(item: TFolder): void {
this.inputEl.value = item.path;
this.inputEl.trigger("input");
this.close();
}
}
53 changes: 53 additions & 0 deletions src/utils/ui/settings/generic-text-suggest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { App, FuzzyMatch, prepareFuzzySearch } from "obsidian";
import { processMatches } from "utils/suggest";
import { TextInputSuggest } from "../suggest";

export class GenericTextSuggest extends TextInputSuggest<FuzzyMatch<string>> {
constructor(
app: App,
inputEl: HTMLInputElement,
public readonly items: string[],
) {
super(app, inputEl);
}

getSuggestions(inputStr: string): FuzzyMatch<string>[] {
const searchFn = prepareFuzzySearch(inputStr);
return this.items
.flatMap((item) => {
const match = searchFn(item);
if (match) {
return [{ item, match }];
} else {
return [];
}
})
.sort((a, b) => a.match.score - b.match.score);
}

renderSuggestion({ item, match }: FuzzyMatch<string>, el: HTMLElement): void {
if (item == null) return;

el.createDiv(undefined, (div) => {
processMatches(
item,
match,
(text) => {
div.appendText(text);
},
(text) => {
div.createEl("strong", { text });
},
);
});
// if (renderExtras != null) {
// renderExtras(match, el);
// }
}

selectSuggestion({ item }: FuzzyMatch<string>): void {
this.inputEl.value = item;
this.inputEl.trigger("input");
this.close();
}
}

0 comments on commit 926e091

Please sign in to comment.