Fix 3 issues, implement a feature, and tidy up .

Fixed:
- note splitting bug
- missing some logging
- leaking important things to log. #11
New feature:
- No not delete empty folder
Tidy Up:
- Setting dialog.
- URI and Database are splited.
- Controlled options that should not be selected at the same time
- Drop history improved
This commit is contained in:
vorotamoroz
2021-11-15 12:25:18 +09:00
parent 8adab63724
commit bf4ce560ea
3 changed files with 301 additions and 178 deletions

303
main.ts
View File

@@ -28,6 +28,7 @@ interface ObsidianLiveSyncSettings {
couchDB_URI: string; couchDB_URI: string;
couchDB_USER: string; couchDB_USER: string;
couchDB_PASSWORD: string; couchDB_PASSWORD: string;
couchDB_DBNAME: string;
liveSync: boolean; liveSync: boolean;
syncOnSave: boolean; syncOnSave: boolean;
syncOnStart: boolean; syncOnStart: boolean;
@@ -47,12 +48,14 @@ interface ObsidianLiveSyncSettings {
passphrase: string; passphrase: string;
workingEncrypt: boolean; workingEncrypt: boolean;
workingPassphrase: string; workingPassphrase: string;
doNotDeleteFolder: boolean;
} }
const DEFAULT_SETTINGS: ObsidianLiveSyncSettings = { const DEFAULT_SETTINGS: ObsidianLiveSyncSettings = {
couchDB_URI: "", couchDB_URI: "",
couchDB_USER: "", couchDB_USER: "",
couchDB_PASSWORD: "", couchDB_PASSWORD: "",
couchDB_DBNAME: "",
liveSync: false, liveSync: false,
syncOnSave: false, syncOnSave: false,
syncOnStart: false, syncOnStart: false,
@@ -72,6 +75,7 @@ const DEFAULT_SETTINGS: ObsidianLiveSyncSettings = {
passphrase: "", passphrase: "",
workingEncrypt: false, workingEncrypt: false,
workingPassphrase: "", workingPassphrase: "",
doNotDeleteFolder: false,
}; };
interface Entry { interface Entry {
_id: string; _id: string;
@@ -994,13 +998,15 @@ class LocalPouchDB {
if (n1 > longLineThreshold) { if (n1 > longLineThreshold) {
// long sentence is an established piece // long sentence is an established piece
cPieceSize = n1 + 1; cPieceSize = n1;
} else { } else {
// cPieceSize = Math.min.apply([n2, n3, n4].filter((e) => e > 1)); // cPieceSize = Math.min.apply([n2, n3, n4].filter((e) => e > 1));
// ^ heavy. // ^ heavy.
if (n1 > 0 && cPieceSize < n1) cPieceSize = n1;
if (n2 > 0 && cPieceSize < n2) cPieceSize = n2 + 1; if (n2 > 0 && cPieceSize < n2) cPieceSize = n2 + 1;
if (n3 > 0 && cPieceSize < n3) cPieceSize = n3 + 3; if (n3 > 0 && cPieceSize < n3) cPieceSize = n3 + 3;
if (n4 > 0 && cPieceSize < n4) cPieceSize = n4 + 0; // Choose shorter, empty line and \n#
if (n4 > 0 && cPieceSize > n4) cPieceSize = n4 + 0;
cPieceSize++; cPieceSize++;
} }
} while (cPieceSize < minimumChunkSize); } while (cPieceSize < minimumChunkSize);
@@ -1042,8 +1048,6 @@ class LocalPouchDB {
pieceData.data = await decrypt(pieceData.data, this.settings.passphrase); pieceData.data = await decrypt(pieceData.data, this.settings.passphrase);
} catch (e) { } catch (e) {
Logger("Decode failed !"); Logger("Decode failed !");
Logger(pieceData.data);
Logger(this.settings.passphrase);
throw e; throw e;
} }
} }
@@ -1181,7 +1185,7 @@ class LocalPouchDB {
} }
this.syncStatus = "CLOSED"; this.syncStatus = "CLOSED";
this.updateInfo(); this.updateInfo();
let uri = setting.couchDB_URI; let uri = setting.couchDB_URI + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
let auth: Credential = { let auth: Credential = {
username: setting.couchDB_USER, username: setting.couchDB_USER,
password: setting.couchDB_PASSWORD, password: setting.couchDB_PASSWORD,
@@ -1249,7 +1253,7 @@ class LocalPouchDB {
new Notice("Open settings and check message, please."); new Notice("Open settings and check message, please.");
return; return;
} }
let uri = setting.couchDB_URI; let uri = setting.couchDB_URI + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
let auth: Credential = { let auth: Credential = {
username: setting.couchDB_USER, username: setting.couchDB_USER,
password: setting.couchDB_PASSWORD, password: setting.couchDB_PASSWORD,
@@ -1435,7 +1439,7 @@ class LocalPouchDB {
} }
async tryResetRemoteDatabase(setting: ObsidianLiveSyncSettings) { async tryResetRemoteDatabase(setting: ObsidianLiveSyncSettings) {
await this.closeReplication(); await this.closeReplication();
let uri = setting.couchDB_URI; let uri = setting.couchDB_URI + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
let auth: Credential = { let auth: Credential = {
username: setting.couchDB_USER, username: setting.couchDB_USER,
password: setting.couchDB_PASSWORD, password: setting.couchDB_PASSWORD,
@@ -1452,7 +1456,7 @@ class LocalPouchDB {
} }
async tryCreateRemoteDatabase(setting: ObsidianLiveSyncSettings) { async tryCreateRemoteDatabase(setting: ObsidianLiveSyncSettings) {
await this.closeReplication(); await this.closeReplication();
let uri = setting.couchDB_URI; let uri = setting.couchDB_URI + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
let auth: Credential = { let auth: Credential = {
username: setting.couchDB_USER, username: setting.couchDB_USER,
password: setting.couchDB_PASSWORD, password: setting.couchDB_PASSWORD,
@@ -1462,7 +1466,7 @@ class LocalPouchDB {
Logger("Remote Database Created or Connected", LOG_LEVEL.NOTICE); Logger("Remote Database Created or Connected", LOG_LEVEL.NOTICE);
} }
async markRemoteLocked(setting: ObsidianLiveSyncSettings, locked: boolean) { async markRemoteLocked(setting: ObsidianLiveSyncSettings, locked: boolean) {
let uri = setting.couchDB_URI; let uri = setting.couchDB_URI + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
let auth: Credential = { let auth: Credential = {
username: setting.couchDB_USER, username: setting.couchDB_USER,
password: setting.couchDB_PASSWORD, password: setting.couchDB_PASSWORD,
@@ -1496,7 +1500,7 @@ class LocalPouchDB {
await dbret.db.put(remoteMilestone); await dbret.db.put(remoteMilestone);
} }
async markRemoteResolved(setting: ObsidianLiveSyncSettings) { async markRemoteResolved(setting: ObsidianLiveSyncSettings) {
let uri = setting.couchDB_URI; let uri = setting.couchDB_URI + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
let auth: Credential = { let auth: Credential = {
username: setting.couchDB_USER, username: setting.couchDB_USER,
password: setting.couchDB_PASSWORD, password: setting.couchDB_PASSWORD,
@@ -1677,6 +1681,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
this.registerWatchEvents(); this.registerWatchEvents();
} catch (ex) { } catch (ex) {
Logger("Error while loading Self-hosted LiveSync", LOG_LEVEL.NOTICE); Logger("Error while loading Self-hosted LiveSync", LOG_LEVEL.NOTICE);
Logger(ex, LOG_LEVEL.VERBOSE);
} }
}); });
this.addCommand({ this.addCommand({
@@ -1987,10 +1992,12 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
Logger(`deleted:${file.path}`); Logger(`deleted:${file.path}`);
Logger(`other items:${dir.children.length}`); Logger(`other items:${dir.children.length}`);
if (dir.children.length == 0) { if (dir.children.length == 0) {
if (!this.settings.doNotDeleteFolder) {
Logger(`all files deleted by replication, so delete dir`); Logger(`all files deleted by replication, so delete dir`);
await this.deleteVaultItem(dir); await this.deleteVaultItem(dir);
} }
} }
}
async doc2storate_modify(docEntry: EntryBody, file: TFile, force?: boolean) { async doc2storate_modify(docEntry: EntryBody, file: TFile, force?: boolean) {
if (docEntry._deleted) { if (docEntry._deleted) {
//basically pass. //basically pass.
@@ -2190,16 +2197,18 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
const count = objects.length; const count = objects.length;
Logger(procedurename); Logger(procedurename);
let i = 0; let i = 0;
let lastTicks = performance.now() + 2000;
let procs = objects.map(async (e) => { let procs = objects.map(async (e) => {
try { try {
// debugger; // debugger;
// Logger("hello?") // Logger("hello?")
await callback(e); await callback(e);
i++; i++;
if (i % 25 == 0) { if (lastTicks < performance.now()) {
const notify = `${procedurename} : ${i}/${count}`; const notify = `${procedurename} : ${i}/${count}`;
if (notice != null) notice.setMessage(notify); if (notice != null) notice.setMessage(notify);
Logger(notify); Logger(notify);
lastTicks = performance.now() + 2000;
// this.statusBar.setText(notify); // this.statusBar.setText(notify);
} }
} catch (ex) { } catch (ex) {
@@ -2207,8 +2216,24 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
Logger(ex); Logger(ex);
} }
}); });
if (!Promise.allSettled) {
await Promise.all(
procs.map((p) =>
p
.then((value) => ({
status: "fulfilled",
value,
}))
.catch((reason) => ({
status: "rejected",
reason,
}))
)
);
} else {
await Promise.allSettled(procs); await Promise.allSettled(procs);
} }
}
await runAll("UPDATE DATABASE", onlyInStorage, async (e) => { await runAll("UPDATE DATABASE", onlyInStorage, async (e) => {
Logger(`Update into ${e.path}`); Logger(`Update into ${e.path}`);
await this.updateIntoDB(e); await this.updateIntoDB(e);
@@ -2627,12 +2652,12 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
this.plugin = plugin; this.plugin = plugin;
} }
async testConnection(): Promise<void> { async testConnection(): Promise<void> {
let db = await connectRemoteCouchDB(this.plugin.settings.couchDB_URI, { let db = await connectRemoteCouchDB(this.plugin.settings.couchDB_URI + (this.plugin.settings.couchDB_DBNAME == "" ? "" : "/" + this.plugin.settings.couchDB_DBNAME), {
username: this.plugin.settings.couchDB_USER, username: this.plugin.settings.couchDB_USER,
password: this.plugin.settings.couchDB_PASSWORD, password: this.plugin.settings.couchDB_PASSWORD,
}); });
if (db === false) { if (db === false) {
this.plugin.addLog(`could not connect to ${this.plugin.settings.couchDB_URI}`, LOG_LEVEL.NOTICE); this.plugin.addLog(`could not connect to ${this.plugin.settings.couchDB_URI} : ${this.plugin.settings.couchDB_DBNAME}`, LOG_LEVEL.NOTICE);
return; return;
} }
this.plugin.addLog(`Connected to ${db.info.db_name}`, LOG_LEVEL.NOTICE); this.plugin.addLog(`Connected to ${db.info.db_name}`, LOG_LEVEL.NOTICE);
@@ -2644,7 +2669,52 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
containerEl.createEl("h2", { text: "Settings for Self-hosted LiveSync." }); containerEl.createEl("h2", { text: "Settings for Self-hosted LiveSync." });
new Setting(containerEl).setName("CouchDB Remote URI").addText((text) => containerEl.createEl("h3", { text: "Remote Database configuration" });
const isAnySyncEnabled = (): boolean => {
if (this.plugin.settings.liveSync) return true;
if (this.plugin.settings.periodicReplication) return true;
if (this.plugin.settings.syncOnFileOpen) return true;
if (this.plugin.settings.syncOnSave) return true;
if (this.plugin.settings.syncOnStart) return true;
};
const applyDisplayEnabled = () => {
if (isAnySyncEnabled()) {
dbsettings.forEach((e) => {
e.setDisabled(true).setTooltip("When any sync is enabled, It cound't be changed.");
});
} else {
dbsettings.forEach((e) => {
e.setDisabled(false).setTooltip("");
});
}
if (this.plugin.settings.liveSync) {
syncNonLive.forEach((e) => {
e.setDisabled(true).setTooltip("");
});
syncLive.forEach((e) => {
e.setDisabled(false).setTooltip("");
});
} else if (this.plugin.settings.syncOnFileOpen || this.plugin.settings.syncOnSave || this.plugin.settings.syncOnStart || this.plugin.settings.periodicReplication) {
syncNonLive.forEach((e) => {
e.setDisabled(false).setTooltip("");
});
syncLive.forEach((e) => {
e.setDisabled(true).setTooltip("");
});
} else {
syncNonLive.forEach((e) => {
e.setDisabled(false).setTooltip("");
});
syncLive.forEach((e) => {
e.setDisabled(false).setTooltip("");
});
}
};
let dbsettings: Setting[] = [];
dbsettings.push(
new Setting(containerEl).setName("URI").addText((text) =>
text text
.setPlaceholder("https://........") .setPlaceholder("https://........")
.setValue(this.plugin.settings.couchDB_URI) .setValue(this.plugin.settings.couchDB_URI)
@@ -2652,9 +2722,9 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
this.plugin.settings.couchDB_URI = value; this.plugin.settings.couchDB_URI = value;
await this.plugin.saveSettings(); await this.plugin.saveSettings();
}) })
); ),
new Setting(containerEl) new Setting(containerEl)
.setName("CouchDB Username") .setName("Username")
.setDesc("username") .setDesc("username")
.addText((text) => .addText((text) =>
text text
@@ -2664,9 +2734,9 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
this.plugin.settings.couchDB_USER = value; this.plugin.settings.couchDB_USER = value;
await this.plugin.saveSettings(); await this.plugin.saveSettings();
}) })
); ),
new Setting(containerEl) new Setting(containerEl)
.setName("CouchDB Password") .setName("Password")
.setDesc("password") .setDesc("password")
.addText((text) => { .addText((text) => {
text.setPlaceholder("") text.setPlaceholder("")
@@ -2676,7 +2746,18 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
await this.plugin.saveSettings(); await this.plugin.saveSettings();
}); });
text.inputEl.setAttribute("type", "password"); text.inputEl.setAttribute("type", "password");
}); }),
new Setting(containerEl).setName("Database name").addText((text) =>
text
.setPlaceholder("")
.setValue(this.plugin.settings.couchDB_DBNAME)
.onChange(async (value) => {
this.plugin.settings.couchDB_DBNAME = value;
await this.plugin.saveSettings();
})
)
);
new Setting(containerEl) new Setting(containerEl)
.setName("Test Database Connection") .setName("Test Database Connection")
.setDesc("Open database connection. If the remote database is not found and you have the privilege to create a database, the database will be created.") .setDesc("Open database connection. If the remote database is not found and you have the privilege to create a database, the database will be created.")
@@ -2689,27 +2770,27 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
}) })
); );
containerEl.createEl("h3", { text: "Database configuration" }); containerEl.createEl("h3", { text: "Local Database configuration" });
// new Setting(containerEl)
// .setName("File to Database saving delay")
// .setDesc("ms, between 200 and 5000, restart required.")
// .addText((text) => {
// text.setPlaceholder("")
// .setValue(this.plugin.settings.savingDelay + "")
// .onChange(async (value) => {
// let v = Number(value);
// if (isNaN(v) || v < 200 || v > 5000) {
// return 200;
// //text.inputEl.va;
// }
// this.plugin.settings.savingDelay = v;
// await this.plugin.saveSettings();
// });
// text.inputEl.setAttribute("type", "number");
// });
new Setting(containerEl) new Setting(containerEl)
.setName("File to Database saving delay") .setName("Auto Garbage Collection delay")
.setDesc("ms, between 200 and 5000, restart required.")
.addText((text) => {
text.setPlaceholder("")
.setValue(this.plugin.settings.savingDelay + "")
.onChange(async (value) => {
let v = Number(value);
if (isNaN(v) || v < 200 || v > 5000) {
return 200;
//text.inputEl.va;
}
this.plugin.settings.savingDelay = v;
await this.plugin.saveSettings();
});
text.inputEl.setAttribute("type", "number");
});
new Setting(containerEl)
.setName("Auto GC delay")
.setDesc("(seconds), if you set zero, you have to run manually.") .setDesc("(seconds), if you set zero, you have to run manually.")
.addText((text) => { .addText((text) => {
text.setPlaceholder("") text.setPlaceholder("")
@@ -2724,43 +2805,25 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
}); });
text.inputEl.setAttribute("type", "number"); text.inputEl.setAttribute("type", "number");
}); });
new Setting(containerEl).setName("Manual Garbage Collect").addButton((button) =>
containerEl.createEl("h3", { text: "Log Setting" }); button
.setButtonText("Collect now")
new Setting(containerEl) .setDisabled(false)
.setName("Do not show low-priority Log") .onClick(async () => {
.setDesc("Reduce log infomations") await this.plugin.garbageCollect();
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.lessInformationInLog).onChange(async (value) => {
this.plugin.settings.lessInformationInLog = value;
await this.plugin.saveSettings();
}) })
); );
new Setting(containerEl) new Setting(containerEl)
.setName("Verbose Log") .setName("End to End Encryption (beta)")
.setDesc("Show verbose log ")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.showVerboseLog).onChange(async (value) => {
this.plugin.settings.showVerboseLog = value;
await this.plugin.saveSettings();
})
);
containerEl.createEl("h3", { text: "End to End Encryption (beta)" });
containerEl.createEl("div", {
text: "When you change any encryption enabled or passphrase, you have to reset all databases to make sure that the last password is unused and erase encrypted data from anywhere. This operation will not lost your vault if you are fully synced.",
});
new Setting(containerEl)
.setName("Encrypt database")
.setDesc("Encrypting contents on the database.") .setDesc("Encrypting contents on the database.")
.addToggle((toggle) => .addToggle((toggle) =>
toggle.setValue(this.plugin.settings.workingEncrypt).onChange(async (value) => { toggle.setValue(this.plugin.settings.workingEncrypt).onChange(async (value) => {
this.plugin.settings.workingEncrypt = value; this.plugin.settings.workingEncrypt = value;
phasspharase.setDisabled(!value);
await this.plugin.saveSettings(); await this.plugin.saveSettings();
}) })
); );
new Setting(containerEl) let phasspharase = new Setting(containerEl)
.setName("Passphrase") .setName("Passphrase")
.setDesc("Encrypting passphrase") .setDesc("Encrypting passphrase")
.addText((text) => { .addText((text) => {
@@ -2772,7 +2835,10 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
}); });
text.inputEl.setAttribute("type", "password"); text.inputEl.setAttribute("type", "password");
}); });
phasspharase.setDisabled(!this.plugin.settings.workingEncrypt);
containerEl.createEl("div", {
text: "When you change any encryption enabled or passphrase, you have to reset all databases to make sure that the last password is unused and erase encrypted data from anywhere. This operation will not lost your vault if you are fully synced.",
});
const applyEncryption = async (sendToServer: boolean) => { const applyEncryption = async (sendToServer: boolean) => {
if (this.plugin.settings.workingEncrypt && this.plugin.settings.workingPassphrase == "") { if (this.plugin.settings.workingEncrypt && this.plugin.settings.workingPassphrase == "") {
Logger("If you enable encryption, you have to set the passphrase", LOG_LEVEL.NOTICE); Logger("If you enable encryption, you have to set the passphrase", LOG_LEVEL.NOTICE);
@@ -2827,6 +2893,27 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
}) })
); );
containerEl.createEl("h3", { text: "General Settings" });
new Setting(containerEl)
.setName("Do not show low-priority Log")
.setDesc("Reduce log infomations")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.lessInformationInLog).onChange(async (value) => {
this.plugin.settings.lessInformationInLog = value;
await this.plugin.saveSettings();
})
);
new Setting(containerEl)
.setName("Verbose Log")
.setDesc("Show verbose log ")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.showVerboseLog).onChange(async (value) => {
this.plugin.settings.showVerboseLog = value;
await this.plugin.saveSettings();
})
);
containerEl.createEl("h3", { text: "Sync setting" }); containerEl.createEl("h3", { text: "Sync setting" });
if (this.plugin.settings.versionUpFlash != "") { if (this.plugin.settings.versionUpFlash != "") {
@@ -2835,23 +2922,31 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
e.addEventListener("click", async () => { e.addEventListener("click", async () => {
this.plugin.settings.versionUpFlash = ""; this.plugin.settings.versionUpFlash = "";
await this.plugin.saveSettings(); await this.plugin.saveSettings();
applyDisplayEnabled();
c.remove(); c.remove();
}); });
}); });
c.addClass("op-warn"); c.addClass("op-warn");
} }
let syncLive: Setting[] = [];
let syncNonLive: Setting[] = [];
syncLive.push(
new Setting(containerEl) new Setting(containerEl)
.setName("LiveSync") .setName("LiveSync")
.setDesc("Sync realtime") .setDesc("Sync realtime")
.addToggle((toggle) => .addToggle((toggle) =>
toggle.setValue(this.plugin.settings.liveSync).onChange(async (value) => { toggle.setValue(this.plugin.settings.liveSync).onChange(async (value) => {
this.plugin.settings.liveSync = value; this.plugin.settings.liveSync = value;
// ps.setDisabled(value);
await this.plugin.saveSettings(); await this.plugin.saveSettings();
applyDisplayEnabled();
this.plugin.realizeSettingSyncMode(); this.plugin.realizeSettingSyncMode();
}) })
)
); );
syncNonLive.push(
new Setting(containerEl) new Setting(containerEl)
.setName("Periodic Sync") .setName("Periodic Sync")
.setDesc("Sync periodically") .setDesc("Sync periodically")
@@ -2859,8 +2954,9 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
toggle.setValue(this.plugin.settings.periodicReplication).onChange(async (value) => { toggle.setValue(this.plugin.settings.periodicReplication).onChange(async (value) => {
this.plugin.settings.periodicReplication = value; this.plugin.settings.periodicReplication = value;
await this.plugin.saveSettings(); await this.plugin.saveSettings();
applyDisplayEnabled();
}) })
); ),
new Setting(containerEl) new Setting(containerEl)
.setName("Periodic sync intreval") .setName("Periodic sync intreval")
.setDesc("Interval (sec)") .setDesc("Interval (sec)")
@@ -2874,9 +2970,10 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
} }
this.plugin.settings.periodicReplicationInterval = v; this.plugin.settings.periodicReplicationInterval = v;
await this.plugin.saveSettings(); await this.plugin.saveSettings();
applyDisplayEnabled();
}); });
text.inputEl.setAttribute("type", "number"); text.inputEl.setAttribute("type", "number");
}); }),
new Setting(containerEl) new Setting(containerEl)
.setName("Sync on Save") .setName("Sync on Save")
@@ -2885,8 +2982,9 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
toggle.setValue(this.plugin.settings.syncOnSave).onChange(async (value) => { toggle.setValue(this.plugin.settings.syncOnSave).onChange(async (value) => {
this.plugin.settings.syncOnSave = value; this.plugin.settings.syncOnSave = value;
await this.plugin.saveSettings(); await this.plugin.saveSettings();
applyDisplayEnabled();
}) })
); ),
new Setting(containerEl) new Setting(containerEl)
.setName("Sync on File Open") .setName("Sync on File Open")
.setDesc("When you open file, sync automatically") .setDesc("When you open file, sync automatically")
@@ -2894,8 +2992,9 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
toggle.setValue(this.plugin.settings.syncOnFileOpen).onChange(async (value) => { toggle.setValue(this.plugin.settings.syncOnFileOpen).onChange(async (value) => {
this.plugin.settings.syncOnFileOpen = value; this.plugin.settings.syncOnFileOpen = value;
await this.plugin.saveSettings(); await this.plugin.saveSettings();
applyDisplayEnabled();
}) })
); ),
new Setting(containerEl) new Setting(containerEl)
.setName("Sync on Start") .setName("Sync on Start")
.setDesc("Start synchronization on Obsidian started.") .setDesc("Start synchronization on Obsidian started.")
@@ -2903,11 +3002,13 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
toggle.setValue(this.plugin.settings.syncOnStart).onChange(async (value) => { toggle.setValue(this.plugin.settings.syncOnStart).onChange(async (value) => {
this.plugin.settings.syncOnStart = value; this.plugin.settings.syncOnStart = value;
await this.plugin.saveSettings(); await this.plugin.saveSettings();
applyDisplayEnabled();
}) })
)
); );
new Setting(containerEl) new Setting(containerEl)
.setName("Trash deleted files") .setName("Use Trash for deleted files")
.setDesc("Do not delete files that deleted in remote, just move to trash.") .setDesc("Do not delete files that deleted in remote, just move to trash.")
.addToggle((toggle) => .addToggle((toggle) =>
toggle.setValue(this.plugin.settings.trashInsteadDelete).onChange(async (value) => { toggle.setValue(this.plugin.settings.trashInsteadDelete).onChange(async (value) => {
@@ -2916,6 +3017,16 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
}) })
); );
new Setting(containerEl)
.setName("Do not delete empty folder")
.setDesc("Normally, folder is deleted When the folder became empty by replication. enable this, leave it as is")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.doNotDeleteFolder).onChange(async (value) => {
this.plugin.settings.doNotDeleteFolder = value;
await this.plugin.saveSettings();
})
);
new Setting(containerEl) new Setting(containerEl)
.setName("Minimum chunk size") .setName("Minimum chunk size")
.setDesc("(letters), minimum chunk size.") .setDesc("(letters), minimum chunk size.")
@@ -2950,15 +3061,6 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
text.inputEl.setAttribute("type", "number"); text.inputEl.setAttribute("type", "number");
}); });
new Setting(containerEl).setName("Garbage Collect").addButton((button) =>
button
.setButtonText("Garbage Collection")
.setDisabled(false)
.onClick(async () => {
await this.plugin.garbageCollect();
})
);
containerEl.createEl("h3", { text: "Hatch" }); containerEl.createEl("h3", { text: "Hatch" });
if (this.plugin.localDatabase.remoteLockedAndDeviceNotAccepted) { if (this.plugin.localDatabase.remoteLockedAndDeviceNotAccepted) {
@@ -2986,28 +3088,48 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
c.addClass("op-warn"); c.addClass("op-warn");
} }
} }
const dropHistory = async (sendToServer: boolean) => {
new Setting(containerEl)
.setName("Drop History")
.setDesc("Initialize local and remote database, and create local database from storage and put all into server. And also, lock the database to prevent data corruption.")
.addButton((button) =>
button
.setButtonText("Execute")
.setWarning()
.setDisabled(false)
.onClick(async () => {
this.plugin.settings.liveSync = false; this.plugin.settings.liveSync = false;
this.plugin.settings.periodicReplication = false; this.plugin.settings.periodicReplication = false;
this.plugin.settings.syncOnSave = false; this.plugin.settings.syncOnSave = false;
this.plugin.settings.syncOnStart = false; this.plugin.settings.syncOnStart = false;
await this.plugin.saveSettings(); await this.plugin.saveSettings();
applyDisplayEnabled();
await this.plugin.resetLocalDatabase(); await this.plugin.resetLocalDatabase();
if (sendToServer) {
await this.plugin.initializeDatabase(true); await this.plugin.initializeDatabase(true);
await this.plugin.markRemoteLocked();
await this.plugin.tryResetRemoteDatabase(); await this.plugin.tryResetRemoteDatabase();
await this.plugin.markRemoteLocked(); await this.plugin.markRemoteLocked();
await this.plugin.replicateAllToServer(true); await this.plugin.replicateAllToServer(true);
} else {
await this.plugin.markRemoteResolved();
await this.plugin.replicate(true);
}
};
new Setting(containerEl)
.setName("Drop History")
.setDesc("Initialize local and remote database, and send all or retrieve all again.")
.addButton((button) =>
button
.setButtonText("Drop and send")
.setWarning()
.setDisabled(false)
.onClick(async () => {
await dropHistory(true);
})
)
.addButton((button) =>
button
.setButtonText("Drop and receive")
.setWarning()
.setDisabled(false)
.onClick(async () => {
await dropHistory(false);
}) })
); );
new Setting(containerEl) new Setting(containerEl)
.setName("Lock remote database") .setName("Lock remote database")
.setDesc("Lock remote database for synchronize") .setDesc("Lock remote database for synchronize")
@@ -3082,5 +3204,6 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
} else { } else {
let cx = containerEl.createEl("div", { text: "There's no collupted data." }); let cx = containerEl.createEl("div", { text: "There's no collupted data." });
} }
applyDisplayEnabled();
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"id": "obsidian-livesync", "id": "obsidian-livesync",
"name": "Self-hosted LiveSync", "name": "Self-hosted LiveSync",
"version": "0.1.15", "version": "0.1.16",
"minAppVersion": "0.9.12", "minAppVersion": "0.9.12",
"description": "Community implementation of self-hosted livesync. Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.", "description": "Community implementation of self-hosted livesync. Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
"author": "vorotamoroz", "author": "vorotamoroz",

View File

@@ -1,6 +1,6 @@
{ {
"name": "obsidian-livesync", "name": "obsidian-livesync",
"version": "0.1.15", "version": "0.1.16",
"description": "Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.", "description": "Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {