Skip to content

Commit

Permalink
Merge pull request #15 from chhoumann/v1.6.1
Browse files Browse the repository at this point in the history
  • Loading branch information
chhoumann authored May 25, 2021
2 parents 235a3fe + 3659a6b commit 3706703
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 65 deletions.
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "metaedit",
"name": "MetaEdit",
"version": "1.6.1",
"version": "1.6.2",
"minAppVersion": "0.12.0",
"description": "MetaEdit helps you manage your metadata.",
"author": "Christian B. B. Houmann",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "metaedit",
"version": "1.6.1",
"version": "1.6.2",
"description": "MetaEdit helps you manage your metadata.",
"main": "main.js",
"scripts": {
Expand Down
8 changes: 5 additions & 3 deletions src/Modals/GenericPrompt/GenericPrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@ export default class GenericPrompt extends Modal {
private input: string;
public waitForClose: Promise<string>;

public static Prompt(app: App, header: string, placeholder?: string, value?: string): Promise<string> {
const newPromptModal = new GenericPrompt(app, header, placeholder, value);
public static Prompt(app: App, header: string, placeholder?: string, value?: string, suggestValues?: string[]): Promise<string> {
const newPromptModal = new GenericPrompt(app, header, placeholder, value, suggestValues);
return newPromptModal.waitForClose;
}

private constructor(app: App, header: string, placeholder?: string, value?: string) {
private constructor(app: App, header: string, placeholder?: string, value?: string, suggestValues?: string[]) {
super(app);

this.modalContent = new GenericPromptContent({
target: this.contentEl,
props: {
app,
header,
placeholder,
value,
suggestValues,
onSubmit: (input: string) => {
this.input = input;
this.close();
Expand Down
18 changes: 16 additions & 2 deletions src/Modals/GenericPrompt/GenericPromptContent.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
<script lang="ts">
import {onMount} from "svelte";
import {GenericTextSuggester} from "./genericTextSuggester";
import type {App} from "obsidian";
export let app: App;
export let header: string = "";
export let placeholder: string = "";
export let value: string = "";
export let onSubmit: (value: string) => void;
export let suggestValues: string[];
let suggester: GenericTextSuggester;
let inputEl: HTMLInputElement;
onMount(() => {
if (suggestValues && suggestValues.length > 0)
suggester = new GenericTextSuggester(app, inputEl, suggestValues);
inputEl.select();
inputEl.focus();
})
Expand All @@ -22,5 +30,11 @@

<div class="metaEditPrompt">
<h1 style="text-align: center">{header}</h1>
<input class="metaEditPromptInput" bind:this={inputEl} autofocus style="width: 100%;" on:keydown={submit} type="text" placeholder={placeholder} bind:value={value}>
<input bind:this={inputEl}
bind:value={value}
class="metaEditPromptInput"
on:keydown={submit}
placeholder={placeholder}
style="width: 100%;"
type="text">
</div>
28 changes: 28 additions & 0 deletions src/Modals/GenericPrompt/genericTextSuggester.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {TextInputSuggest} from "../../suggest";
import type {App} from "obsidian";

export class GenericTextSuggester extends TextInputSuggest<string> {

constructor(public app: App, public inputEl: HTMLInputElement, private items: string[]) {
super(app, inputEl);
}

getSuggestions(inputStr: string): string[] {
const inputLowerCase: string = inputStr.toLowerCase();
return this.items.map(item => {
if (item.toLowerCase().contains(inputLowerCase))
return item;
});
}

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

renderSuggestion(value: string, el: HTMLElement): void {
if (value)
el.setText(value);
}
}
19 changes: 17 additions & 2 deletions src/Modals/metaEditSuggester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {Property} from "../parser";
import {MAIN_SUGGESTER_OPTIONS, newDataView, newYaml} from "../constants";
import {MetaType} from "../Types/metaType";
import {concat} from "svelte-preprocess/dist/modules/utils";
import type {AutoProperty} from "../Types/autoProperty";

export default class MetaEditSuggester extends FuzzySuggestModal<Property> {
public app: App;
Expand All @@ -13,6 +14,7 @@ export default class MetaEditSuggester extends FuzzySuggestModal<Property> {
private readonly data: Property[];
private readonly options: Property[];
private controller: MetaController;
private suggestValues: string[];

constructor(app: App, plugin: MetaEdit, data: Property[], file: TFile, controller: MetaController) {
super(app);
Expand All @@ -23,6 +25,7 @@ export default class MetaEditSuggester extends FuzzySuggestModal<Property> {
this.controller = controller;
this.options = MAIN_SUGGESTER_OPTIONS;

this.setSuggestValues();

this.setInstructions([
{command: "❌", purpose: "Delete property"},
Expand Down Expand Up @@ -51,7 +54,7 @@ export default class MetaEditSuggester extends FuzzySuggestModal<Property> {

async onChooseItem(item: Property, evt: MouseEvent | KeyboardEvent): Promise<void> {
if (item.content === newYaml) {
const newProperty = await this.controller.createNewProperty();
const newProperty = await this.controller.createNewProperty(this.suggestValues);
if (!newProperty) return null;

const {propName, propValue} = newProperty;
Expand All @@ -60,7 +63,7 @@ export default class MetaEditSuggester extends FuzzySuggestModal<Property> {
}

if (item.content === newDataView) {
const newProperty = await this.controller.createNewProperty();
const newProperty = await this.controller.createNewProperty(this.suggestValues);
if (!newProperty) return null;

const {propName, propValue} = newProperty;
Expand Down Expand Up @@ -123,4 +126,16 @@ export default class MetaEditSuggester extends FuzzySuggestModal<Property> {

return purged;
}

private setSuggestValues() {
const autoProps = this.plugin.settings.AutoProperties.properties;

this.suggestValues = autoProps.reduce((arr: string[], val: AutoProperty) => {
if (!this.data.find(prop => val.name === prop.key || val.name.startsWith('#'))) {
arr.push(val.name);
}

return arr;
}, []);
}
}
4 changes: 2 additions & 2 deletions src/Settings/metaEditSettingsTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export class MetaEditSettingsTab extends PluginSettingTab {
.setDesc("Quick switch for values you know the value of.")
.addToggle(toggle => {
toggle
.setTooltip("Toggle Progress Properties")
.setTooltip("Toggle Auto Properties")
.setValue(this.plugin.settings.AutoProperties.enabled)
.onChange(async value => {
if (value === this.plugin.settings.AutoProperties.enabled) return;
Expand Down Expand Up @@ -126,7 +126,7 @@ export class MetaEditSettingsTab extends PluginSettingTab {
.setDesc("Hide these properties from the menu.")
.addToggle(toggle => {
toggle
.setTooltip("Toggle Progress Properties")
.setTooltip("Toggle Ignored Properties")
.setValue(this.plugin.settings.IgnoredProperties.enabled)
.onChange(async value => {
if (value === this.plugin.settings.IgnoredProperties.enabled) return;
Expand Down
4 changes: 4 additions & 0 deletions src/Types/datedFileCacheItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface DatedFileCacheItem {
content: string,
updateTime: number
}
91 changes: 45 additions & 46 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,34 @@ import {LinkMenu} from "./Modals/LinkMenu";
import type {Property} from "./parser";
import type {IMetaEditApi} from "./IMetaEditApi";
import {MetaEditApi} from "./MetaEditApi";
import {UniqueQueue} from "./uniqueQueue";
import {UpdatedFileCache} from "./updatedFileCache";

export default class MetaEdit extends Plugin {
public settings: MetaEditSettings;
public linkMenu: LinkMenu;
public api: IMetaEditApi;
private controller: MetaController;
private updatedFileCache: { [fileName: string]: { content: string, updateTime: number } } = {};
private onModifyCallback = debounce(async (file: TAbstractFile) => {
if (file instanceof TFile) {
await this.onModifyProxy(file, async (pFile, fileContent) => {
if (this.settings.ProgressProperties.enabled) {
await this.updateProgressProperties(pFile);
}
if (this.settings.KanbanHelper.enabled) {
await this.kanbanHelper(pFile, fileContent);
}
})
}
}, 4000, false);
private updateFileQueue: UniqueQueue<TFile>;
private updatedFileCache: UpdatedFileCache;
private update = debounce(async () => {
while (!this.updateFileQueue.isEmpty()) {
const file = this.updateFileQueue.dequeue();

if (this.settings.ProgressProperties.enabled) {
await this.updateProgressProperties(file);
}
if (this.settings.KanbanHelper.enabled) {
await this.kanbanHelper(file);
}
}
}, 5000, true);

async onload() {
this.controller = new MetaController(this.app, this);
this.updateFileQueue = new UniqueQueue<TFile>();
this.updatedFileCache = new UpdatedFileCache();

console.log('Loading MetaEdit');

await this.loadSettings();
Expand Down Expand Up @@ -83,19 +89,22 @@ export default class MetaEdit extends Plugin {
}

public getCurrentFile(): TFile {
try {
const currentFile = this.app.workspace.getActiveFile();
const currentFile = this.abstractFileToMarkdownTFile(this.app.workspace.getActiveFile());

if (currentFile.extension === "md")
return currentFile;

this.logError("file is not a markdown file.");
return null;
}
catch (e) {
if (!currentFile) {
this.logError("could not get current file content.");
return null;
}

return currentFile;
}

public abstractFileToMarkdownTFile(file: TAbstractFile): TFile {
if (file instanceof TFile && file.extension === "md")
return file;

this.logError("file is not a markdown file.");
return null;
}

public onModifyCallbackToggle(enable: boolean) {
Expand Down Expand Up @@ -137,39 +146,29 @@ export default class MetaEdit extends Plugin {
return files;
}

private async updateProgressProperties(file: TFile) {
const data = await this.controller.getPropertiesInFile(file);
if (!data) return;
private onModifyCallback = async (file: TAbstractFile) => await this.onModify(file);

await this.controller.handleProgressProps(data, file);
}
private async onModify(file: TAbstractFile) {
const outfile: TFile = this.abstractFileToMarkdownTFile(file);
if (!outfile) return;

private async onModifyProxy(file: TFile, callback: (file: TFile, fileContent: string) => void) {
const fileContent = await this.app.vault.read(file);
const fileContent = await this.app.vault.cachedRead(outfile);
if (!this.updatedFileCache.set(file.path, fileContent)) return;

if (!this.updatedFileCache[file.name] || fileContent !== this.updatedFileCache[file.name].content) {
this.updatedFileCache[file.name] = {
content: fileContent,
updateTime: Date.now(),
};

await callback(file, fileContent);
if (this.updateFileQueue.enqueue(outfile)) {
await this.update();
}

this.cleanCache();
}

private cleanCache() {
const five_minutes = 18000;
private async updateProgressProperties(file: TFile) {
const data = await this.controller.getPropertiesInFile(file);
if (!data) return;

for (let cacheItem in this.updatedFileCache) {
if (this.updatedFileCache[cacheItem].updateTime < Date.now() - five_minutes) {
delete this.updatedFileCache[cacheItem];
}
}
await this.controller.handleProgressProps(data, file);
}

private async kanbanHelper(file: TFile, fileContent: string) {
private async kanbanHelper(file: TFile) {
const fileContent = await this.app.vault.read(file);
const boards = this.settings.KanbanHelper.boards;
const board = boards.find(board => board.boardName === file.basename);
const fileCache = this.app.metadataCache.getFileCache(file);
Expand Down
13 changes: 6 additions & 7 deletions src/metaController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,12 @@ export default class MetaController {
if (!enabled) return;

const tasks = this.app.metadataCache.getFileCache(file)?.listItems?.filter(li => li.task);
if (!tasks) return;
let total: number = 0, complete: number = 0, incomplete: number = 0;

if (tasks) {
total = tasks.length;
complete = tasks.filter(i => i.task != " ").length;
incomplete = total - complete;
}
total = tasks.length;
complete = tasks.filter(i => i.task != " ").length;
incomplete = total - complete;

const props = await this.progressPropHelper(properties, meta, {total, complete, incomplete});
await this.updateMultipleInFile(props, file);
Expand All @@ -139,8 +138,8 @@ export default class MetaController {
}
}

public async createNewProperty() {
let propName = await GenericPrompt.Prompt(this.app, "Enter a property name", "Property");
public async createNewProperty(suggestValues?: string[]) {
let propName = await GenericPrompt.Prompt(this.app, "Enter a property name", "Property", "", suggestValues);
if (!propName) return null;

let propValue: string;
Expand Down
28 changes: 28 additions & 0 deletions src/uniqueQueue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export class UniqueQueue<T> {
private readonly elements: T[];

constructor() {
this.elements = [];
}

public enqueue(item: T): boolean {
if (this.elements.contains(item)) {
return false;
}

this.elements.push(item);
return true;
}

public dequeue(): T | undefined {
return this.elements.shift();
}

public peek(): T | undefined{
return this.elements[0];
}

public isEmpty(): boolean {
return this.elements.length === 0;
}
}
Loading

0 comments on commit 3706703

Please sign in to comment.