From 7a3eb0b5cbf4fcdda38b6ad05fd218f03f28848b Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Mon, 25 Dec 2023 19:38:37 -0500 Subject: [PATCH 01/44] Task addition dialog, displaying it as drop down and text area --- src/addTaskModal.ts | 106 ++++++++++++++++++++++++++++++++++++++++++++ src/main.ts | 37 +++++++++++++++- 2 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 src/addTaskModal.ts diff --git a/src/addTaskModal.ts b/src/addTaskModal.ts new file mode 100644 index 0000000..d14e894 --- /dev/null +++ b/src/addTaskModal.ts @@ -0,0 +1,106 @@ +import { App, Modal, Setting, DropdownComponent, TextAreaComponent } from "obsidian"; +import { Category } from "./interfaces"; + +export class AddTaskModal extends Modal { + result: {catId: string, task: string}; + onSubmit: (result: {catId: string, task: string}) => void; + categories: Category[]; + + constructor(app: App, categories: Category[], onSubmit: (result: { catId: string; task: string; }) => void) { + super(app); + this.onSubmit = onSubmit; + this.categories = categories.sort((a, b) => { + return this.getFullPathToCategoryTitle(a, categories).localeCompare(this.getFullPathToCategoryTitle(b, categories)); + }); + this.result = { catId: '', task: '' }; // initialize result + } + + onOpen() { + const { contentEl } = this; + + contentEl.createEl("h1", { text: "New Amazing Marvin Task" }); + + + new Setting(contentEl) + .setName("Category") + .addDropdown((dropdown: DropdownComponent) => { + // Add "Inbox" at the top + dropdown.addOption("###root###", "Inbox"); + + // Display categories hierarchically + this.categories.forEach(category => { + const title = this.getTitleWithParent(category); + dropdown.addOption(category._id, title); + }); + dropdown.onChange((value: string) => { + this.result.catId = value; + }); + }); + + new Setting(contentEl) + .setHeading().setName("Task"); + + new Setting(contentEl) + .addTextArea((textArea: TextAreaComponent) => { + textArea.inputEl.style.minHeight = "5em"; // Increase the size of the text area + textArea.onChange((value: string) => { + this.result.task = value; + }); + }).settingEl.addClass("task-textarea-setting"); + + + // Submit Button + new Setting(contentEl) + .addButton((btn) => + btn + .setButtonText("Submit") + .setCta() + .onClick(() => { + this.close(); + if (this.onSubmit && this.result.catId && this.result.task) { + this.onSubmit(this.result); + } + })); + } + + private getTitleWithParent(category: Category): string { + let parent = category.parentId; + + let parentTitle = []; + while (parent && parent !== "root") { + const parentCategory = this.categories.find(c => c._id === parent); + if (parentCategory) { + parentTitle.push(parentCategory.title); + parent = parentCategory.parentId; + } else { + break; + } + } + if (parentTitle.length > 0) { + return category.title + ` in ${parentTitle.reverse().join("/")}`; + } + return category.title; + } + + private getFullPathToCategoryTitle(category: Category, categories: Category[]): string { + let parent = category.parentId; + + let parentTitle = []; + parentTitle.push('/'); + while (parent && parent !== "root") { + const parentCategory = categories.find(c => c._id === parent); + if (parentCategory) { + parentTitle.push(parentCategory.title); + parent = parentCategory.parentId; + } else { + break; + } + } + return `${parentTitle.reverse().join("/")}${category.title}`; + } + + onClose() { + let { contentEl } = this; + contentEl.empty(); + } +} diff --git a/src/main.ts b/src/main.ts index db56d1b..a89859d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,7 +5,6 @@ import { requestUrl, } from "obsidian"; - import { Category, Task @@ -21,6 +20,7 @@ import { getDateFromFile } from "obsidian-daily-notes-interface"; import { amTaskWatcher } from "./amTaskWatcher"; +import { AddTaskModal } from "./addTaskModal"; let noticeTimeout: NodeJS.Timeout; @@ -48,6 +48,7 @@ const CONSTANTS = { dueOnDayEndpoint: '/api/dueItems' } + export default class AmazingMarvinPlugin extends Plugin { settings: AmazingMarvinPluginSettings; @@ -76,6 +77,40 @@ export default class AmazingMarvinPlugin extends Plugin { this.registerEditorExtension(amTaskWatcher(this.app, this)); } + this.addCommand({ + id: "create-marvin-task", + name: "Create Marvin Task", + editorCallback: async (editor, view) => { + // Fetch categories first and make sure they are loaded + try { + const categories = await this.fetchTasksAndCategories(CONSTANTS.categoriesEndpoint); + console.log('Categories:', categories); // For debug purposes + // Ensure categories are fetched before initializing the modal + if (categories.length > 0) { + new AddTaskModal(this.app, categories, async (taskDetails: { catId: string, task: string }) => { + console.log('Task details:', taskDetails); + + // Now you can add the logic to create a Marvin task here using the API... + // For example: + // this.createMarvinTask(taskDetails.catId, taskDetails.task) + // .then(task => { + // editor.replaceRange(`[Marvin Task](${task.deepLink})`, editor.getCursor()); + // }) + // .catch(error => { + // new Notice('Could not create Marvin task: ' + error.message); + // }); + }).open(); + } else { + // Handle the case where categories could not be loaded + new Notice('Failed to load categories from Amazing Marvin.'); + } + } catch (error) { + console.error('Error fetching categories:', error); + new Notice('Failed to load categories from Amazing Marvin.'); + } + } + }); + this.addCommand({ id: 'am-import', name: 'Import Categories and Tasks', From 48308fc9da6153b844d3f48424def0dde63d4c72 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Mon, 25 Dec 2023 20:07:03 -0500 Subject: [PATCH 02/44] Switch from a dropdown to a fuzzy matcher dialog for category --- src/addTaskModal.ts | 121 ++++++++++++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 39 deletions(-) diff --git a/src/addTaskModal.ts b/src/addTaskModal.ts index d14e894..8774749 100644 --- a/src/addTaskModal.ts +++ b/src/addTaskModal.ts @@ -1,9 +1,72 @@ -import { App, Modal, Setting, DropdownComponent, TextAreaComponent } from "obsidian"; +import { App, Modal, Setting, DropdownComponent, TextAreaComponent, FuzzySuggestModal, FuzzyMatch } from "obsidian"; import { Category } from "./interfaces"; +function getTitleWithParent(category: Category, categories: Category[]): string { + let parent = category.parentId; + + let parentTitle = []; + while (parent && parent !== "root") { + const parentCategory = categories.find(category => category._id === parent); + if (parentCategory) { + parentTitle.push(parentCategory.title); + parent = parentCategory.parentId; + } else { + break; + } + } + if (parentTitle.length > 0) { + return category.title + ` in ${parentTitle.reverse().join("/")}`; + } + return category.title; +} + +// Suggester Modal Class for Category Selection +class CategorySuggesterModal extends FuzzySuggestModal { + getItems(): Category[] { + // Prepend a faux 'Inbox' category for matching purposes + const inboxCategory: Category = { + _id: "__inbox-faux__", // Arbitrary unique ID for the Inbox faux category + title: "Inbox", + type: "faux", + updatedAt: 0, + parentId: "root", + startDate: "", + endDate: "", + note: "", + isRecurring: false, + priority: "", + deepLink: "", + dueDate: "", + done: false, + }; + + // Include the Inbox at the beginning of the categories list + return [inboxCategory, ...this.categories]; + } + getItemText(category: Category): string { + if (category.type === "faux") { + return "Inbox"; + } + return getTitleWithParent(category, this.categories); + } + categories: Category[]; + onChooseItem: (item: Category, _evt: MouseEvent | KeyboardEvent) => void; + + constructor(app: App, categories: Category[], onChooseItem: (item: Category, _evt: MouseEvent | KeyboardEvent) => void) { + super(app); + this.categories = categories; + this.onChooseItem = onChooseItem; + this.setPlaceholder("Type to search for a Category"); + } + + onChooseSuggestion(item: FuzzyMatch, _evt: MouseEvent | KeyboardEvent): void { + this.onChooseItem(item.item, _evt); + } +} + export class AddTaskModal extends Modal { - result: {catId: string, task: string}; - onSubmit: (result: {catId: string, task: string}) => void; + result: { catId: string, task: string }; + onSubmit: (result: { catId: string, task: string }) => void; categories: Category[]; constructor(app: App, categories: Category[], onSubmit: (result: { catId: string; task: string; }) => void) { @@ -17,36 +80,35 @@ export class AddTaskModal extends Modal { onOpen() { const { contentEl } = this; + let categoryInput: HTMLInputElement; contentEl.createEl("h1", { text: "New Amazing Marvin Task" }); - new Setting(contentEl) .setName("Category") - .addDropdown((dropdown: DropdownComponent) => { - // Add "Inbox" at the top - dropdown.addOption("###root###", "Inbox"); - - // Display categories hierarchically - this.categories.forEach(category => { - const title = this.getTitleWithParent(category); - dropdown.addOption(category._id, title); - }); - dropdown.onChange((value: string) => { - this.result.catId = value; + .addText(text => { + categoryInput = text.inputEl; + text.onChange(value => { + // Simulate a dropdown by creating a suggester modal + const suggester = new CategorySuggesterModal(this.app, this.categories, (item: Category) => { + categoryInput.value = item.title; + this.result.catId = item._id; + suggester.close(); + }); + suggester.open(); }); }); - new Setting(contentEl) - .setHeading().setName("Task"); + new Setting(contentEl) + .setHeading().setName("Task"); - new Setting(contentEl) + new Setting(contentEl) .addTextArea((textArea: TextAreaComponent) => { textArea.inputEl.style.minHeight = "5em"; // Increase the size of the text area textArea.onChange((value: string) => { this.result.task = value; }); - }).settingEl.addClass("task-textarea-setting"); + }).settingEl.addClass("am-task-textarea-setting"); // Submit Button @@ -63,25 +125,6 @@ export class AddTaskModal extends Modal { })); } - private getTitleWithParent(category: Category): string { - let parent = category.parentId; - - let parentTitle = []; - while (parent && parent !== "root") { - const parentCategory = this.categories.find(c => c._id === parent); - if (parentCategory) { - parentTitle.push(parentCategory.title); - parent = parentCategory.parentId; - } else { - break; - } - } - if (parentTitle.length > 0) { - return category.title + ` in ${parentTitle.reverse().join("/")}`; - } - return category.title; - } - private getFullPathToCategoryTitle(category: Category, categories: Category[]): string { let parent = category.parentId; @@ -96,7 +139,7 @@ export class AddTaskModal extends Modal { break; } } - return `${parentTitle.reverse().join("/")}${category.title}`; + return `${parentTitle.reverse().join("/")}${category.title}`; } onClose() { From 4122aa7abe88090cf672c8522d2ca273e9f27fda Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Mon, 25 Dec 2023 20:49:22 -0500 Subject: [PATCH 03/44] Implement task addition API --- src/addTaskModal.ts | 15 +++++++++++ src/main.ts | 63 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/addTaskModal.ts b/src/addTaskModal.ts index 8774749..74f0955 100644 --- a/src/addTaskModal.ts +++ b/src/addTaskModal.ts @@ -110,6 +110,13 @@ export class AddTaskModal extends Modal { }); }).settingEl.addClass("am-task-textarea-setting"); + const shortcutsDesc = document.createDocumentFragment(); + shortcutsDesc.appendText('The Task field accepts labels (@), time estimates (~), and scheduled dates (+). See '); + shortcutsDesc.appendChild(this.getShortcutsLink()); + shortcutsDesc.appendText('.'); + + new Setting(contentEl) + .setDesc(shortcutsDesc); // Submit Button new Setting(contentEl) @@ -125,6 +132,14 @@ export class AddTaskModal extends Modal { })); } + private getShortcutsLink(): HTMLAnchorElement { + const a = document.createElement('a'); + a.href = 'https://help.amazingmarvin.com/en/articles/1949399-using-shortcuts-while-creating-a-task'; + a.text = 'Using shortcuts while creating a task'; + a.target = '_blank'; + return a; + } + private getFullPathToCategoryTitle(category: Category, categories: Category[]): string { let parent = category.parentId; diff --git a/src/main.ts b/src/main.ts index a89859d..0315a49 100644 --- a/src/main.ts +++ b/src/main.ts @@ -45,7 +45,8 @@ const CONSTANTS = { categoriesEndpoint: '/api/categories', childrenEndpoint: '/api/children', scheduledOnDayEndpoint: '/api/todayItems', - dueOnDayEndpoint: '/api/dueItems' + dueOnDayEndpoint: '/api/dueItems', + addTaskEndpoint: '/api/addTask', } @@ -90,15 +91,13 @@ export default class AmazingMarvinPlugin extends Plugin { new AddTaskModal(this.app, categories, async (taskDetails: { catId: string, task: string }) => { console.log('Task details:', taskDetails); - // Now you can add the logic to create a Marvin task here using the API... - // For example: - // this.createMarvinTask(taskDetails.catId, taskDetails.task) - // .then(task => { - // editor.replaceRange(`[Marvin Task](${task.deepLink})`, editor.getCursor()); - // }) - // .catch(error => { - // new Notice('Could not create Marvin task: ' + error.message); - // }); + this.addMarvinTask(taskDetails.catId, taskDetails.task) + .then(task => { + editor.replaceRange(`- [${task.done ? 'x' : ' '}] [⚓](${task.deepLink}) ${this.formatTaskDetails(task as Task, '')} ${task.title}`, editor.getCursor()); + }) + .catch(error => { + new Notice('Could not create Marvin task: ' + error.message); + }); }).open(); } else { // Handle the case where categories could not be loaded @@ -152,6 +151,50 @@ export default class AmazingMarvinPlugin extends Plugin { }); } + async addMarvinTask(catId: string, taskTitle: string): Promise { + const opt = this.settings; + + let requestBody = (catId === '' || catId === undefined || catId === "root" || catId === "__inbox-faux__") ? + { + title : taskTitle, + timeZoneOffset: new Date().getTimezoneOffset(), + } + : + { + title: taskTitle, + timeZoneOffset: new Date().getTimezoneOffset(), + parentId: catId, + }; + + try { + const remoteResponse = await requestUrl({ + url: `https://serv.amazingmarvin.com/api/addTask`, + method: 'POST', + headers: { + 'X-API-Token': opt.apiKey, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(requestBody) + }); + + if (remoteResponse.status === 200) { + new Notice("Task added in Amazing Marvin."); + return this.decorateWithDeepLink(remoteResponse.json) as Task; + } + } catch (error) { + const errorNote = document.createDocumentFragment(); + errorNote.appendText('Error creating task in Amazing Marvin. Try again or do it'); + const a = document.createElement('a'); + a.href = 'https://app.amazingmarvin.com/'; + a.text = 'manually'; + a.target = '_blank'; + errorNote.appendChild(a); + + new Notice(errorNote, 0); + console.error('Error creating task:', error); + } + return Promise.reject(new Error('Error creating task')); + } onunload() { } From b3af0cfccfa8e9a755d6bd484ff3af77dd2f314b Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Mon, 25 Dec 2023 20:53:33 -0500 Subject: [PATCH 04/44] Update to version 0.5.0b1 --- manifest.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index 946036c..28a646b 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.3.1", + "version": "0.5.0b1", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index bf0e152..576693c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.4.2b", + "version": "0.5.0b1", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index dbd8c28..8014e86 100644 --- a/versions.json +++ b/versions.json @@ -9,5 +9,6 @@ "0.3.2b2": "1.4.16", "0.4.0b": "1.4.16", "0.4.1b": "1.4.16", - "0.4.2b": "1.4.16" + "0.4.2b": "1.4.16", + "0.5.0b1": "1.4.16" } From 466fd2f088103920b8b43cd34ea60a71f0b050d8 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Mon, 25 Dec 2023 21:06:23 -0500 Subject: [PATCH 05/44] Add task creation and deep linking features to README --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ee7bd79..187ac95 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ The Amazing Marvin Plugin provides a way to bring your tasks and project structu - **Parent Links**: For easy navigation, notes for subcategories and subprojects include backlinks to their parent category or project. - **Wiki Links**: Sub-Categories and projects Amazing Marvin are added as wiki links. - **Categories and Projects are folder notes**: Categories and projects are created as folder notes, compatible with [Obsidian folder notes](https://github.com/LostPaul/obsidian-folder-notes). +- **Task Creation**: Users can create Amazing Marvin tasks directly within Obsidian, with support for standard Marvin shorthand notations like `+` for dates or `@` for labels. +- **Deep Linking**: Each task and category is equipped with a deep link, providing quick navigation back to Amazing Marvin. ## Usage Instructions @@ -35,6 +37,15 @@ To initiate a sync: 2. Search for and select the command `Sync Amazing Marvin categories and projects`. 3. The plugin will then proceed to update your Obsidian vault with the current structure and content from Amazing Marvin. +### Creating a Marvin Task + +To create a task: + +1. Open Obsidian's Command Palette with `Ctrl/Cmd + P`. +2. Search for and select the command `Create Marvin Task`. +3. Input the task details and select the appropriate category from the dropdown, which shows suggestions as you type. +4. Upon task creation, a markdown link to the Marvin task is inserted at your cursor location in Obsidian, and the Amazing Marvin task contains a URI-friendly link back to the triggering Obsidian note. + ### Important Considerations - **Data Loss**: Be cautious when editing Amazing Marvin-generated notes in Obsidian, as these changes will be overwritten by the next sync. @@ -53,7 +64,7 @@ Once synced, your Obsidian vault will contain a new `AmazingMarvin` folder. Insi 1. Install the BRAT plugin 1. Open `Settings` -> `Community Plugins` 2. Disable safe mode, if enabled - 3. *Browse*, and search for "BRAT" + 3. *Browse*, and search for "BRAT" 4. Install the latest version of **Obsidian42 - BRAT** 2. Open BRAT settings (`Settings` -> `BRAT`) 1. Scroll to the `Beta Plugin List` section From fbc2465dfd729ca2001c51e299974c8c444122ea Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Mon, 25 Dec 2023 21:10:42 -0500 Subject: [PATCH 06/44] Add features for task creation and auto-mark as done --- README.md | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 187ac95..bb9b985 100644 --- a/README.md +++ b/README.md @@ -37,14 +37,35 @@ To initiate a sync: 2. Search for and select the command `Sync Amazing Marvin categories and projects`. 3. The plugin will then proceed to update your Obsidian vault with the current structure and content from Amazing Marvin. +Once synced, your Obsidian vault will contain a new `AmazingMarvin` folder. Inside, you'll find the structured notes corresponding to your categories and projects from Amazing Marvin. + ### Creating a Marvin Task +The task creation dialog is designed to mirror the task input experience in Amazing Marvin closely. It includes the following features: + +- Autocomplete for Categories and Projects using `#` syntax or a search sub-dialog. +- Recognizes shorthand notations for properties like start date (`~`), due date (`@`), and labels (`+`). +- Places a link to the Marvin task as a deep link in Obsidian at the cursor location upon task creation. +- The created Marvin task contains an Advanced URI-friendly link back to the Obsidian note that instigated the task. + To create a task: 1. Open Obsidian's Command Palette with `Ctrl/Cmd + P`. 2. Search for and select the command `Create Marvin Task`. 3. Input the task details and select the appropriate category from the dropdown, which shows suggestions as you type. -4. Upon task creation, a markdown link to the Marvin task is inserted at your cursor location in Obsidian, and the Amazing Marvin task contains a URI-friendly link back to the triggering Obsidian note. +4. Upon task creation, a markdown checklist item with a link to the Marvin task is inserted at your cursor location in Obsidian. + +### Auto-Mark as Done Feature + +One of the highlights in this version is the ability to auto-mark tasks as done in Amazing Marvin when they are checked off in Obsidian. When this feature is enabled in the plugin settings, checking a task off in your Obsidian note will automatically update the task status in Amazing Marvin. + +Here's how to enable this feature: + +1. Go to `Settings > Obsidian Amazing Marvin Plugin`. +2. Check the option `Attempt to mark tasks as done in Amazing Marvin when checked off in Obsidian`. +3. Save your settings. + +Now, when you check off a task with an Amazing Marvin Link in an Obsidian note, a request will be sent to Amazing Marvin to mark the task as done there as well. ### Important Considerations @@ -53,9 +74,6 @@ To create a task: By following these guidelines, you can ensure your Amazing Marvin data is accurately reflected in Obsidian while being mindful of the plugin's current limitations. -### Viewing Synced Content - -Once synced, your Obsidian vault will contain a new `AmazingMarvin` folder. Inside, you'll find the structured notes corresponding to your categories and projects from Amazing Marvin. ## Installing From 22286d8c18aa75aa757c742890d647d0fe514ade Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Mon, 25 Dec 2023 21:22:06 -0500 Subject: [PATCH 07/44] Fix local server settings not reflecting saved value --- src/settings.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/settings.ts b/src/settings.ts index f0552cb..db59627 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -153,6 +153,10 @@ export class AmazingMarvinSettingsTab extends PluginSettingTab { .setPlaceholder("localhost") .setValue(this.plugin.settings.localServerHost || "localhost") .setDisabled(!this.plugin.settings.useLocalServer) + .onChange(async (value) => { + this.plugin.settings.localServerHost = value; + await this.plugin.saveSettings(); + }) ); // Local Server Port @@ -162,16 +166,19 @@ export class AmazingMarvinSettingsTab extends PluginSettingTab { .setPlaceholder("12082") .setValue(this.plugin.settings.localServerPort?.toString() || "12082") .setDisabled(!this.plugin.settings.useLocalServer) + .onChange(async (value) => { + this.plugin.settings.localServerPort = value; + await this.plugin.saveSettings(); + }) ); // Update the disabled state based on the toggle localServerToggle.addToggle(toggle => toggle.onChange(async (value) => { this.plugin.settings.useLocalServer = value; - await this.plugin.saveSettings(); - localServerHostSetting.setDisabled(!value); localServerPortSetting.setDisabled(!value); - })); + await this.plugin.saveSettings(); + }).setValue(this.plugin.settings.useLocalServer)); } } From 18b50ab3c8b6414278a76ff54b564ed4a30f7cf6 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Mon, 25 Dec 2023 22:36:21 -0500 Subject: [PATCH 08/44] Improve dialog behavior when no category is selected --- src/addTaskModal.ts | 78 ++++++++++++++++++++++++++++----------------- src/main.ts | 4 +-- 2 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/addTaskModal.ts b/src/addTaskModal.ts index 74f0955..968f1f1 100644 --- a/src/addTaskModal.ts +++ b/src/addTaskModal.ts @@ -1,6 +1,22 @@ -import { App, Modal, Setting, DropdownComponent, TextAreaComponent, FuzzySuggestModal, FuzzyMatch } from "obsidian"; +import { App, Modal, Setting, DropdownComponent, TextAreaComponent, FuzzySuggestModal, FuzzyMatch, Notice } from "obsidian"; import { Category } from "./interfaces"; +const inboxCategory: Category = { + _id: "__inbox-faux__", // Arbitrary unique ID for the Inbox faux category + title: "Inbox", + type: "faux", + updatedAt: 0, + parentId: "root", + startDate: "", + endDate: "", + note: "", + isRecurring: false, + priority: "", + deepLink: "", + dueDate: "", + done: false, +}; + function getTitleWithParent(category: Category, categories: Category[]): string { let parent = category.parentId; @@ -22,23 +38,10 @@ function getTitleWithParent(category: Category, categories: Category[]): string // Suggester Modal Class for Category Selection class CategorySuggesterModal extends FuzzySuggestModal { + categories: Category[]; + + onChooseItem: (item: Category, _evt: MouseEvent | KeyboardEvent) => void; getItems(): Category[] { - // Prepend a faux 'Inbox' category for matching purposes - const inboxCategory: Category = { - _id: "__inbox-faux__", // Arbitrary unique ID for the Inbox faux category - title: "Inbox", - type: "faux", - updatedAt: 0, - parentId: "root", - startDate: "", - endDate: "", - note: "", - isRecurring: false, - priority: "", - deepLink: "", - dueDate: "", - done: false, - }; // Include the Inbox at the beginning of the categories list return [inboxCategory, ...this.categories]; @@ -49,14 +52,11 @@ class CategorySuggesterModal extends FuzzySuggestModal { } return getTitleWithParent(category, this.categories); } - categories: Category[]; - onChooseItem: (item: Category, _evt: MouseEvent | KeyboardEvent) => void; constructor(app: App, categories: Category[], onChooseItem: (item: Category, _evt: MouseEvent | KeyboardEvent) => void) { super(app); this.categories = categories; this.onChooseItem = onChooseItem; - this.setPlaceholder("Type to search for a Category"); } onChooseSuggestion(item: FuzzyMatch, _evt: MouseEvent | KeyboardEvent): void { @@ -75,7 +75,7 @@ export class AddTaskModal extends Modal { this.categories = categories.sort((a, b) => { return this.getFullPathToCategoryTitle(a, categories).localeCompare(this.getFullPathToCategoryTitle(b, categories)); }); - this.result = { catId: '', task: '' }; // initialize result + this.result = { catId: inboxCategory._id, task: '' }; } onOpen() { @@ -88,8 +88,9 @@ export class AddTaskModal extends Modal { .setName("Category") .addText(text => { categoryInput = text.inputEl; + text.setValue(inboxCategory.title); + this.result.catId = inboxCategory._id; text.onChange(value => { - // Simulate a dropdown by creating a suggester modal const suggester = new CategorySuggesterModal(this.app, this.categories, (item: Category) => { categoryInput.value = item.title; this.result.catId = item._id; @@ -104,7 +105,9 @@ export class AddTaskModal extends Modal { new Setting(contentEl) .addTextArea((textArea: TextAreaComponent) => { - textArea.inputEl.style.minHeight = "5em"; // Increase the size of the text area + textArea.inputEl.style.minHeight = "5em"; + textArea.inputEl.style.minWidth = "100%"; + textArea.onChange((value: string) => { this.result.task = value; }); @@ -118,20 +121,37 @@ export class AddTaskModal extends Modal { new Setting(contentEl) .setDesc(shortcutsDesc); - // Submit Button new Setting(contentEl) .addButton((btn) => btn - .setButtonText("Submit") + .setButtonText("Add") .setCta() .onClick(() => { - this.close(); - if (this.onSubmit && this.result.catId && this.result.task) { - this.onSubmit(this.result); - } + this.addTask(); })); + + this.modalEl.addEventListener("keydown", (e: KeyboardEvent) => { + if (e.key === "Enter" && e.ctrlKey) { + e.preventDefault(); + this.addTask(); + } + }); + + } + + private addTask() { + if (!this.result.task.trim()) { + new Notice('Please enter a task description.', 4000); + return; + } + this.close(); + if (this.onSubmit && this.result.task) { + this.onSubmit(this.result); + } } + + private getShortcutsLink(): HTMLAnchorElement { const a = document.createElement('a'); a.href = 'https://help.amazingmarvin.com/en/articles/1949399-using-shortcuts-while-creating-a-task'; diff --git a/src/main.ts b/src/main.ts index 0315a49..49128c9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -85,12 +85,10 @@ export default class AmazingMarvinPlugin extends Plugin { // Fetch categories first and make sure they are loaded try { const categories = await this.fetchTasksAndCategories(CONSTANTS.categoriesEndpoint); - console.log('Categories:', categories); // For debug purposes // Ensure categories are fetched before initializing the modal if (categories.length > 0) { new AddTaskModal(this.app, categories, async (taskDetails: { catId: string, task: string }) => { - console.log('Task details:', taskDetails); - + console.debug(`TaskModal result: ${taskDetails.catId} - ${taskDetails.task}}`); this.addMarvinTask(taskDetails.catId, taskDetails.task) .then(task => { editor.replaceRange(`- [${task.done ? 'x' : ' '}] [⚓](${task.deepLink}) ${this.formatTaskDetails(task as Task, '')} ${task.title}`, editor.getCursor()); From 7db6ed460941caf1f1673b1c56859844bf0aa521 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 08:29:56 -0500 Subject: [PATCH 09/44] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb9b985..138da09 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ By following these guidelines, you can ensure your Amazing Marvin data is accura ### Manually 1. If you haven't enabled community plugins in Obsidian, follow these [instructions](https://help.obsidian.md/Extending+Obsidian/Community+plugins#Install+a+community+plugin) to do so. -2. Download the latest release from the [releases](https://github.com/cloud-atlas-ai/obsidian-am/releases) page. +2. Download `cloudatlas-obsidian-am.zip` from the [releases](https://github.com/cloud-atlas-ai/obsidian-am/releases). 3. Unzip the release and copy the directory into your vault's plugins folder: `/.obsidian/plugins/cloudatlas-o-am`. 4. Restart Obsidian to recognize the new plugin. 5. In Obsidian's settings under "Community Plugins," find and enable the Obsidian Amazing Marvin Plugin. From b52625cd65360f1f055b3e1739f57d6f383d71ea Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Mon, 25 Dec 2023 23:06:45 -0500 Subject: [PATCH 10/44] Update to version 0.5.0b2 --- manifest.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index 28a646b..533216e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.5.0b1", + "version": "0.5.0b2", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index 576693c..81aa593 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.5.0b1", + "version": "0.5.0b2", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index 8014e86..4bf9053 100644 --- a/versions.json +++ b/versions.json @@ -10,5 +10,6 @@ "0.4.0b": "1.4.16", "0.4.1b": "1.4.16", "0.4.2b": "1.4.16", - "0.5.0b1": "1.4.16" + "0.5.0b1": "1.4.16", + "0.5.0b2": "1.4.16" } From 0a03b7678970c6b430b77ac1c7817dddea0c13f1 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Mon, 25 Dec 2023 23:54:50 -0500 Subject: [PATCH 11/44] Update addMarvinTask method to include notePath and vaultName --- src/main.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main.ts b/src/main.ts index 49128c9..18c4075 100644 --- a/src/main.ts +++ b/src/main.ts @@ -88,8 +88,7 @@ export default class AmazingMarvinPlugin extends Plugin { // Ensure categories are fetched before initializing the modal if (categories.length > 0) { new AddTaskModal(this.app, categories, async (taskDetails: { catId: string, task: string }) => { - console.debug(`TaskModal result: ${taskDetails.catId} - ${taskDetails.task}}`); - this.addMarvinTask(taskDetails.catId, taskDetails.task) + this.addMarvinTask(taskDetails.catId, taskDetails.task, view.file?.path, this.app.vault.getName()) .then(task => { editor.replaceRange(`- [${task.done ? 'x' : ' '}] [⚓](${task.deepLink}) ${this.formatTaskDetails(task as Task, '')} ${task.title}`, editor.getCursor()); }) @@ -149,20 +148,21 @@ export default class AmazingMarvinPlugin extends Plugin { }); } - async addMarvinTask(catId: string, taskTitle: string): Promise { + async addMarvinTask(catId: string, taskTitle: string, notePath: string = '', vaultName: string = ''): Promise { const opt = this.settings; - let requestBody = (catId === '' || catId === undefined || catId === "root" || catId === "__inbox-faux__") ? - { - title : taskTitle, - timeZoneOffset: new Date().getTimezoneOffset(), - } - : - { - title: taskTitle, - timeZoneOffset: new Date().getTimezoneOffset(), - parentId: catId, - }; + let requestBody: any = { + title: taskTitle, + timeZoneOffset: new Date().getTimezoneOffset(), + }; + + if (catId && catId !== '' && catId !== 'root' && catId !== '__inbox-faux__') { + requestBody.parentId = catId; + } + + if (notePath && notePath !== '') { + requestBody.note = `[🏷️](obsidian://advanced-uri?filePath=${notePath}${vaultName !== '' ? `&vault=${vaultName}` : ''})`; + } try { const remoteResponse = await requestUrl({ From a12a465d539198190f5109b57e8f879c3486ef51 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Mon, 25 Dec 2023 23:56:20 -0500 Subject: [PATCH 12/44] Revert "Update addMarvinTask method to include notePath and vaultName" This reverts commit 0a03b7678970c6b430b77ac1c7817dddea0c13f1. Did not intend to commit directly to master branch. --- src/main.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main.ts b/src/main.ts index 18c4075..49128c9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -88,7 +88,8 @@ export default class AmazingMarvinPlugin extends Plugin { // Ensure categories are fetched before initializing the modal if (categories.length > 0) { new AddTaskModal(this.app, categories, async (taskDetails: { catId: string, task: string }) => { - this.addMarvinTask(taskDetails.catId, taskDetails.task, view.file?.path, this.app.vault.getName()) + console.debug(`TaskModal result: ${taskDetails.catId} - ${taskDetails.task}}`); + this.addMarvinTask(taskDetails.catId, taskDetails.task) .then(task => { editor.replaceRange(`- [${task.done ? 'x' : ' '}] [⚓](${task.deepLink}) ${this.formatTaskDetails(task as Task, '')} ${task.title}`, editor.getCursor()); }) @@ -148,21 +149,20 @@ export default class AmazingMarvinPlugin extends Plugin { }); } - async addMarvinTask(catId: string, taskTitle: string, notePath: string = '', vaultName: string = ''): Promise { + async addMarvinTask(catId: string, taskTitle: string): Promise { const opt = this.settings; - let requestBody: any = { - title: taskTitle, - timeZoneOffset: new Date().getTimezoneOffset(), - }; - - if (catId && catId !== '' && catId !== 'root' && catId !== '__inbox-faux__') { - requestBody.parentId = catId; - } - - if (notePath && notePath !== '') { - requestBody.note = `[🏷️](obsidian://advanced-uri?filePath=${notePath}${vaultName !== '' ? `&vault=${vaultName}` : ''})`; - } + let requestBody = (catId === '' || catId === undefined || catId === "root" || catId === "__inbox-faux__") ? + { + title : taskTitle, + timeZoneOffset: new Date().getTimezoneOffset(), + } + : + { + title: taskTitle, + timeZoneOffset: new Date().getTimezoneOffset(), + parentId: catId, + }; try { const remoteResponse = await requestUrl({ From 9511dba11112977805beef2fdeaa61d527830735 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Mon, 25 Dec 2023 23:57:32 -0500 Subject: [PATCH 13/44] Add link back to Obsidian Note that triggered the new task in the `note` field Fixes #26 --- src/main.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main.ts b/src/main.ts index 49128c9..18c4075 100644 --- a/src/main.ts +++ b/src/main.ts @@ -88,8 +88,7 @@ export default class AmazingMarvinPlugin extends Plugin { // Ensure categories are fetched before initializing the modal if (categories.length > 0) { new AddTaskModal(this.app, categories, async (taskDetails: { catId: string, task: string }) => { - console.debug(`TaskModal result: ${taskDetails.catId} - ${taskDetails.task}}`); - this.addMarvinTask(taskDetails.catId, taskDetails.task) + this.addMarvinTask(taskDetails.catId, taskDetails.task, view.file?.path, this.app.vault.getName()) .then(task => { editor.replaceRange(`- [${task.done ? 'x' : ' '}] [⚓](${task.deepLink}) ${this.formatTaskDetails(task as Task, '')} ${task.title}`, editor.getCursor()); }) @@ -149,20 +148,21 @@ export default class AmazingMarvinPlugin extends Plugin { }); } - async addMarvinTask(catId: string, taskTitle: string): Promise { + async addMarvinTask(catId: string, taskTitle: string, notePath: string = '', vaultName: string = ''): Promise { const opt = this.settings; - let requestBody = (catId === '' || catId === undefined || catId === "root" || catId === "__inbox-faux__") ? - { - title : taskTitle, - timeZoneOffset: new Date().getTimezoneOffset(), - } - : - { - title: taskTitle, - timeZoneOffset: new Date().getTimezoneOffset(), - parentId: catId, - }; + let requestBody: any = { + title: taskTitle, + timeZoneOffset: new Date().getTimezoneOffset(), + }; + + if (catId && catId !== '' && catId !== 'root' && catId !== '__inbox-faux__') { + requestBody.parentId = catId; + } + + if (notePath && notePath !== '') { + requestBody.note = `[🏷️](obsidian://advanced-uri?filePath=${notePath}${vaultName !== '' ? `&vault=${vaultName}` : ''})`; + } try { const remoteResponse = await requestUrl({ From d2dba1da30a144dd8c1f47507ebe7a832e015e90 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 00:13:29 -0500 Subject: [PATCH 14/44] Add ability to create tasks using selected text --- src/main.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main.ts b/src/main.ts index 18c4075..53ac86e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -84,6 +84,17 @@ export default class AmazingMarvinPlugin extends Plugin { editorCallback: async (editor, view) => { // Fetch categories first and make sure they are loaded try { + + //if a region of text is selected, at least 3 characters long, use that to add a new task and skip the modal + if (editor.somethingSelected() && editor.getSelection().length > 2) { + this.addMarvinTask('', editor.getSelection(), view.file?.path, this.app.vault.getName()).then(task => { + editor.replaceSelection(`- [${task.done ? 'x' : ' '}] [⚓](${task.deepLink}) ${this.formatTaskDetails(task as Task, '')} ${task.title}`); + }).catch(error => { + new Notice('Could not create Marvin task: ' + error.message); + }); + return; + } + const categories = await this.fetchTasksAndCategories(CONSTANTS.categoriesEndpoint); // Ensure categories are fetched before initializing the modal if (categories.length > 0) { From 120fea6cdcbd1b4d06c860f796753a16a4a91f78 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 00:16:35 -0500 Subject: [PATCH 15/44] Fixes Improve local server error logging #27 --- src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 53ac86e..8730979 100644 --- a/src/main.ts +++ b/src/main.ts @@ -274,7 +274,7 @@ export default class AmazingMarvinPlugin extends Plugin { errorMessage = `[${response.status}] ${await response.text}`; } catch (err) { errorMessage = err.message; - console.error('Error fetching data from local server:', err); + console.debug('Failed while fetching from local server, will try the public server next:', err); } if (!opt.useLocalServer || errorMessage) { From dedb848bce3222b6d1d563f8e43521261b34f790 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 00:17:19 -0500 Subject: [PATCH 16/44] Update to version 0.5.0b3 --- manifest.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index 533216e..a7bcba7 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.5.0b2", + "version": "0.5.0b3", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index 81aa593..bd5e94b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.5.0b2", + "version": "0.5.0b3", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index 4bf9053..fa69e60 100644 --- a/versions.json +++ b/versions.json @@ -11,5 +11,6 @@ "0.4.1b": "1.4.16", "0.4.2b": "1.4.16", "0.5.0b1": "1.4.16", - "0.5.0b2": "1.4.16" + "0.5.0b2": "1.4.16", + "0.5.0b3": "1.4.16" } From ccf66ecb5db2dc0cc3091156b46446bb98dd8390 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 00:53:04 -0500 Subject: [PATCH 17/44] Reverse time zone offset calculation because this is what AM's API expects --- src/main.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main.ts b/src/main.ts index 8730979..92b4e3c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -21,8 +21,11 @@ import { } from "obsidian-daily-notes-interface"; import { amTaskWatcher } from "./amTaskWatcher"; import { AddTaskModal } from "./addTaskModal"; +import { time } from "console"; -let noticeTimeout: NodeJS.Timeout; +function getAMTimezoneOffset() { + return new Date().getTimezoneOffset() * -1; +} const animateNotice = (notice: Notice) => { let message = notice.noticeEl.innerText; @@ -37,7 +40,7 @@ const animateNotice = (notice: Notice) => { message = message.replace(" ...", " "); } notice.setMessage(message); - noticeTimeout = setTimeout(() => animateNotice(notice), 500); + setTimeout(() => animateNotice(notice), 500); }; const CONSTANTS = { @@ -164,7 +167,7 @@ export default class AmazingMarvinPlugin extends Plugin { let requestBody: any = { title: taskTitle, - timeZoneOffset: new Date().getTimezoneOffset(), + timeZoneOffset: getAMTimezoneOffset(), }; if (catId && catId !== '' && catId !== 'root' && catId !== '__inbox-faux__') { @@ -222,7 +225,7 @@ export default class AmazingMarvinPlugin extends Plugin { const opt = this.settings; const requestBody = { itemId: taskId, - timeZoneOffset: new Date().getTimezoneOffset() + timeZoneOffset: getAMTimezoneOffset() }; try { From 3509440c12c1ba4350b9224101984991edefd560 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 00:57:48 -0500 Subject: [PATCH 18/44] Update to version 0.5.0b4 --- manifest.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index a7bcba7..91813c0 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.5.0b3", + "version": "0.5.0b4", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index bd5e94b..d9064d7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.5.0b3", + "version": "0.5.0b4", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index fa69e60..a737684 100644 --- a/versions.json +++ b/versions.json @@ -12,5 +12,6 @@ "0.4.2b": "1.4.16", "0.5.0b1": "1.4.16", "0.5.0b2": "1.4.16", - "0.5.0b3": "1.4.16" + "0.5.0b3": "1.4.16", + "0.5.0b4": "1.4.16" } From d5f3448ac22250ae50a67065bf0b3eb3b4874da8 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 01:06:34 -0500 Subject: [PATCH 19/44] Fix typo --- src/main.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 92b4e3c..3675b08 100644 --- a/src/main.ts +++ b/src/main.ts @@ -195,12 +195,13 @@ export default class AmazingMarvinPlugin extends Plugin { } } catch (error) { const errorNote = document.createDocumentFragment(); - errorNote.appendText('Error creating task in Amazing Marvin. Try again or do it'); + errorNote.appendText('Error creating task in Amazing Marvin. Try again or do it '); const a = document.createElement('a'); a.href = 'https://app.amazingmarvin.com/'; a.text = 'manually'; a.target = '_blank'; errorNote.appendChild(a); + errorNote.appendText('.'); new Notice(errorNote, 0); console.error('Error creating task:', error); From ae0d8e8d69b92b337eb132d008b814b984fc04c7 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 01:13:39 -0500 Subject: [PATCH 20/44] Add 429 handling in task creation --- src/main.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main.ts b/src/main.ts index 3675b08..8a21765 100644 --- a/src/main.ts +++ b/src/main.ts @@ -195,7 +195,14 @@ export default class AmazingMarvinPlugin extends Plugin { } } catch (error) { const errorNote = document.createDocumentFragment(); - errorNote.appendText('Error creating task in Amazing Marvin. Try again or do it '); + + if(error.remoteResponse.status === 429){ + errorNote.appendText('Your request was throttled by Amazing Marvin. Wait a few minutes and try again. Or do it '); + console.error('Your request was throttled by Amazing Marvin. Wait a few minutes and try again. Or do it manually.'); + } else { + errorNote.appendText('Error creating task in Amazing Marvin. You can try again or do it '); + console.error('Error creating task:', error); + } const a = document.createElement('a'); a.href = 'https://app.amazingmarvin.com/'; a.text = 'manually'; @@ -204,7 +211,6 @@ export default class AmazingMarvinPlugin extends Plugin { errorNote.appendText('.'); new Notice(errorNote, 0); - console.error('Error creating task:', error); } return Promise.reject(new Error('Error creating task')); } From e105b2fce497f80f61c448ef1a48da8c86564750 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 01:19:50 -0500 Subject: [PATCH 21/44] More 429 handling --- src/main.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main.ts b/src/main.ts index 8a21765..b8f5a60 100644 --- a/src/main.ts +++ b/src/main.ts @@ -196,7 +196,7 @@ export default class AmazingMarvinPlugin extends Plugin { } catch (error) { const errorNote = document.createDocumentFragment(); - if(error.remoteResponse.status === 429){ + if (error.remoteResponse.status === 429) { errorNote.appendText('Your request was throttled by Amazing Marvin. Wait a few minutes and try again. Or do it '); console.error('Your request was throttled by Amazing Marvin. Wait a few minutes and try again. Or do it manually.'); } else { @@ -252,7 +252,14 @@ export default class AmazingMarvinPlugin extends Plugin { } } catch (error) { const errorNote = document.createDocumentFragment(); - errorNote.appendText('Error marking task as done in Amazing Marvin. You should do it '); + if (error.remoteResponse.status === 429) { + errorNote.appendText('Your request was throttled by Amazing Marvin. Or do it manually at '); + console.error('Your request was throttled by Amazing Marvin. Wait a few minutes and try again. Or do it manually.'); + } else { + errorNote.appendText('Error marking task as done in Amazing Marvin. You should do it '); + console.error('Error marking task as done:', error); + } + const a = document.createElement('a'); a.href = 'https://app.amazingmarvin.com/#t=' + taskId; a.text = 'manually'; @@ -260,7 +267,6 @@ export default class AmazingMarvinPlugin extends Plugin { errorNote.appendChild(a); new Notice(errorNote, 0); - console.error('Error marking task as done:', error); } } @@ -299,7 +305,11 @@ export default class AmazingMarvinPlugin extends Plugin { errorMessage = `[${response.status}] ${await response.text()}`; } catch (err) { - errorMessage = err.message; + if (response?.status === 429) { + errorMessage = 'Your request was throttled by Amazing Marvin.'; + } else { + errorMessage = err.message; + } } } From 05752baecbde6bcb0ae6d45ee7d6ac7a98799f0a Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 01:56:10 -0500 Subject: [PATCH 22/44] Update to version 0.5.0 --- manifest.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index 91813c0..83bb5f3 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.5.0b4", + "version": "0.5.0", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index d9064d7..49e5901 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.5.0b4", + "version": "0.5.0", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index a737684..d095180 100644 --- a/versions.json +++ b/versions.json @@ -13,5 +13,6 @@ "0.5.0b1": "1.4.16", "0.5.0b2": "1.4.16", "0.5.0b3": "1.4.16", - "0.5.0b4": "1.4.16" + "0.5.0b4": "1.4.16", + "0.5.0": "1.4.16" } From 29550cd2f4c7f32c5c169564dc8e63ef8bfa3a11 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 01:57:04 -0500 Subject: [PATCH 23/44] update BRAT manifest to latest release --- manifest-beta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest-beta.json b/manifest-beta.json index 82ac981..83bb5f3 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.4.2b", + "version": "0.5.0", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", From 84e6f2aecbda8b992453e21291ebe33e95fa808e Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 03:52:10 -0500 Subject: [PATCH 24/44] Noticed this code was failing, fixing --- src/main.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main.ts b/src/main.ts index b8f5a60..07177f0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -192,17 +192,22 @@ export default class AmazingMarvinPlugin extends Plugin { if (remoteResponse.status === 200) { new Notice("Task added in Amazing Marvin."); return this.decorateWithDeepLink(remoteResponse.json) as Task; - } - } catch (error) { - const errorNote = document.createDocumentFragment(); + } else if (remoteResponse.status === 429) { - if (error.remoteResponse.status === 429) { + const errorNote = document.createDocumentFragment(); errorNote.appendText('Your request was throttled by Amazing Marvin. Wait a few minutes and try again. Or do it '); - console.error('Your request was throttled by Amazing Marvin. Wait a few minutes and try again. Or do it manually.'); - } else { - errorNote.appendText('Error creating task in Amazing Marvin. You can try again or do it '); - console.error('Error creating task:', error); + const a = document.createElement('a'); + a.href = 'https://app.amazingmarvin.com/'; + a.text = 'manually'; + a.target = '_blank'; + errorNote.appendChild(a); + errorNote.appendText('.'); + new Notice(errorNote,); } + } catch (error) { + const errorNote = document.createDocumentFragment(); + errorNote.appendText('Error creating task in Amazing Marvin. You can try again or do it '); + console.error('Error creating task:', error); const a = document.createElement('a'); a.href = 'https://app.amazingmarvin.com/'; a.text = 'manually'; From 7c709094fe729e5a8c30d352f1fc58b71461198c Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 04:04:18 -0500 Subject: [PATCH 25/44] more fixes to the 429 handler --- src/main.ts | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main.ts b/src/main.ts index 07177f0..b964600 100644 --- a/src/main.ts +++ b/src/main.ts @@ -254,16 +254,23 @@ export default class AmazingMarvinPlugin extends Plugin { if (remoteResponse.status === 200) { new Notice("Task marked as done in Amazing Marvin."); return remoteResponse.json; - } - } catch (error) { - const errorNote = document.createDocumentFragment(); - if (error.remoteResponse.status === 429) { + } else if (remoteResponse.status === 429) { + const errorNote = document.createDocumentFragment(); errorNote.appendText('Your request was throttled by Amazing Marvin. Or do it manually at '); console.error('Your request was throttled by Amazing Marvin. Wait a few minutes and try again. Or do it manually.'); - } else { - errorNote.appendText('Error marking task as done in Amazing Marvin. You should do it '); - console.error('Error marking task as done:', error); + const a = document.createElement('a'); + a.href = 'https://app.amazingmarvin.com/#t=' + taskId; + a.text = 'manually'; + a.target = '_blank'; + errorNote.appendChild(a); + + new Notice(errorNote, 0); + } + } catch (error) { + const errorNote = document.createDocumentFragment(); + errorNote.appendText('Error marking task as done in Amazing Marvin. You should do it '); + console.error('Error marking task as done:', error); const a = document.createElement('a'); a.href = 'https://app.amazingmarvin.com/#t=' + taskId; From 1d11ea1327adfc62f87d0207174a1c8faf10fd69 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 04:05:13 -0500 Subject: [PATCH 26/44] Make the handler more flexible so as to be compatible with Task Plugin and other plugins that decorate tasks on completion --- src/amTaskWatcher.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/amTaskWatcher.ts b/src/amTaskWatcher.ts index c8380df..e66b735 100644 --- a/src/amTaskWatcher.ts +++ b/src/amTaskWatcher.ts @@ -19,15 +19,13 @@ export function amTaskWatcher(_app: App, plugin: AmazingMarvinPlugin) { return; } update.changes.iterChanges((fromA, _toA, _fromB, _toB, change) => { - //only match if the change is a single character and it's an X or x - if (change.length === 1 && (change.sliceString(0, 1) === "X" || change.sliceString(0, 1) === "x")) { + console.log("change", change) + //only match if the change is on an AM task and it's a completed task let line = update.state.doc.lineAt(fromA).text; - const match = line.match(COMPLETED_AM_TASK); if (match && match[1]) { plugin.markDone(match[1]); } - } }); } }, From b5d706b5854bedb60efd7ba4f34a7345cf0c5c2e Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 04:11:41 -0500 Subject: [PATCH 27/44] Update to version 0.5.1 --- manifest.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index 83bb5f3..208520e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.5.0", + "version": "0.5.1", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index 49e5901..cd3dd79 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.5.0", + "version": "0.5.1", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index d095180..14ff0df 100644 --- a/versions.json +++ b/versions.json @@ -14,5 +14,6 @@ "0.5.0b2": "1.4.16", "0.5.0b3": "1.4.16", "0.5.0b4": "1.4.16", - "0.5.0": "1.4.16" + "0.5.0": "1.4.16", + "0.5.1": "1.4.16" } From 9b99d3787168da5443ad8ea94d712e58b2d06d66 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 04:16:35 -0500 Subject: [PATCH 28/44] Remove console.log statement in amTaskWatcher function --- src/amTaskWatcher.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/amTaskWatcher.ts b/src/amTaskWatcher.ts index e66b735..7320ebf 100644 --- a/src/amTaskWatcher.ts +++ b/src/amTaskWatcher.ts @@ -19,13 +19,12 @@ export function amTaskWatcher(_app: App, plugin: AmazingMarvinPlugin) { return; } update.changes.iterChanges((fromA, _toA, _fromB, _toB, change) => { - console.log("change", change) //only match if the change is on an AM task and it's a completed task - let line = update.state.doc.lineAt(fromA).text; - const match = line.match(COMPLETED_AM_TASK); - if (match && match[1]) { - plugin.markDone(match[1]); - } + let line = update.state.doc.lineAt(fromA).text; + const match = line.match(COMPLETED_AM_TASK); + if (match && match[1]) { + plugin.markDone(match[1]); + } }); } }, From 36b191820aea9b427794b4a452faa8118af3215d Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 05:20:07 -0500 Subject: [PATCH 29/44] Encode filepath and vaultName fix casing of filepath parameter --- src/main.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.ts b/src/main.ts index b964600..465594f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -175,8 +175,10 @@ export default class AmazingMarvinPlugin extends Plugin { } if (notePath && notePath !== '') { - requestBody.note = `[🏷️](obsidian://advanced-uri?filePath=${notePath}${vaultName !== '' ? `&vault=${vaultName}` : ''})`; - } + let encodedVaultName = vaultName !== '' ? encodeURIComponent(vaultName) : ''; + let encodedNotePath = encodeURIComponent(encodeURIComponent(notePath)); + requestBody.note = `[🏷️](obsidian://advanced-uri?filepath=${encodedNotePath}${encodedVaultName !== '' ? `&vault=${encodedVaultName}` : ''})`; + } try { const remoteResponse = await requestUrl({ From 23e64524b1022047d02fdcbf43e845fbbe50dacf Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 05:21:58 -0500 Subject: [PATCH 30/44] Update to version 0.5.2 --- manifest.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index 208520e..282272f 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.5.1", + "version": "0.5.2", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index cd3dd79..c46838b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.5.1", + "version": "0.5.2", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index 14ff0df..b59bc9f 100644 --- a/versions.json +++ b/versions.json @@ -15,5 +15,6 @@ "0.5.0b3": "1.4.16", "0.5.0b4": "1.4.16", "0.5.0": "1.4.16", - "0.5.1": "1.4.16" + "0.5.1": "1.4.16", + "0.5.2": "1.4.16" } From ece8ce182c6e6907f50d671d7d4993701621558b Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 05:35:17 -0500 Subject: [PATCH 31/44] Update to version 0.5.3 --- manifest.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index 282272f..0a24827 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.5.2", + "version": "0.5.3", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index c46838b..67f37ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.5.2", + "version": "0.5.3", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index b59bc9f..203aca9 100644 --- a/versions.json +++ b/versions.json @@ -16,5 +16,6 @@ "0.5.0b4": "1.4.16", "0.5.0": "1.4.16", "0.5.1": "1.4.16", - "0.5.2": "1.4.16" + "0.5.2": "1.4.16", + "0.5.3": "1.4.16" } From f2bd85d423bc01e242ac62a78a4ccb097820bb44 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 05:50:40 -0500 Subject: [PATCH 32/44] update BRAT release to 0.5.3 --- manifest-beta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest-beta.json b/manifest-beta.json index 83bb5f3..0a24827 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.5.0", + "version": "0.5.3", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", From ce02ec5f4e2234806ae9c113724c68da92d64fef Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 07:25:06 -0500 Subject: [PATCH 33/44] Fixes #35 --- src/main.ts | 33 ++++++++++++++++++------------ src/settings.ts | 53 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/src/main.ts b/src/main.ts index 465594f..fdc60a3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -175,9 +175,12 @@ export default class AmazingMarvinPlugin extends Plugin { } if (notePath && notePath !== '') { - let encodedVaultName = vaultName !== '' ? encodeURIComponent(vaultName) : ''; - let encodedNotePath = encodeURIComponent(encodeURIComponent(notePath)); - requestBody.note = `[🏷️](obsidian://advanced-uri?filepath=${encodedNotePath}${encodedVaultName !== '' ? `&vault=${encodedVaultName}` : ''})`; + let link = `obsidian://open?file=${encodeURI(notePath)}${vaultName !== '' ? `&vault=${encodeURI(vaultName)}` : ''}`; + if (this.settings.linkBackToObsidianText !== '') { + requestBody.note = `[${this.settings.linkBackToObsidianText}](${link})`; + } else { + requestBody.note = link; + } } try { @@ -253,21 +256,25 @@ export default class AmazingMarvinPlugin extends Plugin { body: JSON.stringify(requestBody) }); + const note = document.createDocumentFragment(); + const a = document.createElement('a'); + a.href = 'https://app.amazingmarvin.com/#t=' + taskId; + + a.target = '_blank'; + if (remoteResponse.status === 200) { - new Notice("Task marked as done in Amazing Marvin."); + a.text = 'Task'; + note.append(a); + note.appendText(' marked as done in Amazing Marvin.'); + new Notice(note, 5000); return remoteResponse.json; } else if (remoteResponse.status === 429) { - const errorNote = document.createDocumentFragment(); - errorNote.appendText('Your request was throttled by Amazing Marvin. Or do it manually at '); - console.error('Your request was throttled by Amazing Marvin. Wait a few minutes and try again. Or do it manually.'); - const a = document.createElement('a'); - a.href = 'https://app.amazingmarvin.com/#t=' + taskId; a.text = 'manually'; - a.target = '_blank'; - errorNote.appendChild(a); - - new Notice(errorNote, 0); + note.appendText('Your request was throttled by Amazing Marvin. Do it manually at '); + console.error('Your request was throttled by Amazing Marvin. Wait a few minutes and try again. Or do it manually.'); + note.appendChild(a); + new Notice(note, 0); } } catch (error) { const errorNote = document.createDocumentFragment(); diff --git a/src/settings.ts b/src/settings.ts index db59627..a52bc39 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -2,6 +2,7 @@ import { App, Platform, PluginSettingTab, Setting } from "obsidian"; import AmazingMarvinPlugin from "./main"; export interface AmazingMarvinPluginSettings { + linkBackToObsidianText: string; attemptToMarkTasksAsDone: any; useLocalServer: boolean; localServerHost: string; @@ -14,6 +15,7 @@ export interface AmazingMarvinPluginSettings { } export const DEFAULT_SETTINGS: AmazingMarvinPluginSettings = { + linkBackToObsidianText: '', useLocalServer: false, localServerHost: "localhost", localServerPort: 12082, @@ -33,22 +35,16 @@ export class AmazingMarvinSettingsTab extends PluginSettingTab { this.plugin = plugin; } - private getAPILink(): HTMLAnchorElement { - const a = document.createElement('a'); - a.href = 'https://app.amazingmarvin.com/pre?api'; - a.text = 'API page'; - a.target = '_blank'; - return a; - } + // refactor a function for link creation that takes the href and text as parameters - private getLocalAPIDocs(): HTMLAnchorElement { - const a = document.createElement('a'); - a.href = 'https://help.amazingmarvin.com/en/articles/5165191-desktop-local-api-server'; - a.text = 'Desktop Local API Server'; - a.target = '_blank'; - return a; - } +private a(href: string, text: string) { + const a = document.createElement('a'); + a.href = href; + a.text = text; + a.target = '_blank'; + return a; +} display(): void { const { containerEl } = this; @@ -56,7 +52,7 @@ export class AmazingMarvinSettingsTab extends PluginSettingTab { const TokenDescEl = document.createDocumentFragment(); TokenDescEl.appendText('Get your Token at the '); - TokenDescEl.appendChild(this.getAPILink()); + TokenDescEl.appendChild(this.a('https://app.amazingmarvin.com/pre?api', 'API page')); new Setting(containerEl) .setName("API Token") @@ -73,7 +69,7 @@ export class AmazingMarvinSettingsTab extends PluginSettingTab { new Setting(containerEl) .setName("Mark tasks as done") - .setDesc("Attempt to mark tasks as done in Amazing Marvin") + .setDesc("Attempt to mark tasks as done in Amazing Marvin. Note that this only applies to Amazing Marvins tasks imported or created with this plugin.") .addToggle(toggle => toggle .setValue(this.plugin.settings.attemptToMarkTasksAsDone) .onChange(async (value) => { @@ -99,6 +95,29 @@ export class AmazingMarvinSettingsTab extends PluginSettingTab { }) ); + new Setting(containerEl) + .setHeading().setName("Task creation"); + + + const noteLink = document.createDocumentFragment(); + // make this text much shorter + noteLink.appendText('Text for note back to Obsidian on tasks created with this plugin. If empty, a link be added.'); + noteLink.append(document.createElement('br')); + + new Setting(containerEl) + .setName("Note link text") + .setDesc(noteLink) + .addText((text) => + text + .setPlaceholder("Note link text") + .setValue(this.plugin.settings.linkBackToObsidianText) + .onChange(async (value) => { + this.plugin.settings.linkBackToObsidianText = value.trim(); + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) .setHeading().setName("Task formatting"); @@ -135,7 +154,7 @@ export class AmazingMarvinSettingsTab extends PluginSettingTab { if (Platform.isDesktopApp) { const lsDescEl = document.createDocumentFragment(); lsDescEl.appendText('The local API can speed up the plugin. See the '); - lsDescEl.appendChild(this.getLocalAPIDocs()); + lsDescEl.appendChild(this.a('https://help.amazingmarvin.com/en/articles/5165191-desktop-local-api-server', 'Desktop Local API Server')); lsDescEl.appendText(' for more information.'); let ls = new Setting(containerEl) From 077fc30f229153e677d713582d386b4d7cc1e3d5 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 07:27:44 -0500 Subject: [PATCH 34/44] Update to version 0.5.4b --- manifest-beta.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest-beta.json b/manifest-beta.json index 0a24827..17db8d3 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.5.3", + "version": "0.5.4b", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index 67f37ad..37fbb2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.5.3", + "version": "0.5.4b", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index 203aca9..74b7df9 100644 --- a/versions.json +++ b/versions.json @@ -17,5 +17,6 @@ "0.5.0": "1.4.16", "0.5.1": "1.4.16", "0.5.2": "1.4.16", - "0.5.3": "1.4.16" + "0.5.3": "1.4.16", + "0.5.4b": "1.4.16" } From 960fef70bf0fb32010ddc1a82a886fa63be98a1e Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 07:27:54 -0500 Subject: [PATCH 35/44] Update to version 0.5.4 --- manifest.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index 0a24827..0ff77fd 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.5.3", + "version": "0.5.4", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index 37fbb2b..3b1b565 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.5.4b", + "version": "0.5.4", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index 74b7df9..6e869c7 100644 --- a/versions.json +++ b/versions.json @@ -18,5 +18,6 @@ "0.5.1": "1.4.16", "0.5.2": "1.4.16", "0.5.3": "1.4.16", - "0.5.4b": "1.4.16" + "0.5.4b": "1.4.16", + "0.5.4": "1.4.16" } From 94eb5951b7d19d5b0a5ce2a3feacec1d530c9b06 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 08:25:11 -0500 Subject: [PATCH 36/44] add manifest.json to release --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ab508b9..0168642 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,4 +44,5 @@ jobs: --draft \ dist/main-debug.js \ dist/main.js \ + dist/mainifest.json \ ${{ env.PLUGIN_NAME }}.zip From 19eb6e2371b6c406affe477c025054926b0694b7 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 08:25:32 -0500 Subject: [PATCH 37/44] Update to version 0.6.0 --- manifest.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index 0ff77fd..85cbb01 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.5.4", + "version": "0.6.0", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index 3b1b565..d520f55 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.5.4", + "version": "0.6.0", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index 6e869c7..a3395a9 100644 --- a/versions.json +++ b/versions.json @@ -19,5 +19,6 @@ "0.5.2": "1.4.16", "0.5.3": "1.4.16", "0.5.4b": "1.4.16", - "0.5.4": "1.4.16" + "0.5.4": "1.4.16", + "0.6.0": "1.4.16" } From 657e435c88cca7bdb008c7b4231dfef160f7c064 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 08:27:21 -0500 Subject: [PATCH 38/44] typo fix --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0168642..7a7af89 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,5 +44,5 @@ jobs: --draft \ dist/main-debug.js \ dist/main.js \ - dist/mainifest.json \ + dist/manifest.json \ ${{ env.PLUGIN_NAME }}.zip From 64eea9312c807e4a3abf460644d5b5043c10a731 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 08:27:44 -0500 Subject: [PATCH 39/44] Update to version 0.9.0 --- manifest.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index 85cbb01..5b14bd6 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.6.0", + "version": "0.9.0", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index d520f55..ae65ddb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.6.0", + "version": "0.9.0", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index a3395a9..946cd22 100644 --- a/versions.json +++ b/versions.json @@ -20,5 +20,6 @@ "0.5.3": "1.4.16", "0.5.4b": "1.4.16", "0.5.4": "1.4.16", - "0.6.0": "1.4.16" + "0.6.0": "1.4.16", + "0.9.0": "1.4.16" } From 1a8410ade43ca2943ead7b395a4c8ca692b85288 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 26 Dec 2023 08:29:00 -0500 Subject: [PATCH 40/44] Update BRAT release --- manifest-beta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest-beta.json b/manifest-beta.json index 17db8d3..5b14bd6 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin", - "version": "0.5.4b", + "version": "0.9.0", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", From 8e969fffe82e8102164b7ad640949df992abaf4b Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Fri, 29 Dec 2023 13:02:07 -0500 Subject: [PATCH 41/44] Update manifest.json --- manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifest.json b/manifest.json index 5b14bd6..5a23e49 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", - "name": "Amazing Marvin", - "version": "0.9.0", + "name": "Amazing Marvin by Cloud Atlas", + "version": "0.9.1", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", From 33a813b11b05eeee737fc3979f3eebf6150931e4 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 2 Jan 2024 19:02:25 -0500 Subject: [PATCH 42/44] remove unused code --- src/regexp-cursor.ts | 195 ------------------------------------------- 1 file changed, 195 deletions(-) delete mode 100644 src/regexp-cursor.ts diff --git a/src/regexp-cursor.ts b/src/regexp-cursor.ts deleted file mode 100644 index c9bec08..0000000 --- a/src/regexp-cursor.ts +++ /dev/null @@ -1,195 +0,0 @@ -// from https://github.com/codemirror/search/blob/main/src/regexp.ts - -import {Text, TextIterator} from "@codemirror/state" - -const empty = {from: -1, to: -1, match: /.*/.exec("")!} - -const baseFlags = "gm" + (/x/.unicode == null ? "" : "u") - -export interface RegExpCursorOptions { - ignoreCase?: boolean - test?: (from: number, to: number, match: RegExpExecArray) => boolean -} - -/// This class is similar to [`SearchCursor`](#search.SearchCursor) -/// but searches for a regular expression pattern instead of a plain -/// string. -export class RegExpCursor implements Iterator<{from: number, to: number, match: RegExpExecArray}> { - private iter!: TextIterator - private re!: RegExp - private test?: (from: number, to: number, match: RegExpExecArray) => boolean - private curLine = "" - private curLineStart!: number - private matchPos!: number - - /// Set to `true` when the cursor has reached the end of the search - /// range. - done = false - - /// Will contain an object with the extent of the match and the - /// match object when [`next`](#search.RegExpCursor.next) - /// sucessfully finds a match. - value = empty - - /// Create a cursor that will search the given range in the given - /// document. `query` should be the raw pattern (as you'd pass it to - /// `new RegExp`). - constructor(private text: Text, query: string, options?: RegExpCursorOptions, - from: number = 0, private to: number = text.length) { - if (/\\[sWDnr]|\n|\r|\[\^/.test(query)) return new MultilineRegExpCursor(text, query, options, from, to) as any - this.re = new RegExp(query, baseFlags + (options?.ignoreCase ? "i" : "")) - this.test = options?.test - this.iter = text.iter() - let startLine = text.lineAt(from) - this.curLineStart = startLine.from - this.matchPos = toCharEnd(text, from) - this.getLine(this.curLineStart) - } - - private getLine(skip: number) { - this.iter.next(skip) - if (this.iter.lineBreak) { - this.curLine = "" - } else { - this.curLine = this.iter.value - if (this.curLineStart + this.curLine.length > this.to) - this.curLine = this.curLine.slice(0, this.to - this.curLineStart) - this.iter.next() - } - } - - private nextLine() { - this.curLineStart = this.curLineStart + this.curLine.length + 1 - if (this.curLineStart > this.to) this.curLine = "" - else this.getLine(0) - } - - /// Move to the next match, if there is one. - next() { - for (let off = this.matchPos - this.curLineStart;;) { - this.re.lastIndex = off - let match = this.matchPos <= this.to && this.re.exec(this.curLine) - if (match) { - let from = this.curLineStart + match.index, to = from + match[0].length - this.matchPos = toCharEnd(this.text, to + (from == to ? 1 : 0)) - if (from == this.curLineStart + this.curLine.length) this.nextLine() - if ((from < to || from > this.value.to) && (!this.test || this.test(from, to, match))) { - this.value = {from, to, match} - return this - } - off = this.matchPos - this.curLineStart - } else if (this.curLineStart + this.curLine.length < this.to) { - this.nextLine() - off = 0 - } else { - this.done = true - return this - } - } - } - - [Symbol.iterator]!: () => Iterator<{from: number, to: number, match: RegExpExecArray}> -} - -const flattened = new WeakMap() - -// Reusable (partially) flattened document strings -class FlattenedDoc { - constructor(readonly from: number, - readonly text: string) {} - get to() { return this.from + this.text.length } - - static get(doc: Text, from: number, to: number) { - let cached = flattened.get(doc) - if (!cached || cached.from >= to || cached.to <= from) { - let flat = new FlattenedDoc(from, doc.sliceString(from, to)) - flattened.set(doc, flat) - return flat - } - if (cached.from == from && cached.to == to) return cached - let {text, from: cachedFrom} = cached - if (cachedFrom > from) { - text = doc.sliceString(from, cachedFrom) + text - cachedFrom = from - } - if (cached.to < to) - text += doc.sliceString(cached.to, to) - flattened.set(doc, new FlattenedDoc(cachedFrom, text)) - return new FlattenedDoc(from, text.slice(from - cachedFrom, to - cachedFrom)) - } -} - -const enum Chunk { Base = 5000 } - -class MultilineRegExpCursor implements Iterator<{from: number, to: number, match: RegExpExecArray}> { - private flat: FlattenedDoc - private matchPos - private re: RegExp - private test?: (from: number, to: number, match: RegExpExecArray) => boolean - - done = false - value = empty - - constructor(private text: Text, query: string, options: RegExpCursorOptions | undefined, from: number, private to: number) { - this.matchPos = toCharEnd(text, from) - this.re = new RegExp(query, baseFlags + (options?.ignoreCase ? "i" : "")) - this.test = options?.test - this.flat = FlattenedDoc.get(text, from, this.chunkEnd(from + Chunk.Base)) - } - - private chunkEnd(pos: number) { - return pos >= this.to ? this.to : this.text.lineAt(pos).to - } - - next() { - for (;;) { - let off = this.re.lastIndex = this.matchPos - this.flat.from - let match = this.re.exec(this.flat.text) - // Skip empty matches directly after the last match - if (match && !match[0] && match.index == off) { - this.re.lastIndex = off + 1 - match = this.re.exec(this.flat.text) - } - if (match) { - let from = this.flat.from + match.index, to = from + match[0].length - // If a match goes almost to the end of a noncomplete chunk, try - // again, since it'll likely be able to match more - if ((this.flat.to >= this.to || match.index + match[0].length <= this.flat.text.length - 10) && - (!this.test || this.test(from, to, match))) { - this.value = {from, to, match} - this.matchPos = toCharEnd(this.text, to + (from == to ? 1 : 0)) - return this - } - } - if (this.flat.to == this.to) { - this.done = true - return this - } - // Grow the flattened doc - this.flat = FlattenedDoc.get(this.text, this.flat.from, this.chunkEnd(this.flat.from + this.flat.text.length * 2)) - } - } - - [Symbol.iterator]!: () => Iterator<{from: number, to: number, match: RegExpExecArray}> -} - -if (typeof Symbol != "undefined") { - RegExpCursor.prototype[Symbol.iterator] = MultilineRegExpCursor.prototype[Symbol.iterator] = - function(this: RegExpCursor) { return this } -} - -export function validRegExp(source: string) { - try { - new RegExp(source, baseFlags) - return true - } catch { - return false - } -} - -function toCharEnd(text: Text, pos: number) { - if (pos >= text.length) return pos - let line = text.lineAt(pos), next - while (pos < line.to && (next = line.text.charCodeAt(pos - line.from)) >= 0xDC00 && next < 0xE000) pos++ - return pos -} From 6264135b7017911fc05764b5284f9a411522e89c Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 2 Jan 2024 19:19:27 -0500 Subject: [PATCH 43/44] Move styling to css and fix it --- .github/workflows/release.yml | 1 + src/addTaskModal.ts | 3 --- styles.css | 5 +++++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7a7af89..ba9867b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,6 +42,7 @@ jobs: gh release create "$tag" \ --title="$tag" \ --draft \ + dist/styles.css \ dist/main-debug.js \ dist/main.js \ dist/manifest.json \ diff --git a/src/addTaskModal.ts b/src/addTaskModal.ts index 968f1f1..411e669 100644 --- a/src/addTaskModal.ts +++ b/src/addTaskModal.ts @@ -105,9 +105,6 @@ export class AddTaskModal extends Modal { new Setting(contentEl) .addTextArea((textArea: TextAreaComponent) => { - textArea.inputEl.style.minHeight = "5em"; - textArea.inputEl.style.minWidth = "100%"; - textArea.onChange((value: string) => { this.result.task = value; }); diff --git a/styles.css b/styles.css index 71cc60f..6640178 100644 --- a/styles.css +++ b/styles.css @@ -6,3 +6,8 @@ available in the app when your plugin is enabled. If your plugin does not need CSS, delete this file. */ + +.am-task-textarea-setting textarea{ + min-height: 5em; + width: 200%; +} From 0c58b915577cb872b9060e06df754254f96a70f6 Mon Sep 17 00:00:00 2001 From: Muness Castle <931+muness@users.noreply.github.com> Date: Tue, 2 Jan 2024 19:20:01 -0500 Subject: [PATCH 44/44] Update to version 0.9.2 --- manifest.json | 2 +- package.json | 2 +- versions.json | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index 5a23e49..dc92288 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "cloudatlas-o-am", "name": "Amazing Marvin by Cloud Atlas", - "version": "0.9.1", + "version": "0.9.2", "minAppVersion": "1.4.16", "description": "Integration with Amazing Marvin", "author": "Cloud Atlas", diff --git a/package.json b/package.json index ae65ddb..e8b1b7a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloud-atlas", - "version": "0.9.0", + "version": "0.9.2", "description": "Interoperability between Obsidian and Amazing Marvin", "main": "dist/main.js", "scripts": { diff --git a/versions.json b/versions.json index 946cd22..febb80c 100644 --- a/versions.json +++ b/versions.json @@ -21,5 +21,6 @@ "0.5.4b": "1.4.16", "0.5.4": "1.4.16", "0.6.0": "1.4.16", - "0.9.0": "1.4.16" + "0.9.0": "1.4.16", + "0.9.2": "1.4.16" }