mirror of
https://github.com/tmfelwu/obsidian-inbox.git
synced 2026-07-22 07:40:30 +00:00
done required change
This commit is contained in:
parent
863346341f
commit
b0d434d6cb
8 changed files with 347 additions and 314 deletions
25
README.md
25
README.md
|
|
@ -1,8 +1,21 @@
|
||||||
|
|
||||||
# Defaults
|
# Usage logic
|
||||||
- There should be a file `Inbox` at the root of the vault.
|
|
||||||
- When you use the associated shortcut a modal opens up to pasete your thought.
|
- [x] Use the shortcut key will trigger the plugin.
|
||||||
- Presss `Ctrl+Enter` to add it to `Inbox`
|
- [x] A modal will open with 'Note Title', 'Note Body' and 'Submit Button'
|
||||||
|
- [ ] As user types the datalist will show relevant `note path` in the Vault.
|
||||||
|
- [x] Navigation
|
||||||
|
- [x] If the user press `Enter` while the datalist length > 0 the first item in current datalist will be navigated to.
|
||||||
|
- [x] Another way is to use up and down arrow key and press `Enter`
|
||||||
|
- Create New Notes
|
||||||
|
- If content is empty and note of the same name doesnt exist
|
||||||
|
- [x] Create New Note
|
||||||
|
- If content is present.
|
||||||
|
- [ ] If note exists with similar name give Notice error.
|
||||||
|
- [ ] If note doesnt exist with same name, create the note with content.
|
||||||
|
- Creating the new notes
|
||||||
|
- Press `Ctrl+Enter` or
|
||||||
|
- Press `Submit` button at the bottom.
|
||||||
|
|
||||||
# Setup for OS to associate shortcut key
|
# Setup for OS to associate shortcut key
|
||||||
|
|
||||||
|
|
@ -54,3 +67,7 @@ On Ubuntu 22.04, you can set up a global hotkey to trigger the Obsidian plugin c
|
||||||
8. Close the settings application.
|
8. Close the settings application.
|
||||||
|
|
||||||
Now the global hotkey should be active and trigger the plugin command from anywhere in your operating system.
|
Now the global hotkey should be active and trigger the plugin command from anywhere in your operating system.
|
||||||
|
|
||||||
|
|
||||||
|
# Conversation
|
||||||
|
Naman - https://chat.openai.com/c/3021e291-47a7-44b0-a0f6-7cc4ad58ba67
|
||||||
|
|
|
||||||
350
main.js
350
main.js
|
|
@ -1,128 +1,94 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
var __extends = (this && this.__extends) || (function () {
|
|
||||||
var extendStatics = function (d, b) {
|
|
||||||
extendStatics = Object.setPrototypeOf ||
|
|
||||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
||||||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
||||||
return extendStatics(d, b);
|
|
||||||
};
|
|
||||||
return function (d, b) {
|
|
||||||
if (typeof b !== "function" && b !== null)
|
|
||||||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
||||||
extendStatics(d, b);
|
|
||||||
function __() { this.constructor = d; }
|
|
||||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
||||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
||||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
||||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
||||||
function step(op) {
|
|
||||||
if (f) throw new TypeError("Generator is already executing.");
|
|
||||||
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
||||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
||||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
||||||
switch (op[0]) {
|
|
||||||
case 0: case 1: t = op; break;
|
|
||||||
case 4: _.label++; return { value: op[1], done: false };
|
|
||||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
||||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
||||||
default:
|
|
||||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
||||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
||||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
||||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
||||||
if (t[2]) _.ops.pop();
|
|
||||||
_.trys.pop(); continue;
|
|
||||||
}
|
|
||||||
op = body.call(thisArg, _);
|
|
||||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
||||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
var obsidian_1 = require("obsidian");
|
const obsidian_1 = require("obsidian");
|
||||||
var TextInputModal = /** @class */ (function (_super) {
|
class TextInputModal extends obsidian_1.Modal {
|
||||||
__extends(TextInputModal, _super);
|
constructor(app, onSubmit) {
|
||||||
function TextInputModal(app, onSubmit) {
|
super(app);
|
||||||
var _this = _super.call(this, app) || this;
|
this.onSubmit = onSubmit;
|
||||||
_this.onSubmit = onSubmit;
|
|
||||||
return _this;
|
|
||||||
}
|
}
|
||||||
TextInputModal.prototype.onOpen = function () {
|
noteExists(title) {
|
||||||
var _this = this;
|
const existingNote = this.app.metadataCache.getFirstLinkpathDest(title, '');
|
||||||
|
return existingNote ? true : false;
|
||||||
|
}
|
||||||
|
onOpen() {
|
||||||
// Create a container for better layout control
|
// Create a container for better layout control
|
||||||
var container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.style.display = 'flex';
|
container.classList.add('container');
|
||||||
container.style.flexDirection = 'column';
|
|
||||||
container.style.gap = '1rem';
|
|
||||||
container.style.padding = '1rem';
|
|
||||||
this.contentEl.appendChild(container);
|
this.contentEl.appendChild(container);
|
||||||
// Add a title input field
|
// Add a title input field
|
||||||
this.titleInput = document.createElement('input');
|
this.titleInput = document.createElement('input');
|
||||||
this.titleInput.type = 'text';
|
this.titleInput.type = 'text';
|
||||||
this.titleInput.placeholder = 'Enter note title';
|
this.titleInput.placeholder = 'Enter note title';
|
||||||
this.titleInput.style.fontSize = '1.1em';
|
this.titleInput.classList.add('title-input');
|
||||||
this.titleInput.style.padding = '0.5rem';
|
|
||||||
this.titleInput.style.border = '1px solid var(--text-faint)';
|
|
||||||
this.titleInput.style.borderRadius = '4px';
|
|
||||||
container.appendChild(this.titleInput);
|
container.appendChild(this.titleInput);
|
||||||
// Add a datalist for existing notes
|
// Add a datalist for existing notes
|
||||||
this.datalist = document.createElement('datalist');
|
this.datalist = document.createElement('datalist');
|
||||||
this.datalist.id = 'note-titles';
|
this.datalist.id = 'note-titles';
|
||||||
container.appendChild(this.datalist);
|
container.appendChild(this.datalist);
|
||||||
|
const noteTitles = this.app.vault.getMarkdownFiles().map((note) => note.basename);
|
||||||
|
const notePaths = this.app.vault.getMarkdownFiles().map((note) => note.path);
|
||||||
|
// Function to update the datalist with matching note titles
|
||||||
|
const updateDatalist = (searchText) => {
|
||||||
|
// Clear the existing datalist
|
||||||
|
this.datalist.innerHTML = '';
|
||||||
|
// Filter the noteTitles array based on the user's input
|
||||||
|
const filteredTitles = noteTitles.filter((title) => title.toLowerCase().includes(searchText.toLowerCase()));
|
||||||
|
// Add the top 10 matching items to the datalist
|
||||||
|
const maxItems = 10;
|
||||||
|
for (let i = 0; i < Math.min(maxItems, filteredTitles.length); i++) {
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.value = filteredTitles[i];
|
||||||
|
this.datalist.appendChild(option);
|
||||||
|
}
|
||||||
|
};
|
||||||
// Set the list attribute for the title input field
|
// Set the list attribute for the title input field
|
||||||
|
// By setting the list attribute of the input element to the id of the datalist element, you're associating the input field with the datalist. This association allows the browser to display the options in the datalist as suggestions when the user starts typing in the input field.
|
||||||
this.titleInput.setAttribute('list', 'note-titles');
|
this.titleInput.setAttribute('list', 'note-titles');
|
||||||
// Populate the datalist with note titles
|
// If Enter is pressed we want to navigate to existing note.
|
||||||
var noteTitles = this.app.vault.getMarkdownFiles().map(function (note) { return note.basename; });
|
this.titleInput.addEventListener('keydown', (event) => {
|
||||||
var maxItems = 10;
|
if (event.key === 'Enter') {
|
||||||
var itemCount = 0;
|
event.preventDefault(); // Prevent the default action of submitting the form
|
||||||
for (var _i = 0, noteTitles_1 = noteTitles; _i < noteTitles_1.length; _i++) {
|
// if the list has items we choose the first one.
|
||||||
var title = noteTitles_1[_i];
|
if (this.datalist.childNodes.length > 0) {
|
||||||
if (itemCount >= maxItems) {
|
const firstOption = this.datalist.childNodes[0];
|
||||||
break;
|
this.onSubmit(firstOption.value, null);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
// Implies no note with same name tf. create new note
|
||||||
|
if (this.datalist.childNodes.length == 0) {
|
||||||
|
this.onSubmit(event.target.value, '');
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var option = document.createElement('option');
|
});
|
||||||
option.value = title;
|
|
||||||
this.datalist.appendChild(option);
|
|
||||||
itemCount++;
|
|
||||||
}
|
|
||||||
// Navigate to the selected note from the datalist
|
// Navigate to the selected note from the datalist
|
||||||
this.titleInput.addEventListener('change', function (event) {
|
this.titleInput.addEventListener('change', (event) => {
|
||||||
var selectedTitle = event.target.value;
|
event.preventDefault();
|
||||||
var selectedNote = _this.app.vault.getAbstractFileByPath("".concat(selectedTitle, ".md"));
|
if (this.noteExists(event.target.value)) {
|
||||||
if (selectedNote) {
|
const selectedTitle = event.target.value;
|
||||||
_this.close();
|
this.onSubmit(selectedTitle, null);
|
||||||
_this.app.workspace.activeLeaf.openFile(selectedNote);
|
this.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// Add an input event listener on the titleInput to update the datalist based on the user's input
|
||||||
|
this.titleInput.addEventListener('input', (event) => {
|
||||||
|
const searchText = event.target.value;
|
||||||
|
updateDatalist(searchText);
|
||||||
|
});
|
||||||
// Add a textarea for note content
|
// Add a textarea for note content
|
||||||
this.textarea = document.createElement('textarea');
|
this.textarea = document.createElement('textarea');
|
||||||
this.textarea.rows = 5;
|
this.textarea.rows = 5;
|
||||||
this.textarea.placeholder = 'Enter note content';
|
this.textarea.placeholder = 'Enter note content';
|
||||||
this.textarea.style.fontSize = '1em';
|
this.textarea.classList.add('textarea-custom');
|
||||||
this.textarea.style.padding = '0.5rem';
|
this.textarea.addEventListener('keydown', (event) => {
|
||||||
this.textarea.style.border = '1px solid var(--text-faint)';
|
if (event.key === 'Enter' && event.ctrlKey) {
|
||||||
this.textarea.style.borderRadius = '4px';
|
this.onSubmit(this.titleInput.value, this.textarea.value);
|
||||||
this.textarea.style.resize = 'vertical';
|
this.close();
|
||||||
// this.textarea.addEventListener('keydown', (event) => {
|
}
|
||||||
// if (event.key === 'Enter' && event.ctrlKey) {
|
else if (event.key === 'Escape') {
|
||||||
// this.onSubmit(this.titleInput.value, this.textarea.value);
|
this.close();
|
||||||
// this.close();
|
}
|
||||||
// } else if (event.key === 'Escape') {
|
});
|
||||||
// this.close();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
container.appendChild(this.textarea);
|
container.appendChild(this.textarea);
|
||||||
// Add a submit button
|
// Add a submit button
|
||||||
this.submitButton = document.createElement('button');
|
this.submitButton = document.createElement('button');
|
||||||
|
|
@ -134,133 +100,69 @@ var TextInputModal = /** @class */ (function (_super) {
|
||||||
this.submitButton.style.borderRadius = '4px';
|
this.submitButton.style.borderRadius = '4px';
|
||||||
this.submitButton.style.cursor = 'pointer';
|
this.submitButton.style.cursor = 'pointer';
|
||||||
this.submitButton.style.backgroundColor = 'var(--background-secondary)';
|
this.submitButton.style.backgroundColor = 'var(--background-secondary)';
|
||||||
this.submitButton.addEventListener('click', function () {
|
this.submitButton.addEventListener('click', () => {
|
||||||
_this.onSubmit(_this.titleInput.value, _this.textarea.value);
|
this.onSubmit(this.titleInput.value, this.textarea.value);
|
||||||
_this.close();
|
this.close();
|
||||||
});
|
});
|
||||||
container.appendChild(this.submitButton);
|
container.appendChild(this.submitButton);
|
||||||
};
|
|
||||||
TextInputModal.prototype.onClose = function () {
|
|
||||||
this.titleInput.remove();
|
|
||||||
this.textarea.remove();
|
|
||||||
};
|
|
||||||
return TextInputModal;
|
|
||||||
}(obsidian_1.Modal));
|
|
||||||
var QuickCaptureToNotePlugin = /** @class */ (function (_super) {
|
|
||||||
__extends(QuickCaptureToNotePlugin, _super);
|
|
||||||
function QuickCaptureToNotePlugin() {
|
|
||||||
return _super !== null && _super.apply(this, arguments) || this;
|
|
||||||
}
|
}
|
||||||
QuickCaptureToNotePlugin.prototype.onload = function () {
|
}
|
||||||
return __awaiter(this, void 0, void 0, function () {
|
class QuickCaptureToNotePlugin extends obsidian_1.Plugin {
|
||||||
var _this = this;
|
async onload() {
|
||||||
return __generator(this, function (_a) {
|
this.addCommand({
|
||||||
this.addCommand({
|
id: 'quick-capture-to-note',
|
||||||
id: 'quick-capture-to-note',
|
name: 'Quick Capture to Note',
|
||||||
name: 'Quick Capture to Note',
|
callback: () => this.openCaptureModal(),
|
||||||
callback: function () { return _this.openCaptureModal(); },
|
});
|
||||||
});
|
// This is the global listeneer for obsidian url Eg. obsidian://quick-capture
|
||||||
// This is the global listeneer for obsidian url Eg. obsidian://quick-capture
|
this.registerObsidianProtocolHandler('quick-capture', () => {
|
||||||
this.registerObsidianProtocolHandler('quick-capture', function () {
|
this.openCaptureModal();
|
||||||
_this.openCaptureModal();
|
});
|
||||||
});
|
}
|
||||||
return [2 /*return*/];
|
// Open the Modal to provide title and content for the navigation or create new note
|
||||||
});
|
openCaptureModal() {
|
||||||
|
const modal = new TextInputModal(this.app, async (title, content) => {
|
||||||
|
// We create a new note
|
||||||
|
// content === '' for blank note
|
||||||
|
if (title && (content || content === '')) {
|
||||||
|
await this.createNoteWithTitle(title, content);
|
||||||
|
}
|
||||||
|
// We navigate
|
||||||
|
if (title && content === null) {
|
||||||
|
this.navigateToSelectedNote(title);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
|
||||||
//
|
|
||||||
QuickCaptureToNotePlugin.prototype.openCaptureModal = function () {
|
|
||||||
var _this = this;
|
|
||||||
var modal = new TextInputModal(this.app, function (title, content) { return __awaiter(_this, void 0, void 0, function () {
|
|
||||||
var existingNote;
|
|
||||||
return __generator(this, function (_a) {
|
|
||||||
switch (_a.label) {
|
|
||||||
case 0:
|
|
||||||
if (!(title && content)) return [3 /*break*/, 2];
|
|
||||||
return [4 /*yield*/, this.createNoteWithTitle(title, content)];
|
|
||||||
case 1:
|
|
||||||
_a.sent();
|
|
||||||
_a.label = 2;
|
|
||||||
case 2:
|
|
||||||
// If only title is provided, open the existing note
|
|
||||||
if (title && !content) {
|
|
||||||
existingNote = this.app.vault.getAbstractFileByPath("".concat(title, ".md"));
|
|
||||||
if (existingNote) {
|
|
||||||
this.app.workspace.activeLeaf.openFile(existingNote);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [2 /*return*/];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}); });
|
|
||||||
modal.open();
|
modal.open();
|
||||||
};
|
}
|
||||||
//
|
//
|
||||||
QuickCaptureToNotePlugin.prototype.createNoteWithTitle = function (title, content) {
|
async createNoteWithTitle(title, content) {
|
||||||
return __awaiter(this, void 0, void 0, function () {
|
try {
|
||||||
var noteExists, error_1;
|
let note = this.app.vault.getAbstractFileByPath(`${title}.md`);
|
||||||
return __generator(this, function (_a) {
|
if (!note) {
|
||||||
switch (_a.label) {
|
// Create new note
|
||||||
case 0:
|
await this.app.vault.create(`${title}.md`, content);
|
||||||
_a.trys.push([0, 4, , 5]);
|
// Navigate to note after creation
|
||||||
noteExists = this.app.vault.getAbstractFileByPath("".concat(title, ".md"));
|
this.navigateToSelectedNote(title);
|
||||||
if (!!noteExists) return [3 /*break*/, 2];
|
}
|
||||||
return [4 /*yield*/, this.app.vault.create("".concat(title, ".md"), content)];
|
else {
|
||||||
case 1:
|
console.error('Note with the same title already exists');
|
||||||
_a.sent();
|
}
|
||||||
return [3 /*break*/, 3];
|
}
|
||||||
case 2:
|
catch (error) {
|
||||||
console.error('Note with the same title already exists');
|
console.error('Error while creating a new note:', error);
|
||||||
_a.label = 3;
|
}
|
||||||
case 3: return [3 /*break*/, 5];
|
}
|
||||||
case 4:
|
async navigateToSelectedNote(title) {
|
||||||
error_1 = _a.sent();
|
if (title) {
|
||||||
console.error('Error while creating a new note:', error_1);
|
const existingNote = this.app.metadataCache.getFirstLinkpathDest(title, '');
|
||||||
return [3 /*break*/, 5];
|
if (existingNote instanceof obsidian_1.TFile) {
|
||||||
case 5: return [2 /*return*/];
|
// Close the modal before navigating to the selected note
|
||||||
}
|
const newLeaf = this.app.workspace.getLeaf(false);
|
||||||
});
|
await newLeaf.openFile(existingNote);
|
||||||
});
|
}
|
||||||
};
|
}
|
||||||
// To append data to an existing note called Inbox
|
}
|
||||||
// openCaptureModal() {
|
}
|
||||||
// const targetNoteTitle = 'Inbox'; // You can change this to any note title you prefer
|
|
||||||
// const targetNote = this.app.vault.getAbstractFileByPath(`${targetNoteTitle}.md`);
|
|
||||||
// const modal = new TextInputModal(this.app, async (capturedText) => {
|
|
||||||
// if (capturedText) {
|
|
||||||
// await this.appendTextToNote(targetNote, capturedText);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// modal.open();
|
|
||||||
// }
|
|
||||||
QuickCaptureToNotePlugin.prototype.appendTextToNote = function (note, text) {
|
|
||||||
return __awaiter(this, void 0, void 0, function () {
|
|
||||||
var currentContent, newContent, leaf, editor;
|
|
||||||
return __generator(this, function (_a) {
|
|
||||||
switch (_a.label) {
|
|
||||||
case 0:
|
|
||||||
if (!note) return [3 /*break*/, 4];
|
|
||||||
return [4 /*yield*/, this.app.vault.read(note)];
|
|
||||||
case 1:
|
|
||||||
currentContent = _a.sent();
|
|
||||||
newContent = currentContent + '\n' + text;
|
|
||||||
return [4 /*yield*/, this.app.vault.modify(note, newContent)];
|
|
||||||
case 2:
|
|
||||||
_a.sent();
|
|
||||||
leaf = this.app.workspace.activeLeaf;
|
|
||||||
return [4 /*yield*/, leaf.openFile(note, { state: { mode: 'source' } })];
|
|
||||||
case 3:
|
|
||||||
editor = _a.sent();
|
|
||||||
editor.setCursor(editor.lineCount(), 0);
|
|
||||||
return [3 /*break*/, 5];
|
|
||||||
case 4:
|
|
||||||
console.error('Target note not found');
|
|
||||||
_a.label = 5;
|
|
||||||
case 5: return [2 /*return*/];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
return QuickCaptureToNotePlugin;
|
|
||||||
}(obsidian_1.Plugin));
|
|
||||||
exports.default = QuickCaptureToNotePlugin;
|
exports.default = QuickCaptureToNotePlugin;
|
||||||
|
//Function to upload file to s3 bucket
|
||||||
|
//function
|
||||||
|
|
|
||||||
201
main.ts
201
main.ts
|
|
@ -1,4 +1,4 @@
|
||||||
import { App, Plugin, Modal } from 'obsidian';
|
import { App, Plugin, Modal, TFile } from 'obsidian';
|
||||||
|
|
||||||
|
|
||||||
class TextInputModal extends Modal {
|
class TextInputModal extends Modal {
|
||||||
|
|
@ -7,27 +7,28 @@ class TextInputModal extends Modal {
|
||||||
private datalist: HTMLDataListElement;
|
private datalist: HTMLDataListElement;
|
||||||
private submitButton: HTMLButtonElement;
|
private submitButton: HTMLButtonElement;
|
||||||
|
|
||||||
constructor(app, private onSubmit: (title: string, value: string) => void) {
|
constructor(app :App, private onSubmit: (title: string, value: string) => void) {
|
||||||
super(app);
|
super(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
noteExists(title: string){
|
||||||
|
const existingNote = this.app.metadataCache.getFirstLinkpathDest(title, '')
|
||||||
|
return existingNote ? true : false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
onOpen() {
|
onOpen() {
|
||||||
// Create a container for better layout control
|
// Create a container for better layout control
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.style.display = 'flex';
|
container.classList.add('container');
|
||||||
container.style.flexDirection = 'column';
|
|
||||||
container.style.gap = '1rem';
|
|
||||||
container.style.padding = '1rem';
|
|
||||||
this.contentEl.appendChild(container);
|
this.contentEl.appendChild(container);
|
||||||
|
|
||||||
// Add a title input field
|
// Add a title input field
|
||||||
this.titleInput = document.createElement('input');
|
this.titleInput = document.createElement('input');
|
||||||
this.titleInput.type = 'text';
|
this.titleInput.type = 'text';
|
||||||
this.titleInput.placeholder = 'Enter note title';
|
this.titleInput.placeholder = 'Enter note title';
|
||||||
this.titleInput.style.fontSize = '1.1em';
|
this.titleInput.classList.add('title-input');
|
||||||
this.titleInput.style.padding = '0.5rem';
|
|
||||||
this.titleInput.style.border = '1px solid var(--text-faint)';
|
|
||||||
this.titleInput.style.borderRadius = '4px';
|
|
||||||
container.appendChild(this.titleInput);
|
container.appendChild(this.titleInput);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -35,52 +36,86 @@ class TextInputModal extends Modal {
|
||||||
this.datalist = document.createElement('datalist');
|
this.datalist = document.createElement('datalist');
|
||||||
this.datalist.id = 'note-titles';
|
this.datalist.id = 'note-titles';
|
||||||
container.appendChild(this.datalist);
|
container.appendChild(this.datalist);
|
||||||
|
const noteTitles = this.app.vault.getMarkdownFiles().map((note) => note.basename);
|
||||||
|
const notePaths = this.app.vault.getMarkdownFiles().map((note) => note.path);
|
||||||
|
|
||||||
|
// Function to update the datalist with matching note titles
|
||||||
|
const updateDatalist = (searchText: string) => {
|
||||||
|
// Clear the existing datalist
|
||||||
|
this.datalist.innerHTML = '';
|
||||||
|
|
||||||
|
// Filter the noteTitles array based on the user's input
|
||||||
|
const filteredTitles = noteTitles.filter((title) => title.toLowerCase().includes(searchText.toLowerCase()));
|
||||||
|
|
||||||
|
// Add the top 10 matching items to the datalist
|
||||||
|
const maxItems = 10;
|
||||||
|
for (let i = 0; i < Math.min(maxItems, filteredTitles.length); i++) {
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.value = filteredTitles[i];
|
||||||
|
this.datalist.appendChild(option);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Set the list attribute for the title input field
|
// Set the list attribute for the title input field
|
||||||
|
// By setting the list attribute of the input element to the id of the datalist element, you're associating the input field with the datalist. This association allows the browser to display the options in the datalist as suggestions when the user starts typing in the input field.
|
||||||
this.titleInput.setAttribute('list', 'note-titles');
|
this.titleInput.setAttribute('list', 'note-titles');
|
||||||
// Populate the datalist with note titles
|
|
||||||
const noteTitles = this.app.vault.getMarkdownFiles().map((note) => note.basename);
|
|
||||||
const maxItems = 10;
|
|
||||||
let itemCount = 0;
|
|
||||||
|
|
||||||
for (const title of noteTitles) {
|
|
||||||
if (itemCount >= maxItems) {
|
|
||||||
break;
|
// If Enter is pressed we want to navigate to existing note.
|
||||||
|
this.titleInput.addEventListener('keydown', (event) => {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault(); // Prevent the default action of submitting the form
|
||||||
|
|
||||||
|
// if the list has items we choose the first one.
|
||||||
|
if (this.datalist.childNodes.length > 0) {
|
||||||
|
const firstOption = this.datalist.childNodes[0];
|
||||||
|
this.onSubmit(firstOption.value, null)
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implies no note with same name tf. create new note
|
||||||
|
if (this.datalist.childNodes.length == 0 ){
|
||||||
|
this.onSubmit(event.target.value, '')
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
const option = document.createElement('option');
|
|
||||||
option.value = title;
|
|
||||||
this.datalist.appendChild(option);
|
|
||||||
itemCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Navigate to the selected note from the datalist
|
// Navigate to the selected note from the datalist
|
||||||
this.titleInput.addEventListener('change', (event) => {
|
this.titleInput.addEventListener('change', (event) => {
|
||||||
const selectedTitle = event.target.value;
|
event.preventDefault();
|
||||||
const selectedNote = this.app.vault.getAbstractFileByPath(`${selectedTitle}.md`);
|
if (this.noteExists(event.target.value)){
|
||||||
if (selectedNote) {
|
const selectedTitle = event.target.value;
|
||||||
this.close();
|
this.onSubmit(selectedTitle, null)
|
||||||
this.app.workspace.activeLeaf.openFile(selectedNote);
|
this.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Add an input event listener on the titleInput to update the datalist based on the user's input
|
||||||
|
this.titleInput.addEventListener('input', (event) => {
|
||||||
|
const searchText = event.target.value;
|
||||||
|
updateDatalist(searchText);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// Add a textarea for note content
|
// Add a textarea for note content
|
||||||
this.textarea = document.createElement('textarea');
|
this.textarea = document.createElement('textarea');
|
||||||
this.textarea.rows = 5;
|
this.textarea.rows = 5;
|
||||||
this.textarea.placeholder = 'Enter note content';
|
this.textarea.placeholder = 'Enter note content';
|
||||||
this.textarea.style.fontSize = '1em';
|
this.textarea.classList.add('textarea-custom');
|
||||||
this.textarea.style.padding = '0.5rem';
|
this.textarea.addEventListener('keydown', (event) => {
|
||||||
this.textarea.style.border = '1px solid var(--text-faint)';
|
if (event.key === 'Enter' && event.ctrlKey) {
|
||||||
this.textarea.style.borderRadius = '4px';
|
this.onSubmit(this.titleInput.value, this.textarea.value);
|
||||||
this.textarea.style.resize = 'vertical';
|
this.close();
|
||||||
// this.textarea.addEventListener('keydown', (event) => {
|
} else if (event.key === 'Escape') {
|
||||||
// if (event.key === 'Enter' && event.ctrlKey) {
|
this.close();
|
||||||
// this.onSubmit(this.titleInput.value, this.textarea.value);
|
}
|
||||||
// this.close();
|
});
|
||||||
// } else if (event.key === 'Escape') {
|
|
||||||
// this.close();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
container.appendChild(this.textarea);
|
container.appendChild(this.textarea);
|
||||||
|
|
||||||
// Add a submit button
|
// Add a submit button
|
||||||
|
|
@ -98,15 +133,13 @@ class TextInputModal extends Modal {
|
||||||
this.close();
|
this.close();
|
||||||
});
|
});
|
||||||
container.appendChild(this.submitButton);
|
container.appendChild(this.submitButton);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onClose() {
|
|
||||||
this.titleInput.remove();
|
|
||||||
this.textarea.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default class QuickCaptureToNotePlugin extends Plugin {
|
export default class QuickCaptureToNotePlugin extends Plugin {
|
||||||
|
|
||||||
async onload() {
|
async onload() {
|
||||||
|
|
@ -122,18 +155,20 @@ export default class QuickCaptureToNotePlugin extends Plugin {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Open the Modal to provide title and content for the navigation or create new note
|
||||||
openCaptureModal() {
|
openCaptureModal() {
|
||||||
|
|
||||||
const modal = new TextInputModal(this.app, async (title, content) => {
|
const modal = new TextInputModal(this.app, async (title, content) => {
|
||||||
if (title && content) {
|
|
||||||
|
// We create a new note
|
||||||
|
// content === '' for blank note
|
||||||
|
if (title && (content || content === '')) {
|
||||||
await this.createNoteWithTitle(title, content);
|
await this.createNoteWithTitle(title, content);
|
||||||
}
|
}
|
||||||
// If only title is provided, open the existing note
|
|
||||||
if (title && !content) {
|
// We navigate
|
||||||
const existingNote = this.app.vault.getAbstractFileByPath(`${title}.md`);
|
if (title && content === null){
|
||||||
if (existingNote) {
|
this.navigateToSelectedNote(title)
|
||||||
this.app.workspace.activeLeaf.openFile(existingNote);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
@ -142,19 +177,39 @@ export default class QuickCaptureToNotePlugin extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
async createNoteWithTitle(title, content) {
|
async createNoteWithTitle(title: string , content: string) {
|
||||||
try {
|
try {
|
||||||
const noteExists = this.app.vault.getAbstractFileByPath(`${title}.md`);
|
let note = this.app.vault.getAbstractFileByPath(`${title}.md`);
|
||||||
if (!noteExists) {
|
if (!note) {
|
||||||
|
|
||||||
|
// Create new note
|
||||||
await this.app.vault.create(`${title}.md`, content);
|
await this.app.vault.create(`${title}.md`, content);
|
||||||
|
|
||||||
|
// Navigate to note after creation
|
||||||
|
this.navigateToSelectedNote(title)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.error('Note with the same title already exists');
|
console.error('Note with the same title already exists');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error while creating a new note:', error);
|
console.error('Error while creating a new note:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async navigateToSelectedNote(title : string) {
|
||||||
|
if (title) {
|
||||||
|
|
||||||
|
const existingNote = this.app.metadataCache.getFirstLinkpathDest(title, '')
|
||||||
|
if (existingNote instanceof TFile) {
|
||||||
|
// Close the modal before navigating to the selected note
|
||||||
|
const newLeaf = this.app.workspace.getLeaf(false)
|
||||||
|
await newLeaf.openFile(existingNote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// To append data to an existing note called Inbox
|
// To append data to an existing note called Inbox
|
||||||
// openCaptureModal() {
|
// openCaptureModal() {
|
||||||
// const targetNoteTitle = 'Inbox'; // You can change this to any note title you prefer
|
// const targetNoteTitle = 'Inbox'; // You can change this to any note title you prefer
|
||||||
|
|
@ -168,18 +223,24 @@ export default class QuickCaptureToNotePlugin extends Plugin {
|
||||||
// modal.open();
|
// modal.open();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
async appendTextToNote(note, text) {
|
// async appendTextToNote(note : TFile , text : string) {
|
||||||
if (note) {
|
// if (note) {
|
||||||
const currentContent = await this.app.vault.read(note);
|
// const currentContent = await this.app.vault.read(note);
|
||||||
const newContent = currentContent + '\n' + text;
|
// const newContent = currentContent + '\n' + text;
|
||||||
await this.app.vault.modify(note, newContent);
|
// await this.app.vault.modify(note, newContent);
|
||||||
|
|
||||||
// Open the note and set the cursor position to the end of the note
|
// // Open the note and set the cursor position to the end of the note
|
||||||
const leaf = this.app.workspace.activeLeaf;
|
// const leaf = this.app.workspace.activeLeaf;
|
||||||
const editor = await leaf.openFile(note, { state: { mode: 'source' } });
|
// const editor = await leaf!.openFile(note, { state: { mode: 'source' } });
|
||||||
editor.setCursor(editor.lineCount(), 0);
|
// editor.setCursor(editor.lineCount(), 0);
|
||||||
} else {
|
// } else {
|
||||||
console.error('Target note not found');
|
// console.error('Target note not found');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Function to upload file to s3 bucket
|
||||||
|
//function
|
||||||
43
package-lock.json
generated
43
package-lock.json
generated
|
|
@ -4,17 +4,16 @@
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
|
||||||
"typescript": "^5.0.4"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"obsidian": "^0.12.0"
|
"@types/codemirror": "^5.60.7",
|
||||||
|
"obsidian": "^0.12.0",
|
||||||
|
"typescript": "^5.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/codemirror": {
|
"node_modules/@types/codemirror": {
|
||||||
"version": "0.0.108",
|
"version": "5.60.7",
|
||||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz",
|
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.7.tgz",
|
||||||
"integrity": "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==",
|
"integrity": "sha512-QXIC+RPzt/1BGSuD6iFn6UMC9TDp+9hkOANYNPVsjjrDdzKphfRkwQDKGp2YaC54Yhz0g6P5uYTCCibZZEiMAA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/tern": "*"
|
"@types/tern": "*"
|
||||||
|
|
@ -54,10 +53,20 @@
|
||||||
"moment": "2.29.1"
|
"moment": "2.29.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/obsidian/node_modules/@types/codemirror": {
|
||||||
|
"version": "0.0.108",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz",
|
||||||
|
"integrity": "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/tern": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "5.0.4",
|
"version": "5.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
|
||||||
"integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==",
|
"integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==",
|
||||||
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
|
|
@ -69,9 +78,9 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/codemirror": {
|
"@types/codemirror": {
|
||||||
"version": "0.0.108",
|
"version": "5.60.7",
|
||||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz",
|
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.7.tgz",
|
||||||
"integrity": "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==",
|
"integrity": "sha512-QXIC+RPzt/1BGSuD6iFn6UMC9TDp+9hkOANYNPVsjjrDdzKphfRkwQDKGp2YaC54Yhz0g6P5uYTCCibZZEiMAA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/tern": "*"
|
"@types/tern": "*"
|
||||||
|
|
@ -106,12 +115,24 @@
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/codemirror": "0.0.108",
|
"@types/codemirror": "0.0.108",
|
||||||
"moment": "2.29.1"
|
"moment": "2.29.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/codemirror": {
|
||||||
|
"version": "0.0.108",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz",
|
||||||
|
"integrity": "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/tern": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "5.0.4",
|
"version": "5.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
|
||||||
"integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw=="
|
"integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==",
|
||||||
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"devDependencies": {
|
||||||
|
"@types/codemirror": "^5.60.7",
|
||||||
|
"obsidian": "^0.12.0",
|
||||||
"typescript": "^5.0.4"
|
"typescript": "^5.0.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"scripts": {
|
||||||
"obsidian": "^0.12.0"
|
"build": "tsc"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
styles.css
Normal file
21
styles.css
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-input {
|
||||||
|
font-size: 1.1em;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border: 1px solid var(--text-faint);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.textarea-custom {
|
||||||
|
font-size: 1em;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border: 1px solid var(--text-faint);
|
||||||
|
border-radius: 4px;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
@ -4,8 +4,10 @@
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"moduleResolution": "node"
|
"moduleResolution": "node",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strictPropertyInitialization": false
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"],
|
"include": ["src/**/*", "main.ts"],
|
||||||
"exclude": ["node_modules", "**/*.test.ts"]
|
"exclude": ["node_modules", "**/*.test.ts"]
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,13 @@
|
||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@types/codemirror@^5.60.7":
|
||||||
|
"integrity" "sha512-QXIC+RPzt/1BGSuD6iFn6UMC9TDp+9hkOANYNPVsjjrDdzKphfRkwQDKGp2YaC54Yhz0g6P5uYTCCibZZEiMAA=="
|
||||||
|
"resolved" "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.7.tgz"
|
||||||
|
"version" "5.60.7"
|
||||||
|
dependencies:
|
||||||
|
"@types/tern" "*"
|
||||||
|
|
||||||
"@types/codemirror@0.0.108":
|
"@types/codemirror@0.0.108":
|
||||||
"integrity" "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw=="
|
"integrity" "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw=="
|
||||||
"resolved" "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz"
|
"resolved" "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue