diff --git a/src/commands/navigation.ts b/src/commands/navigation.ts index 04a516f..a23fd4f 100644 --- a/src/commands/navigation.ts +++ b/src/commands/navigation.ts @@ -264,7 +264,7 @@ export const jumpToScene: CommandBuilder = (plugin) => ({ }, }); -export const revealProjectFolder: CommandBuilder = (_plugin) => ({ +export const revealProjectFolder: CommandBuilder = (plugin) => ({ id: "longform-reveal-project-folder", name: "Reveal current project in navigation", checkCallback(checking) { @@ -279,8 +279,8 @@ export const revealProjectFolder: CommandBuilder = (_plugin) => ({ // NOTE: This is private Obsidian API, and may fail or change at any time. try { - const parent = app.vault.getAbstractFileByPath(path).parent; - (app as any).internalPlugins.plugins[ + const parent = plugin.app.vault.getAbstractFileByPath(path).parent; + (plugin.app as any).internalPlugins.plugins[ "file-explorer" ].instance.revealInFolder(parent); } catch (error) { diff --git a/src/commands/templates.ts b/src/commands/templates.ts index 7e1faed..ea1dad4 100644 --- a/src/commands/templates.ts +++ b/src/commands/templates.ts @@ -63,7 +63,7 @@ const callbackForFormat = ( } })(); - insertDraftIntoFrontmatter(file.path, newDraft).then(() => { + insertDraftIntoFrontmatter(view.app, file.path, newDraft).then(() => { selectedDraftVaultPath.set(file.path); }); }; diff --git a/src/model/draft-utils.ts b/src/model/draft-utils.ts index 82208e1..be2c8ef 100644 --- a/src/model/draft-utils.ts +++ b/src/model/draft-utils.ts @@ -1,4 +1,4 @@ -import { TFile, Vault } from "obsidian"; +import { App, TFile, Vault } from "obsidian"; import { get, type Writable } from "svelte/store"; import type { Draft, IndentedScene, MultipleSceneDraft } from "./types"; @@ -16,15 +16,17 @@ type SceneInsertionLocation = { }; export async function createScene( + app: App, path: string, draft: MultipleSceneDraft ): Promise { const template = draft.sceneTemplate ?? get(pluginSettings).sceneTemplate; - createNoteWithPotentialTemplate(path, template); + createNoteWithPotentialTemplate(app, path, template); app.workspace.openLinkText(path, "/", false); } export async function insertScene( + app: App, draftsStore: Writable, draft: MultipleSceneDraft, sceneName: string, @@ -57,7 +59,7 @@ export async function insertScene( return d; }); }); - await createScene(newScenePath, draft); + await createScene(app, newScenePath, draft); } export function setDraftOnFrontmatterObject( @@ -178,7 +180,11 @@ export function formatSceneNumber(numbering: number[]): string { return numbering.join("."); } -export async function insertDraftIntoFrontmatter(path: string, draft: Draft) { +export async function insertDraftIntoFrontmatter( + app: App, + path: string, + draft: Draft +) { const exists = await app.vault.adapter.exists(path); if (!exists) { await app.vault.create(path, ""); diff --git a/src/model/migration.ts b/src/model/migration.ts index 17f2cc2..42f87b3 100644 --- a/src/model/migration.ts +++ b/src/model/migration.ts @@ -93,7 +93,7 @@ export async function migrate(settings: LongformPluginSettings, app: App) { sceneTemplate: null, }; - await insertDraftIntoFrontmatter(vaultPath, draft); + await insertDraftIntoFrontmatter(app, vaultPath, draft); await moveScenes( normalizePath( `${projectPath}/${project.draftsPath}/${oldDraft.folder}/` @@ -134,7 +134,7 @@ export async function migrate(settings: LongformPluginSettings, app: App) { sceneTemplate: null, }; - await insertDraftIntoFrontmatter(vaultPath, draft); + await insertDraftIntoFrontmatter(app, vaultPath, draft); await moveScenes( normalizePath( `${projectPath}/${project.draftsPath}/${oldDraft.folder}/` diff --git a/src/model/note-utils.ts b/src/model/note-utils.ts index a36607f..f844f21 100644 --- a/src/model/note-utils.ts +++ b/src/model/note-utils.ts @@ -1,5 +1,5 @@ import { last, sum } from "lodash"; -import type { TFile } from "obsidian"; +import type { App, TFile } from "obsidian"; import type { Draft, DraftWordCounts } from "./types"; @@ -14,20 +14,21 @@ export function fileNameFromPath(path: string): string { * @param template Path to template to use. */ export async function createNoteWithPotentialTemplate( + app: App, path: string, template: string | null ): Promise { - const file = await createNote(path); + const file = await createNote(app, path); if (template && file) { let contents = ""; let pluginUsed = ""; try { - if (isTemplaterEnabled()) { + if (isTemplaterEnabled(app)) { pluginUsed = "Templater"; - contents = await createWithTemplater(file, template); - } else if (isTemplatesEnabled()) { + contents = await createWithTemplater(app, file, template); + } else if (isTemplatesEnabled(app)) { pluginUsed = "Core Templates"; - contents = await createWithTemplates(template); + contents = await createWithTemplates(app, template); } } catch (error) { console.error(`[Longform] Error using plugin [${pluginUsed}]:`, error); @@ -45,6 +46,7 @@ export async function createNoteWithPotentialTemplate( * @returns `null` if it fails to create the note. `TFile` for the new note, if successful. */ export async function createNote( + app: App, path: string, initialContent = "" ): Promise { @@ -72,15 +74,16 @@ export async function createNote( } } -function isTemplaterEnabled(): boolean { +function isTemplaterEnabled(app: App): boolean { return !!(app as any).plugins.getPlugin("templater-obsidian"); } -function isTemplatesEnabled(): boolean { +function isTemplatesEnabled(app: App): boolean { return !!(app as any).internalPlugins.getEnabledPluginById("templates"); } async function createWithTemplater( + app: App, file: TFile, templatePath: string ): Promise { @@ -101,8 +104,10 @@ async function createWithTemplater( return await templaterPlugin.templater.read_and_parse_template(runningConfig); } -async function createWithTemplates(templatePath: string): Promise { - console.log(templatePath); +async function createWithTemplates( + app: App, + templatePath: string +): Promise { const corePlugin = (app as any).internalPlugins.getEnabledPluginById( "templates" ); diff --git a/src/model/store-vault-sync.ts b/src/model/store-vault-sync.ts index a2e096c..b7742ad 100644 --- a/src/model/store-vault-sync.ts +++ b/src/model/store-vault-sync.ts @@ -44,6 +44,7 @@ export function resolveIfLongformFile( * Thus, keeps both store and vault in sync. */ export class StoreVaultSync { + private app: App; private vault: Vault; private metadataCache: MetadataCache; @@ -53,6 +54,7 @@ export class StoreVaultSync { private pathsToIgnoreNextChange: Set = new Set(); constructor(app: App) { + this.app = app; this.vault = app.vault; this.metadataCache = app.metadataCache; } @@ -370,7 +372,7 @@ export class StoreVaultSync { let fm = null; try { - await app.fileManager.processFrontMatter( + await this.app.fileManager.processFrontMatter( fileWithMetadata.file, (_fm) => { fm = _fm; @@ -464,12 +466,12 @@ export class StoreVaultSync { } private async writeDraftFrontmatter(draft: Draft) { - const file = app.vault.getAbstractFileByPath(draft.vaultPath); + const file = this.app.vault.getAbstractFileByPath(draft.vaultPath); if (!file || !(file instanceof TFile)) { return; } - await app.fileManager.processFrontMatter(file, (fm) => { + await this.app.fileManager.processFrontMatter(file, (fm) => { setDraftOnFrontmatterObject(fm, draft); }); } diff --git a/src/view/compile/add-step-modal/index.ts b/src/view/compile/add-step-modal/index.ts index 1a13bdb..9bfcb05 100644 --- a/src/view/compile/add-step-modal/index.ts +++ b/src/view/compile/add-step-modal/index.ts @@ -1,6 +1,7 @@ import { App, Modal } from "obsidian"; import AddStepModal from "./AddStepModal.svelte"; +import { appContext } from "src/view/utils"; export default class AddStepModalContainer extends Modal { constructor(app: App) { @@ -13,7 +14,7 @@ export default class AddStepModalContainer extends Modal { contentEl.createEl("h1", { text: "Add Compile Step to Workfow" }); const entrypoint = contentEl.createDiv("longform-add-step-root"); - const context = new Map(); + const context = appContext(this); context.set("close", () => this.close()); new AddStepModal({ diff --git a/src/view/explorer/ExplorerPane.ts b/src/view/explorer/ExplorerPane.ts index eac4c09..ee17450 100644 --- a/src/view/explorer/ExplorerPane.ts +++ b/src/view/explorer/ExplorerPane.ts @@ -22,6 +22,7 @@ import { insertScene } from "src/model/draft-utils"; import NewDraftModal from "src/view/project-lifecycle/new-draft-modal"; import { UndoManager } from "../undo/undo-manager"; import { ignoreScene } from "./scene-menu-items"; +import { appContext } from "../utils"; export const VIEW_TYPE_LONGFORM_EXPLORER = "VIEW_TYPE_LONGFORM_EXPLORER"; @@ -74,7 +75,7 @@ export class ExplorerPane extends ItemView { } ); - const context = new Map(); + const context = appContext(this); context.set("undoManager", this.undoManager); @@ -119,6 +120,7 @@ export class ExplorerPane extends ItemView { // Context function for creating new scene notes given a path context.set("onNewScene", async (name: string) => { await insertScene( + this.app, drafts, get(selectedDraft) as MultipleSceneDraft, name, @@ -158,7 +160,7 @@ export class ExplorerPane extends ItemView { .indexOf(file.name.split(".md")[0]); if (relativeTo >= 0) { - insertScene(drafts, draft, sceneName, this.app.vault, { + insertScene(this.app, drafts, draft, sceneName, this.app.vault, { at, relativeTo, }); diff --git a/src/view/explorer/ProjectDetails.svelte b/src/view/explorer/ProjectDetails.svelte index 8f3d6c3..911c68b 100644 --- a/src/view/explorer/ProjectDetails.svelte +++ b/src/view/explorer/ProjectDetails.svelte @@ -19,6 +19,9 @@ activeFile, } from "../stores"; import DraftList from "./DraftList.svelte"; + import { useApp } from "../utils"; + + const app = useApp(); let showMetdata = true; let showWordCount = true; diff --git a/src/view/explorer/SceneList.svelte b/src/view/explorer/SceneList.svelte index 6294742..63b43a2 100644 --- a/src/view/explorer/SceneList.svelte +++ b/src/view/explorer/SceneList.svelte @@ -16,9 +16,11 @@ import type { UndoManager } from "src/view/undo/undo-manager"; import { cloneDeep } from "lodash"; import { scenePath } from "src/model/scene-navigation"; - import { selectElementContents } from "../utils"; + import { selectElementContents, useApp } from "../utils"; import { addAll, addScene, ignoreAll, ignoreScene } from "./scene-menu-items"; + const app = useApp(); + let currentDraftIndex: number = -1; $: if ($selectedDraft) { currentDraftIndex = $drafts.findIndex( @@ -76,7 +78,6 @@ const nextScene = index < scenes.length - 1 ? scenes[index + 1] : false; const path = makeScenePath($selectedDraft as MultipleSceneDraft, title); - // TODO: Get app by some other means? const file = app.vault.getAbstractFileByPath(path); let status = undefined; if (file && file instanceof TFile) { diff --git a/src/view/project-lifecycle/new-draft-modal/index.ts b/src/view/project-lifecycle/new-draft-modal/index.ts index 42a8fc8..ad74282 100644 --- a/src/view/project-lifecycle/new-draft-modal/index.ts +++ b/src/view/project-lifecycle/new-draft-modal/index.ts @@ -5,6 +5,7 @@ import { selectedDraft, selectedDraftVaultPath } from "src/model/stores"; import type { Draft } from "src/model/types"; import { get } from "svelte/store"; import NewDraftModal from "./NewDraftModal.svelte"; +import { appContext } from "src/view/utils"; export default class NewDraftModalContainer extends Modal { constructor(app: App) { @@ -21,7 +22,7 @@ export default class NewDraftModalContainer extends Modal { }); const entrypoint = contentEl.createDiv("longform-add-create-draft-root"); - const context = new Map(); + const context = appContext(this); context.set("close", () => this.close()); context.set( @@ -39,7 +40,7 @@ export default class NewDraftModalContainer extends Modal { titleInFrontmatter: true, draftTitle, }; - await insertDraftIntoFrontmatter(newVaultPath, newDraft); + await insertDraftIntoFrontmatter(this.app, newVaultPath, newDraft); selectedDraftVaultPath.set(newVaultPath); this.app.workspace.openLinkText(newVaultPath, "/", false); } else { @@ -71,7 +72,7 @@ export default class NewDraftModalContainer extends Modal { draftTitle, scenes: copyScenes ? draft.scenes : [], }; - await insertDraftIntoFrontmatter(newVaultPath, newDraft); + await insertDraftIntoFrontmatter(this.app, newVaultPath, newDraft); selectedDraftVaultPath.set(newVaultPath); } this.close(); diff --git a/src/view/project-lifecycle/new-project-modal/index.ts b/src/view/project-lifecycle/new-project-modal/index.ts index b5a5be2..dcc17f5 100644 --- a/src/view/project-lifecycle/new-project-modal/index.ts +++ b/src/view/project-lifecycle/new-project-modal/index.ts @@ -8,6 +8,7 @@ import type { } from "src/model/types"; import { selectedTab } from "src/view/stores"; import NewProjectModal from "./NewProjectModal.svelte"; +import { appContext } from "src/view/utils"; export default class NewProjectModalContainer extends Modal { private parent: TFolder; @@ -25,7 +26,7 @@ export default class NewProjectModalContainer extends Modal { }); const entrypoint = contentEl.createDiv("longform-add-create-project-root"); - const context = new Map(); + const context = appContext(this); context.set("close", () => this.close()); context.set( "createProject", @@ -72,7 +73,7 @@ export default class NewProjectModalContainer extends Modal { } })(); - await insertDraftIntoFrontmatter(path, newDraft); + await insertDraftIntoFrontmatter(this.app, path, newDraft); selectedDraftVaultPath.set(path); selectedTab.set(format === "scenes" ? "Scenes" : "Project"); if (format === "single") { diff --git a/src/view/utils.ts b/src/view/utils.ts index cd09e96..fd0997d 100644 --- a/src/view/utils.ts +++ b/src/view/utils.ts @@ -1,4 +1,5 @@ -import { Platform } from "obsidian"; +import { App, Modal, Platform, View } from "obsidian"; +import { getContext } from "svelte"; export function selectElementContents(el: HTMLElement) { const range = document.createRange(); @@ -24,3 +25,13 @@ export function isValidFilename(name: string): boolean { } return true; } + +export function appContext(view: View | Modal): Map { + const context = new Map(); + context.set("app", view.app); + return context; +} + +export function useApp(): App { + return getContext("app") as App; +}