Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions src/model/draft-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,20 @@ type SceneInsertionLocation = {
export async function createScene(
app: App,
path: string,
index: number,
draft: MultipleSceneDraft,
open: boolean
): Promise<void> {
const template = draft.sceneTemplate ?? get(pluginSettings).sceneTemplate;
createNoteWithPotentialTemplate(app, path, template);
const note = await createNoteWithPotentialTemplate(app, path, template);
if (note === null) return;

if (get(pluginSettings).writeProperty) {
await app.fileManager.processFrontMatter(note, (fm) => {
fm["longform-order"] = index;
});
}

if (open) {
app.workspace.openLinkText(path, "/", false);
}
Expand Down Expand Up @@ -63,7 +72,14 @@ export async function insertScene(
return d;
});
});
await createScene(app, newScenePath, draft, open);

await createScene(
app,
newScenePath,
draft.scenes.findIndex((s) => s.title === sceneName),
draft,
open
);
}

export function setDraftOnFrontmatterObject(
Expand Down
8 changes: 6 additions & 2 deletions src/model/note-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ export function fileNameFromPath(path: string): string {
* Prefers Templater, then the core Templates plugin, then a plain note without using the template.
* @param path Path to note to create.
* @param template Path to template to use.
*
* @returns `null` if it fails to create the note. `TFile` for the new note, if successful.
*/
export async function createNoteWithPotentialTemplate(
app: App,
path: string,
template: string | null
): Promise<void> {
): Promise<TFile | null> {
const file = await createNote(app, path);
if (template && file) {
if (!file) return null;
if (template) {
let contents = "";
let pluginUsed = "";
try {
Expand All @@ -37,6 +40,7 @@ export async function createNoteWithPotentialTemplate(
await app.vault.adapter.write(path, contents);
}
}
return file;
}

/**
Expand Down
75 changes: 71 additions & 4 deletions src/model/store-vault-sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,20 @@ import { cloneDeep, isEqual } from "lodash";
import { get, type Unsubscriber } from "svelte/store";

import type { Draft } from "./types";
import { drafts as draftsStore, selectedDraftVaultPath } from "./stores";
import {
drafts as draftsStore,
pluginSettings,
waitingForSync,
selectedDraftVaultPath,
} from "./stores";
import {
arraysToIndentedScenes,
formatSceneNumber,
numberScenes,
setDraftOnFrontmatterObject,
} from "src/model/draft-utils";
import { fileNameFromPath } from "./note-utils";
import { findScene, sceneFolderPath } from "./scene-navigation";
import { pluginSettings } from "./stores";
import { waitingForSync } from "./stores";
import { findScene, sceneFolderPath, scenePath } from "./scene-navigation";

type FileWithMetadata = {
file: TFile;
Expand Down Expand Up @@ -568,9 +573,71 @@ export class StoreVaultSync {
await this.app.fileManager.processFrontMatter(file, (fm) => {
setDraftOnFrontmatterObject(fm, draft);
});

// for multi-scene projects, optionally set a property on each scene that holds its order within the project
if (get(pluginSettings).writeProperty) {
if (draft.format === "scenes") {
const writes: Promise<void>[] = [];
const sceneNumbers = numberScenes(draft.scenes);
sceneNumbers.forEach((numberedScene, index) => {
const sceneFilePath = scenePath(
numberedScene.title,
draft,
this.app.vault
);

const sceneFile = this.app.vault.getAbstractFileByPath(sceneFilePath);
// false if a folder, or not found
if (!(sceneFile instanceof TFile)) {
return;
}
writes.push(
writeSceneNumbers(
this.app,
sceneFile,
index,
numberedScene.numbering
)
);
});

await Promise.all(writes);
}
}
}
}

export function syncSceneIndices(app: App): void | Promise<void[]> {
const writes: Promise<void>[] = [];
get(draftsStore).forEach((draft) => {
if (draft.format !== "scenes") return;
numberScenes(draft.scenes).map((numberedScene, index) => {
const sceneFilePath = scenePath(numberedScene.title, draft, app.vault);

const sceneFile = app.vault.getAbstractFileByPath(sceneFilePath);
// false if a folder, or not found
if (!(sceneFile instanceof TFile)) {
return;
}
return writeSceneNumbers(app, sceneFile, index, numberedScene.numbering);
});
});
if (writes.length === 0) return;
return Promise.all(writes);
}

function writeSceneNumbers(
app: App,
file: TFile,
index: number,
numbering: number[]
) {
return app.fileManager.processFrontMatter(file, (fm) => {
fm["longform-order"] = index;
fm["longform-number"] = formatSceneNumber(numbering);
});
}

const ESCAPED_CHARACTERS = new Set("/&$^+.()=!|[]{},".split(""));
function ignoredPatternToRegex(pattern: string): RegExp {
let regex = "";
Expand Down
41 changes: 23 additions & 18 deletions src/model/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export interface LongformPluginSettings {
waitForSync: boolean;
fallbackWaitEnabled: boolean;
fallbackWaitTime: number;
writeProperty: boolean;
// DEPRECATED. To be removed in future, needed now for migrations.
projects: {
[path: string]: {
Expand Down Expand Up @@ -126,13 +127,14 @@ export const DEFAULT_SETTINGS: LongformPluginSettings = {
sessionFile: DEFAULT_SESSION_FILE,
numberScenes: false,
sceneTemplate: null,
writeProperty: false,
projects: {},
waitForSync: false,
fallbackWaitEnabled: true,
fallbackWaitTime: 5,
};

export const TRACKED_SETTINGS_PATHS = [
export const TRACKED_SETTINGS_PATHS: (keyof LongformPluginSettings)[] = [
"version",
"projects",
"selectedDraftVaultPath",
Expand All @@ -152,22 +154,25 @@ export const TRACKED_SETTINGS_PATHS = [
"waitForSync",
"fallbackWaitEnabled",
"fallbackWaitTime",
"writeProperty",
];

export const PASSTHROUGH_SAVE_SETTINGS_PATHS = [
"sessionStorage",
"userScriptFolder",
"showWordCountInStatusBar",
"startNewSessionEachDay",
"sessionGoal",
"applyGoalTo",
"notifyOnGoal",
"countDeletionsForGoal",
"keepSessionCount",
"sessionFile",
"numberScenes",
"sceneTemplate",
"waitForSync",
"fallbackWaitEnabled",
"fallbackWaitTime",
];
export const PASSTHROUGH_SAVE_SETTINGS_PATHS: (keyof LongformPluginSettings)[] =
[
"sessionStorage",
"userScriptFolder",
"showWordCountInStatusBar",
"startNewSessionEachDay",
"sessionGoal",
"applyGoalTo",
"notifyOnGoal",
"countDeletionsForGoal",
"keepSessionCount",
"sessionFile",
"numberScenes",
"sceneTemplate",
"waitForSync",
"fallbackWaitEnabled",
"fallbackWaitTime",
"writeProperty",
];
19 changes: 19 additions & 0 deletions src/view/settings/LongformSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { pluginSettings, userScriptSteps } from "src/model/stores";
import { FolderSuggest } from "./folder-suggest";
import { DEFAULT_SESSION_FILE } from "src/model/types";
import { FileSuggest } from "./file-suggest";
import { syncSceneIndices } from "src/model/store-vault-sync";

export class LongformSettingsTab extends PluginSettingTab {
plugin: LongformPlugin;
Expand Down Expand Up @@ -65,6 +66,24 @@ export class LongformSettingsTab extends PluginSettingTab {
});
});

new Setting(containerEl)
.setName("Write scene index to frontmatter")
.setDesc(
"If enabled, will add a scene index, and scene number, to the frontmatter of scene files."
)
.addToggle((toggle) => {
toggle.setValue(settings.writeProperty);
toggle.onChange((value) => {
pluginSettings.update((settings) => ({
...settings,
writeProperty: value,
}));
if (value) {
syncSceneIndices(this.app);
}
});
});

new Setting(containerEl).setName("Compile").setHeading();

new Setting(containerEl)
Expand Down