finished the plugin for now!

This commit is contained in:
Ell 2022-03-20 00:20:09 +01:00
parent ee5f13570d
commit a49de1de52
8 changed files with 1281 additions and 2330 deletions

View file

@ -1,2 +0,0 @@
npm node_modules
build

View file

@ -1,23 +0,0 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"env": { "node": true },
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"parserOptions": {
"sourceType": "module"
},
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
"@typescript-eslint/ban-ts-comment": "off",
"no-prototype-builtins": "off",
"@typescript-eslint/no-empty-function": "off"
}
}

View file

@ -1,2 +1,6 @@
# ObsidianKeep
An Obsidian plugin that integrates simply with Google Keep
An Obsidian plugin that displays Google Keep in the app.
Since Google Keep doesn't allow the use of iframes, this plugin gets creative by adding a [BrowserView](https://www.electronjs.org/docs/latest/api/browser-view) for the Google Keep view. However, since they render on top of everything else, the view has to be hidden whenever a modal or menu is open. It's a compromise.
When the official [Google Keep API](https://developers.google.com/keep) is farther along and has an official JavaScript API, this plugin will start using that instead, probably.

236
main.ts
View file

@ -1,137 +1,125 @@
import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian';
import { ItemView, Plugin } from 'obsidian';
import { BrowserView, BrowserWindow, remote } from 'electron';
// Remember to rename these classes and interfaces!
interface MyPluginSettings {
mySetting: string;
}
const DEFAULT_SETTINGS: MyPluginSettings = {
mySetting: 'default'
}
const viewName: string = "keep";
const padding: number = 5;
export default class MyPlugin extends Plugin {
settings: MyPluginSettings;
async onload() {
await this.loadSettings();
async onload(): Promise<void> {
console.log('Loading obsidian-keep');
// This creates an icon in the left ribbon.
const ribbonIconEl = this.addRibbonIcon('dice', 'Sample Plugin', (evt: MouseEvent) => {
// Called when the user clicks the icon.
new Notice('This is a notice!');
});
// Perform additional things with the ribbon
ribbonIconEl.addClass('my-plugin-ribbon-class');
// This adds a status bar item to the bottom of the app. Does not work on mobile apps.
const statusBarItemEl = this.addStatusBarItem();
statusBarItemEl.setText('Status Bar Text');
// This adds a simple command that can be triggered anywhere
this.registerView(viewName, l => new KeepView(l));
this.addCommand({
id: 'open-sample-modal-simple',
name: 'Open sample modal (simple)',
callback: () => {
new SampleModal(this.app).open();
}
});
// This adds an editor command that can perform some operation on the current editor instance
this.addCommand({
id: 'sample-editor-command',
name: 'Sample editor command',
editorCallback: (editor: Editor, view: MarkdownView) => {
console.log(editor.getSelection());
editor.replaceSelection('Sample Editor Command');
}
});
// This adds a complex command that can check whether the current state of the app allows execution of the command
this.addCommand({
id: 'open-sample-modal-complex',
name: 'Open sample modal (complex)',
id: "open-keep",
name: "Open Keep",
checkCallback: (checking: boolean) => {
// Conditions to check
const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView);
if (markdownView) {
// If checking is true, we're simply "checking" if the command can be run.
// If checking is false, then we want to actually perform the operation.
if (!checking) {
new SampleModal(this.app).open();
if (checking)
return !this.app.workspace.getLeavesOfType(viewName).length;
this.openKeep();
},
});
this.app.workspace.onLayoutReady(() => this.openKeep());
}
// This command will only show up in Command Palette when the check function returns true
private openKeep(): void {
if (!this.app.workspace.getLeavesOfType(viewName).length)
this.app.workspace.getRightLeaf(false).setViewState({ type: viewName });
}
}
export class KeepView extends ItemView {
private keep: BrowserView;
private visible: boolean;
private open: boolean;
private size: DOMRect;
async onload(): Promise<void> {
this.keep = new remote.BrowserView();
await this.keep.webContents.loadURL('https://keep.google.com');
this.registerInterval(window.setInterval(() => this.update(), 16.67));
}
onunload(): void {
this.hide();
}
onResize(): void {
this.resizeIfNecessary();
}
getViewType(): string {
return viewName;
}
getDisplayText(): string {
return "Google Keep";
}
getIcon(): string {
return "documents";
}
update() {
if (this.open) {
let covered = this.coveredByElement();
if (this.visible && covered) {
this.hide();
} else if (!this.visible && !covered) {
this.show();
}
if (this.visible)
this.resizeIfNecessary();
}
}
hide() {
if (this.visible) {
remote.BrowserWindow.getFocusedWindow().removeBrowserView(this.keep);
this.visible = false;
}
}
show() {
if (!this.visible) {
remote.BrowserWindow.getFocusedWindow().addBrowserView(this.keep);
this.visible = true;
}
}
protected async onOpen(): Promise<void> {
this.show();
this.resizeIfNecessary();
this.open = true;
}
protected async onClose(): Promise<void> {
this.hide();
this.open = false;
}
private resizeIfNecessary(): void {
let rect = this.contentEl.getBoundingClientRect();
if (this.size && rect.x == this.size.x && rect.y == this.size.y && rect.width == this.size.width && rect.height == this.size.height)
return;
this.size = rect;
this.keep.setBounds({
x: Math.floor(rect.x) + padding,
y: Math.floor(rect.top) + padding,
width: Math.floor(rect.width) - 2 * padding,
height: Math.floor(rect.height) - 2 * padding
});
}
private coveredByElement(): boolean {
let nodes = document.body.querySelectorAll(".modal-bg, .menu");
for (let i = 0; i < nodes.length; i++) {
let rect = nodes[i].getBoundingClientRect();
if (rect.left < this.size.right && this.size.left < rect.right && rect.top < this.size.bottom && this.size.top < rect.bottom)
return true;
}
}
});
// This adds a settings tab so the user can configure various aspects of the plugin
this.addSettingTab(new SampleSettingTab(this.app, this));
// If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin)
// Using this function will automatically remove the event listener when this plugin is disabled.
this.registerDomEvent(document, 'click', (evt: MouseEvent) => {
console.log('click', evt);
});
// When registering intervals, this function will automatically clear the interval when the plugin is disabled.
this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000));
}
onunload() {
}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
}
}
class SampleModal extends Modal {
constructor(app: App) {
super(app);
}
onOpen() {
const { contentEl } = this;
contentEl.setText('Woah!');
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
}
class SampleSettingTab extends PluginSettingTab {
plugin: MyPlugin;
constructor(app: App, plugin: MyPlugin) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl('h2', { text: 'Settings for my awesome plugin.' });
new Setting(containerEl)
.setName('Setting #1')
.setDesc('It\'s a secret')
.addText(text => text
.setPlaceholder('Enter your secret')
.setValue(this.plugin.settings.mySetting)
.onChange(async (value) => {
console.log('Secret: ' + value);
this.plugin.settings.mySetting = value;
await this.plugin.saveSettings();
}));
return false;
}
}

View file

@ -3,7 +3,7 @@
"name": "Obsidian Keep",
"version": "1.0.0",
"minAppVersion": "0.13.33",
"description": "An Obsidian plugin that integrates simply with Google Keep",
"description": "An Obsidian plugin that displays Google Keep in the app",
"author": "Ellpeck",
"authorUrl": "https://ellpeck.de",
"isDesktopOnly": false

3406
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
{
"name": "obsidian-keep",
"version": "1.0.0",
"description": "An Obsidian plugin that integrates simply with Google Keep",
"description": "An Obsidian plugin that displays Google Keep in the app",
"main": "main.js",
"scripts": {
"dev": "node esbuild.config.mjs",
@ -9,13 +9,12 @@
"version": "node version-bump.mjs && git add manifest.json versions.json"
},
"keywords": [],
"author": "",
"author": "Ellpeck",
"license": "MIT",
"devDependencies": {
"@types/node": "^16.11.6",
"@typescript-eslint/eslint-plugin": "^5.2.0",
"@typescript-eslint/parser": "^5.2.0",
"builtin-modules": "^3.2.0",
"electron": "^13.6.2",
"esbuild": "0.13.12",
"obsidian": "latest",
"tslib": "2.3.1",

View file

@ -1 +0,0 @@