import { App, Modal, Notice, Plugin, PluginSettingTab, Setting, request, Platform, TFile, TFolder, } from "obsidian"; import * as CodeMirror from "codemirror"; import type { DatabaseConnection } from "./localdb"; import { prepareDBs, destroyDBs, loadDeleteRenameHistoryTable, insertDeleteRecord, insertRenameRecord, getAllDeleteRenameRecords, } from "./localdb"; import type { SyncStatusType } from "./sync"; import { ensembleMixedStates, getOperation, doActualSync } from "./sync"; import { DEFAULT_S3_CONFIG, getS3Client, listFromRemote, S3Config } from "./s3"; interface SaveRemotePluginSettings { s3?: S3Config; } const DEFAULT_SETTINGS: SaveRemotePluginSettings = { s3: DEFAULT_S3_CONFIG, }; export default class SaveRemotePlugin extends Plugin { settings: SaveRemotePluginSettings; cm: CodeMirror.Editor; db: DatabaseConnection; syncStatus: SyncStatusType; async onload() { console.log("loading plugin obsidian-save-remote"); await this.loadSettings(); await this.prepareDB(); this.syncStatus = "idle"; this.registerEvent( this.app.vault.on("delete", async (fileOrFolder) => { await insertDeleteRecord(this.db, fileOrFolder); }) ); this.registerEvent( this.app.vault.on("rename", async (fileOrFolder, oldPath) => { await insertRenameRecord(this.db, fileOrFolder, oldPath); }) ); // this.addRibbonIcon("dice", "Misc", async () => { // const a = this.app.vault.getAllLoadedFiles(); // console.log(a); // const h = await getAllRecords(this.db); // console.log(h); // }); this.addRibbonIcon("switch", "Save Remote", async () => { if (this.syncStatus !== "idle") { new Notice("Save Remote already running!"); return; } new Notice("Save Remote Sync Preparing"); this.syncStatus = "preparing"; const s3Client = getS3Client(this.settings.s3); const remoteRsp = await listFromRemote(s3Client, this.settings.s3); const local = this.app.vault.getAllLoadedFiles(); const localHistory = await loadDeleteRenameHistoryTable(this.db); // console.log(remoteRsp); // console.log(local); // console.log(localHistory); const mixedStates = await ensembleMixedStates( remoteRsp.Contents, local, localHistory, this.db ); for (const [key, val] of Object.entries(mixedStates)) { getOperation(val, true); } console.log(mixedStates); // The operations above are read only and kind of safe. // The operations below begins to write or delete (!!!) something. new Notice("Save Remote Sync data exchanging!"); await doActualSync( s3Client, this.settings.s3, this.db, this.app.vault, mixedStates ); new Notice("Save Remote finish!"); this.syncStatus = "idle"; }); this.addSettingTab(new SaveRemoteSettingTab(this.app, this)); this.registerCodeMirror((cm: CodeMirror.Editor) => { this.cm = cm; console.log("codemirror registered."); }); // this.registerDomEvent(document, "click", (evt: MouseEvent) => { // console.log("click", evt); // }); // this.registerInterval( // window.setInterval(() => console.log("setInterval"), 5 * 60 * 1000) // ); } onunload() { console.log("unloading plugin obsidian-save-remote"); this.destroyDBs(); } async loadSettings() { this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); } async saveSettings() { await this.saveData(this.settings); } async prepareDB() { this.db = await prepareDBs(); } destroyDBs() { destroyDBs(this.db); } } class SaveRemoteSettingTab extends PluginSettingTab { plugin: SaveRemotePlugin; constructor(app: App, plugin: SaveRemotePlugin) { super(app, plugin); this.plugin = plugin; } display(): void { let { containerEl } = this; containerEl.empty(); containerEl.createEl("h2", { text: "Settings for Save Remote" }); new Setting(containerEl) .setName("s3Endpoint") .setDesc("s3Endpoint") .addText((text) => text .setPlaceholder("") .setValue(this.plugin.settings.s3.s3Endpoint) .onChange(async (value) => { this.plugin.settings.s3.s3Endpoint = value; await this.plugin.saveSettings(); }) ); new Setting(containerEl) .setName("s3Region") .setDesc("s3Region") .addText((text) => text .setPlaceholder("") .setValue(`${this.plugin.settings.s3.s3Region}`) .onChange(async (value) => { this.plugin.settings.s3.s3Region = value; await this.plugin.saveSettings(); }) ); new Setting(containerEl) .setName("s3AccessKeyID") .setDesc("s3AccessKeyID") .addText((text) => text .setPlaceholder("") .setValue(`${this.plugin.settings.s3.s3AccessKeyID}`) .onChange(async (value) => { this.plugin.settings.s3.s3AccessKeyID = value; await this.plugin.saveSettings(); }) ); new Setting(containerEl) .setName("s3SecretAccessKey") .setDesc("s3SecretAccessKey") .addText((text) => text .setPlaceholder("") .setValue(`${this.plugin.settings.s3.s3SecretAccessKey}`) .onChange(async (value) => { this.plugin.settings.s3.s3SecretAccessKey = value; await this.plugin.saveSettings(); }) ); new Setting(containerEl) .setName("s3BucketName") .setDesc("s3BucketName") .addText((text) => text .setPlaceholder("") .setValue(`${this.plugin.settings.s3.s3BucketName}`) .onChange(async (value) => { this.plugin.settings.s3.s3BucketName = value; await this.plugin.saveSettings(); }) ); } }