track local history

This commit is contained in:
fyears 2021-10-23 12:02:03 +08:00
parent 9ea3bdca7e
commit c75962aad5
4 changed files with 164 additions and 3 deletions

View File

@ -30,6 +30,7 @@
"@types/mime-types": "^2.1.1",
"aws-crt": "^1.10.1",
"codemirror": "^5.63.1",
"lovefield-ts": "^0.7.0",
"mime-types": "^2.1.33",
"obsidian": "^0.12.0",
"rimraf": "^3.0.2",

53
src/localdb.ts Normal file
View File

@ -0,0 +1,53 @@
import * as lf from "lovefield-ts/dist/es6/lf.js";
export type DatabaseConnection = lf.DatabaseConnection;
export const DEFAULT_DB_NAME = "saveremotedb";
export const DEFAULT_TBL_DELETE_HISTORY = "filefolderoperationhistory";
export interface FileFolderHistoryRecord {
key: string;
ctime: number;
mtime: number;
size: number;
action_when: number;
action_type: "delete" | "rename";
key_type: "folder" | "file";
rename_to: string;
}
export async function prepareDB() {
const schemaBuilder = lf.schema.create(DEFAULT_DB_NAME, 1);
schemaBuilder
.createTable(DEFAULT_TBL_DELETE_HISTORY)
.addColumn("id", lf.Type.INTEGER)
.addColumn("key", lf.Type.STRING)
.addColumn("ctime", lf.Type.INTEGER)
.addColumn("mtime", lf.Type.INTEGER)
.addColumn("size", lf.Type.INTEGER)
.addColumn("action_when", lf.Type.INTEGER)
.addColumn("action_type", lf.Type.STRING)
.addColumn("key_type", lf.Type.STRING)
.addPrimaryKey(["id"], true)
.addIndex("idxKey", ["key"]);
const db = await schemaBuilder.connect({
storeType: lf.DataStoreType.INDEXED_DB,
});
console.log("db connected");
return db;
}
export function destroyDB(db: lf.DatabaseConnection) {
db.close();
const req = indexedDB.deleteDatabase(DEFAULT_DB_NAME);
req.onsuccess = (event) => {
console.log("db deleted");
};
req.onblocked = (event) => {
console.warn("trying to delete db but it was blocked");
};
req.onerror = (event) => {
console.error("tried to delete db but something bad!");
console.error(event);
};
}

View File

@ -12,12 +12,21 @@ import {
Setting,
request,
Platform,
TFile,
TFolder,
} from "obsidian";
import * as CodeMirror from "codemirror";
import type { FileFolderHistoryRecord, DatabaseConnection } from "./localdb";
import {
prepareDB,
destroyDB,
DEFAULT_DB_NAME,
DEFAULT_TBL_DELETE_HISTORY,
} from "./localdb";
import {
S3Client,
ListObjectsCommand,
ListObjectsV2Command,
PutObjectCommand,
GetObjectCommand,
} from "@aws-sdk/client-s3";
@ -103,12 +112,96 @@ const getObjectBodyToArrayBuffer = async (
export default class SaveRemotePlugin extends Plugin {
settings: SaveRemotePluginSettings;
cm: CodeMirror.Editor;
db: DatabaseConnection;
async onload() {
console.log("loading plugin obsidian-save-remote");
await this.loadSettings();
await this.prepareDB();
this.registerEvent(
this.app.vault.on("delete", async (fileOrFolder) => {
const schema = this.db.getSchema().table(DEFAULT_TBL_DELETE_HISTORY);
const tbl = this.db.getSchema().table(DEFAULT_TBL_DELETE_HISTORY);
// console.log(fileOrFolder);
let k: FileFolderHistoryRecord;
if (fileOrFolder instanceof TFile) {
k = {
key: fileOrFolder.path,
ctime: fileOrFolder.stat.ctime,
mtime: fileOrFolder.stat.mtime,
size: fileOrFolder.stat.size,
action_when: Date.now(),
action_type: "delete",
key_type: "file",
rename_to: "",
};
} else if (fileOrFolder instanceof TFolder) {
k = {
key: fileOrFolder.path,
ctime: 0,
mtime: 0,
size: 0,
action_when: Date.now(),
action_type: "delete",
key_type: "folder",
rename_to: "",
};
}
const row = tbl.createRow(k);
await this.db.insertOrReplace().into(tbl).values([row]).exec();
})
);
this.registerEvent(
this.app.vault.on("rename", async (fileOrFolder, oldPath) => {
const schema = this.db.getSchema().table(DEFAULT_TBL_DELETE_HISTORY);
const tbl = this.db.getSchema().table(DEFAULT_TBL_DELETE_HISTORY);
// console.log(fileOrFolder);
let k: FileFolderHistoryRecord;
if (fileOrFolder instanceof TFile) {
k = {
key: oldPath,
ctime: fileOrFolder.stat.ctime,
mtime: fileOrFolder.stat.mtime,
size: fileOrFolder.stat.size,
action_when: Date.now(),
action_type: "rename",
key_type: "file",
rename_to: fileOrFolder.path,
};
} else if (fileOrFolder instanceof TFolder) {
k = {
key: oldPath,
ctime: 0,
mtime: 0,
size: 0,
action_when: Date.now(),
action_type: "rename",
key_type: "folder",
rename_to: fileOrFolder.path,
};
}
const row = tbl.createRow(k);
await this.db.insertOrReplace().into(tbl).values([row]).exec();
})
);
this.addRibbonIcon("dice", "Misc", async () => {
const a = this.app.vault.getAllLoadedFiles();
console.log(a);
const schema = this.db.getSchema().table(DEFAULT_TBL_DELETE_HISTORY);
const h = await this.db.select().from(schema).exec();
console.log(h);
// console.log(b)
});
this.addRibbonIcon("right-arrow-with-tail", "Upload", async () => {
// console.log(this.app.vault.getFiles());
// console.log(this.app.vault.getAllLoadedFiles());
@ -183,10 +276,15 @@ export default class SaveRemotePlugin extends Plugin {
try {
const listObj = await s3Client.send(
new ListObjectsCommand({ Bucket: this.settings.s3BucketName })
new ListObjectsV2Command({ Bucket: this.settings.s3BucketName })
);
for (const singleContent of listObj.Contents) {
const mtimeSec = Math.round(
singleContent.LastModified.valueOf() / 1000.0
);
console.log(`key ${singleContent.Key} mtime ${mtimeSec}`);
const foldersToBuild = getFolderLevels(singleContent.Key);
for (const folder of foldersToBuild) {
const r = await this.app.vault.adapter.exists(folder);
@ -246,6 +344,7 @@ export default class SaveRemotePlugin extends Plugin {
onunload() {
console.log("unloading plugin obsidian-save-remote");
this.destroyDB();
}
async loadSettings() {
@ -255,6 +354,14 @@ export default class SaveRemotePlugin extends Plugin {
async saveSettings() {
await this.saveData(this.settings);
}
async prepareDB() {
this.db = await prepareDB();
}
destroyDB() {
destroyDB(this.db);
}
}
class SaveRemoteSettingTab extends PluginSettingTab {

View File

@ -2,7 +2,7 @@ const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
entry: "./main.ts",
entry: "./src/main.ts",
target: "web",
output: {
filename: "main.js",