mirror of
https://github.com/tmfelwu/obsidian-inbox.git
synced 2026-07-22 07:40:30 +00:00
Compare commits
No commits in common. "master" and "0.1.0" have entirely different histories.
14 changed files with 114 additions and 8929 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -2,6 +2,8 @@
|
|||
# Edit at https://www.toptal.com/developers/gitignore?templates=obsidian,node
|
||||
|
||||
|
||||
main.js
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
|
|
|
|||
21
LICENSE.md
21
LICENSE.md
|
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 Sparsh Yadav
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
34
README.md
34
README.md
|
|
@ -1,33 +1,3 @@
|
|||
|
||||
Any feature request/ suggestion for improvement please open [here](https://github.com/tmfelwu/obsidian-inbox/issues).
|
||||
https://github.com/tmfelwu/obsidian-inbox/issues
|
||||
|
||||
# Demo
|
||||
|
||||
The shortcut key launches this modal.
|
||||
|
||||

|
||||
|
||||
# Usage logic
|
||||
|
||||
- [x] Use the shortcut key will trigger the plugin.
|
||||
- [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
|
||||
|
||||
**Set up a global hotkey using an external tool:**
|
||||
|
||||
**For Windows:**
|
||||
|
|
@ -76,7 +46,3 @@ On Ubuntu 22.04, you can set up a global hotkey to trigger the Obsidian plugin c
|
|||
8. Close the settings application.
|
||||
|
||||
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
|
||||
|
|
|
|||
BIN
demo.png
BIN
demo.png
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB |
|
|
@ -1,5 +0,0 @@
|
|||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/*.test.ts'],
|
||||
};
|
||||
257
main.js
257
main.js
|
|
@ -1,257 +0,0 @@
|
|||
"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 });
|
||||
var obsidian_1 = require("obsidian");
|
||||
var TextInputModal = /** @class */ (function (_super) {
|
||||
__extends(TextInputModal, _super);
|
||||
function TextInputModal(app, onSubmit) {
|
||||
var _this = _super.call(this, app) || this;
|
||||
_this.onSubmit = onSubmit;
|
||||
return _this;
|
||||
}
|
||||
TextInputModal.prototype.noteExists = function (title) {
|
||||
var existingNote = this.app.metadataCache.getFirstLinkpathDest(title, '');
|
||||
return existingNote ? true : false;
|
||||
};
|
||||
TextInputModal.prototype.onOpen = function () {
|
||||
var _this = this;
|
||||
// Create a container for better layout control
|
||||
var container = document.createElement('div');
|
||||
container.classList.add('quickly-plugin-container');
|
||||
this.contentEl.appendChild(container);
|
||||
// Add a title input field
|
||||
this.titleInput = document.createElement('input');
|
||||
this.titleInput.type = 'text';
|
||||
this.titleInput.placeholder = 'Enter note title';
|
||||
this.titleInput.classList.add('quickly-plugin-title-input');
|
||||
container.appendChild(this.titleInput);
|
||||
// Add a datalist for existing notes
|
||||
this.datalist = document.createElement('datalist');
|
||||
this.datalist.id = 'note-titles';
|
||||
container.appendChild(this.datalist);
|
||||
var noteTitles = this.app.vault.getMarkdownFiles().map(function (note) { return note.basename; });
|
||||
// Not used for now
|
||||
// const notePaths = this.app.vault.getMarkdownFiles().map((note) => note.path);
|
||||
// Function to update the datalist with matching note titles
|
||||
var updateDatalist = function (searchText) {
|
||||
// Clear the existing datalist
|
||||
_this.datalist.innerHTML = '';
|
||||
// Filter the noteTitles array based on the user's input
|
||||
var filteredTitles = noteTitles.filter(function (title) { return title.toLowerCase().includes(searchText.toLowerCase()); });
|
||||
// Add the top 10 matching items to the datalist
|
||||
var maxItems = 10;
|
||||
for (var i = 0; i < Math.min(maxItems, filteredTitles.length); i++) {
|
||||
var option = document.createElement('option');
|
||||
option.value = filteredTitles[i];
|
||||
_this.datalist.appendChild(option);
|
||||
}
|
||||
};
|
||||
// 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');
|
||||
// If Enter is pressed we want to navigate to existing note.
|
||||
this.titleInput.addEventListener('keydown', function (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) {
|
||||
var 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();
|
||||
}
|
||||
}
|
||||
});
|
||||
// Navigate to the selected note from the datalist
|
||||
this.titleInput.addEventListener('change', function (event) {
|
||||
event.preventDefault();
|
||||
if (_this.noteExists(event.target.value)) {
|
||||
var selectedTitle = event.target.value;
|
||||
_this.onSubmit(selectedTitle, null);
|
||||
_this.close();
|
||||
}
|
||||
});
|
||||
// Add an input event listener on the titleInput to update the datalist based on the user's input
|
||||
this.titleInput.addEventListener('input', function (event) {
|
||||
var searchText = event.target.value;
|
||||
updateDatalist(searchText);
|
||||
});
|
||||
// Add a textarea for note content
|
||||
this.textarea = document.createElement('textarea');
|
||||
this.textarea.rows = 5;
|
||||
this.textarea.placeholder = 'Enter note content';
|
||||
this.textarea.classList.add('quickly-plugin-textarea-custom');
|
||||
this.textarea.addEventListener('keydown', function (event) {
|
||||
if (event.key === 'Enter' && event.ctrlKey) {
|
||||
_this.onSubmit(_this.titleInput.value, _this.textarea.value);
|
||||
_this.close();
|
||||
}
|
||||
else if (event.key === 'Escape') {
|
||||
_this.close();
|
||||
}
|
||||
});
|
||||
container.appendChild(this.textarea);
|
||||
// Add a submit button
|
||||
this.submitButton = document.createElement('button');
|
||||
this.submitButton.textContent = 'Submit';
|
||||
this.submitButton.classList.add('quickly-plugin-submit-button');
|
||||
this.submitButton.addEventListener('click', function () {
|
||||
_this.onSubmit(_this.titleInput.value, _this.textarea.value);
|
||||
_this.close();
|
||||
});
|
||||
container.appendChild(this.submitButton);
|
||||
};
|
||||
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 () {
|
||||
var _this = this;
|
||||
return __generator(this, function (_a) {
|
||||
this.addCommand({
|
||||
id: 'quick-capture-to-note',
|
||||
name: 'Quick Capture to Note',
|
||||
callback: function () { return _this.openCaptureModal(); },
|
||||
});
|
||||
// This is the global listeneer for obsidian url Eg. obsidian://quick-capture
|
||||
this.registerObsidianProtocolHandler('quick-capture', function () {
|
||||
_this.openCaptureModal();
|
||||
});
|
||||
return [2 /*return*/];
|
||||
});
|
||||
});
|
||||
};
|
||||
// Open the Modal to provide title and content for the navigation or create new note
|
||||
QuickCaptureToNotePlugin.prototype.openCaptureModal = function () {
|
||||
var _this = this;
|
||||
var modal = new TextInputModal(this.app, function (title, content) { return __awaiter(_this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
if (!(title && (content || content === ''))) return [3 /*break*/, 2];
|
||||
return [4 /*yield*/, this.createNoteWithTitle(title, content)];
|
||||
case 1:
|
||||
_a.sent();
|
||||
_a.label = 2;
|
||||
case 2:
|
||||
// We navigate
|
||||
if (title && content === null) {
|
||||
this.navigateToSelectedNote(title);
|
||||
}
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
modal.open();
|
||||
};
|
||||
//
|
||||
QuickCaptureToNotePlugin.prototype.createNoteWithTitle = function (title, content) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var note, noteRef, newLeaf, error_1;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
_a.trys.push([0, 5, , 6]);
|
||||
note = this.app.vault.getAbstractFileByPath("".concat(title, ".md"));
|
||||
if (!!note) return [3 /*break*/, 3];
|
||||
return [4 /*yield*/, this.app.vault.create("".concat(title, ".md"), content)];
|
||||
case 1:
|
||||
noteRef = _a.sent();
|
||||
newLeaf = this.app.workspace.getLeaf(false);
|
||||
return [4 /*yield*/, newLeaf.openFile(noteRef)];
|
||||
case 2:
|
||||
_a.sent();
|
||||
return [3 /*break*/, 4];
|
||||
case 3:
|
||||
console.error('Note with the same title already exists');
|
||||
_a.label = 4;
|
||||
case 4: return [3 /*break*/, 6];
|
||||
case 5:
|
||||
error_1 = _a.sent();
|
||||
console.error('Error while creating a new note:', error_1);
|
||||
return [3 /*break*/, 6];
|
||||
case 6: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
QuickCaptureToNotePlugin.prototype.navigateToSelectedNote = function (title) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var existingNote, newLeaf;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
if (!title) return [3 /*break*/, 2];
|
||||
existingNote = this.app.metadataCache.getFirstLinkpathDest(title, '');
|
||||
if (!(existingNote instanceof obsidian_1.TFile)) return [3 /*break*/, 2];
|
||||
newLeaf = this.app.workspace.getLeaf(false);
|
||||
return [4 /*yield*/, newLeaf.openFile(existingNote)];
|
||||
case 1:
|
||||
_a.sent();
|
||||
_a.label = 2;
|
||||
case 2: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
return QuickCaptureToNotePlugin;
|
||||
}(obsidian_1.Plugin));
|
||||
exports.default = QuickCaptureToNotePlugin;
|
||||
296
main.ts
296
main.ts
|
|
@ -1,242 +1,82 @@
|
|||
import { App, Plugin, Modal, TFile } from 'obsidian';
|
||||
|
||||
import { Plugin, Modal } from 'obsidian';
|
||||
|
||||
class TextInputModal extends Modal {
|
||||
private titleInput: HTMLInputElement;
|
||||
private textarea: HTMLTextAreaElement;
|
||||
private datalist: HTMLDataListElement;
|
||||
private submitButton: HTMLButtonElement;
|
||||
|
||||
constructor(app :App, private onSubmit: (title: string, value: string) => void) {
|
||||
super(app);
|
||||
}
|
||||
|
||||
noteExists(title: string){
|
||||
const existingNote = this.app.metadataCache.getFirstLinkpathDest(title, '')
|
||||
return existingNote ? true : false
|
||||
}
|
||||
|
||||
|
||||
|
||||
onOpen() {
|
||||
// Create a container for better layout control
|
||||
const container = document.createElement('div');
|
||||
container.classList.add('quickly-plugin-container');
|
||||
this.contentEl.appendChild(container);
|
||||
|
||||
// Add a title input field
|
||||
this.titleInput = document.createElement('input');
|
||||
this.titleInput.type = 'text';
|
||||
this.titleInput.placeholder = 'Enter note title';
|
||||
this.titleInput.classList.add('quickly-plugin-title-input');
|
||||
container.appendChild(this.titleInput);
|
||||
|
||||
|
||||
// Add a datalist for existing notes
|
||||
this.datalist = document.createElement('datalist');
|
||||
this.datalist.id = 'note-titles';
|
||||
container.appendChild(this.datalist);
|
||||
const noteTitles = this.app.vault.getMarkdownFiles().map((note) => note.basename);
|
||||
|
||||
// Not used for now
|
||||
// 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
|
||||
// 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');
|
||||
|
||||
|
||||
|
||||
// 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()
|
||||
private textarea: HTMLTextAreaElement;
|
||||
|
||||
constructor(app, private onSubmit: (value: string) => void) {
|
||||
super(app);
|
||||
}
|
||||
|
||||
onOpen() {
|
||||
this.textarea = document.createElement('textarea');
|
||||
this.textarea.rows = 5;
|
||||
this.textarea.placeholder = 'Enter to capture';
|
||||
this.textarea.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Enter' && event.ctrlKey) {
|
||||
this.onSubmit(this.textarea.value);
|
||||
this.close();
|
||||
} else if (event.key === 'Escape') {
|
||||
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()
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// Navigate to the selected note from the datalist
|
||||
this.titleInput.addEventListener('change', (event) => {
|
||||
event.preventDefault();
|
||||
if (this.noteExists(event.target.value)){
|
||||
const selectedTitle = event.target.value;
|
||||
this.onSubmit(selectedTitle, null)
|
||||
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
|
||||
this.textarea = document.createElement('textarea');
|
||||
this.textarea.rows = 5;
|
||||
this.textarea.placeholder = 'Enter note content';
|
||||
this.textarea.classList.add('quickly-plugin-textarea-custom');
|
||||
this.textarea.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Enter' && event.ctrlKey) {
|
||||
this.onSubmit(this.titleInput.value, this.textarea.value);
|
||||
this.close();
|
||||
} else if (event.key === 'Escape') {
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
container.appendChild(this.textarea);
|
||||
|
||||
// Add a submit button
|
||||
this.submitButton = document.createElement('button');
|
||||
this.submitButton.textContent = 'Submit';
|
||||
this.submitButton.classList.add('quickly-plugin-submit-button');
|
||||
this.submitButton.addEventListener('click', () => {
|
||||
this.onSubmit(this.titleInput.value, this.textarea.value);
|
||||
this.close();
|
||||
});
|
||||
container.appendChild(this.submitButton);
|
||||
});
|
||||
this.contentEl.appendChild(this.textarea);
|
||||
}
|
||||
|
||||
onClose() {
|
||||
this.textarea.remove();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export default class QuickCaptureToNotePlugin extends Plugin {
|
||||
|
||||
async onload() {
|
||||
this.addCommand({
|
||||
id: 'quick-capture-to-note',
|
||||
name: 'Quick Capture to Note',
|
||||
callback: () => this.openCaptureModal(),
|
||||
});
|
||||
|
||||
// This is the global listeneer for obsidian url Eg. obsidian://quick-capture
|
||||
this.registerObsidianProtocolHandler('quick-capture', () => {
|
||||
this.openCaptureModal();
|
||||
});
|
||||
}
|
||||
|
||||
// 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);
|
||||
async onload() {
|
||||
this.addCommand({
|
||||
id: 'quick-capture-to-note',
|
||||
name: 'Quick Capture to Note',
|
||||
callback: () => this.openCaptureModal(),
|
||||
});
|
||||
|
||||
this.registerObsidianProtocolHandler('quick-capture', () => {
|
||||
this.openCaptureModal();
|
||||
});
|
||||
} async onload() {
|
||||
this.addCommand({
|
||||
id: 'quick-capture-to-note',
|
||||
name: 'Quick Capture to Note',
|
||||
callback: () => this.openCaptureModal(),
|
||||
});
|
||||
|
||||
this.registerObsidianProtocolHandler('quick-capture', () => {
|
||||
this.openCaptureModal();
|
||||
});
|
||||
}
|
||||
|
||||
// We navigate
|
||||
if (title && content === null){
|
||||
this.navigateToSelectedNote(title)
|
||||
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();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
modal.open();
|
||||
}
|
||||
|
||||
//
|
||||
async createNoteWithTitle(title: string , content: string) {
|
||||
try {
|
||||
let note = this.app.vault.getAbstractFileByPath(`${title}.md`);
|
||||
if (!note) {
|
||||
|
||||
// Create new note
|
||||
let noteRef = await this.app.vault.create(`${title}.md`, content);
|
||||
|
||||
// Close the modal before navigating to the selected note
|
||||
let newLeaf = this.app.workspace.getLeaf(false)
|
||||
await newLeaf.openFile(noteRef);
|
||||
|
||||
// Navigate to note after creation
|
||||
// this.navigateToSelectedNote(title)
|
||||
|
||||
} else {
|
||||
console.error('Note with the same title already exists');
|
||||
}
|
||||
|
||||
} catch (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);
|
||||
}
|
||||
async appendTextToNote(note, text) {
|
||||
if (note) {
|
||||
const currentContent = await this.app.vault.read(note);
|
||||
const newContent = currentContent + '\n' + text;
|
||||
await this.app.vault.modify(note, newContent);
|
||||
|
||||
// Open the note and set the cursor position to the end of the note
|
||||
const leaf = this.app.workspace.activeLeaf;
|
||||
const editor = await leaf.openFile(note, { state: { mode: 'source' } });
|
||||
editor.setCursor(editor.lineCount(), 0);
|
||||
} else {
|
||||
console.error('Target note not found');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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();
|
||||
// }
|
||||
|
||||
// async appendTextToNote(note : TFile , text : string) {
|
||||
// if (note) {
|
||||
// const currentContent = await this.app.vault.read(note);
|
||||
// const newContent = currentContent + '\n' + text;
|
||||
// await this.app.vault.modify(note, newContent);
|
||||
|
||||
// // Open the note and set the cursor position to the end of the note
|
||||
// const leaf = this.app.workspace.activeLeaf;
|
||||
// const editor = await leaf!.openFile(note, { state: { mode: 'source' } });
|
||||
// editor.setCursor(editor.lineCount(), 0);
|
||||
// } else {
|
||||
// console.error('Target note not found');
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"id": "quickly",
|
||||
"name": "Quickly",
|
||||
"version": "0.1.3",
|
||||
"author": "Sparsh Yadav",
|
||||
"description": "Quickly empowers you to add your thoughts into obsidian with a shortcut key.",
|
||||
"minAppVersion": "0.12.0"
|
||||
}
|
||||
"id": "obsidian-inbox",
|
||||
"name": "Obsidian Inbox",
|
||||
"version": "0.1.0",
|
||||
"author": "Sparsh",
|
||||
"description": "Quickly capture text and append it to the end of a note.",
|
||||
"minAppVersion": "0.12.0"
|
||||
}
|
||||
6158
package-lock.json
generated
6158
package-lock.json
generated
File diff suppressed because it is too large
Load diff
10
package.json
10
package.json
|
|
@ -1,12 +1,8 @@
|
|||
{
|
||||
"devDependencies": {
|
||||
"@types/codemirror": "^5.60.7",
|
||||
"@types/jest": "^29.5.1",
|
||||
"jest": "^29.5.0",
|
||||
"obsidian": "^0.12.0",
|
||||
"dependencies": {
|
||||
"typescript": "^5.0.4"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
"devDependencies": {
|
||||
"obsidian": "^0.12.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
32
styles.css
32
styles.css
|
|
@ -1,32 +0,0 @@
|
|||
.quickly-plugin-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.quickly-plugin-title-input {
|
||||
font-size: 1.1em;
|
||||
padding: 0.5rem;
|
||||
border: 1px solid var(--text-faint);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.quickly-plugin-textarea-custom {
|
||||
font-size: 1em;
|
||||
padding: 0.5rem;
|
||||
border: 1px solid var(--text-faint);
|
||||
border-radius: 4px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
|
||||
.quickly-plugin-submit-button {
|
||||
font-size: 1em;
|
||||
padding: 0.5rem;
|
||||
margin-top: 1rem;
|
||||
border: 1px solid var(--text-faint);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
background-color: var(--background-modifier-hover);
|
||||
}
|
||||
|
|
@ -1,13 +1,10 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node",
|
||||
"skipLibCheck": true,
|
||||
"strictPropertyInitialization": false
|
||||
},
|
||||
"include": ["src/**/*", "main.ts"],
|
||||
"exclude": ["node_modules", "**/*.test.ts"]
|
||||
}
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"module": "commonjs",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["*.ts"]
|
||||
}
|
||||
Loading…
Reference in a new issue