mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2025-12-13 17:55:56 +00:00
Implemented
- Configuration wizard. Fixed - Remove outdated configuration items.
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
import { App, PluginSettingTab, Setting, sanitizeHTMLToDom, RequestUrlParam, requestUrl, TextAreaComponent, MarkdownRenderer } from "obsidian";
|
import { App, PluginSettingTab, Setting, sanitizeHTMLToDom, RequestUrlParam, requestUrl, TextAreaComponent, MarkdownRenderer } from "obsidian";
|
||||||
import { EntryDoc, LOG_LEVEL, RemoteDBSettings } from "./lib/src/types";
|
import { DEFAULT_SETTINGS, LOG_LEVEL, RemoteDBSettings } from "./lib/src/types";
|
||||||
import { path2id, id2path } from "./utils";
|
import { path2id, id2path } from "./utils";
|
||||||
import { delay, runWithLock, versionNumberString2Number } from "./lib/src/utils";
|
import { delay, versionNumberString2Number } from "./lib/src/utils";
|
||||||
import { Logger } from "./lib/src/logger";
|
import { Logger } from "./lib/src/logger";
|
||||||
import { checkSyncInfo } from "./lib/src/utils_couchdb";
|
import { checkSyncInfo } from "./lib/src/utils_couchdb.js";
|
||||||
import { testCrypt } from "./lib/src/e2ee_v2";
|
import { testCrypt } from "./lib/src/e2ee_v2";
|
||||||
import ObsidianLiveSyncPlugin from "./main";
|
import ObsidianLiveSyncPlugin from "./main";
|
||||||
|
|
||||||
@@ -28,6 +28,9 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
containerEl.empty();
|
containerEl.empty();
|
||||||
|
|
||||||
containerEl.createEl("h2", { text: "Settings for Self-hosted LiveSync." });
|
containerEl.createEl("h2", { text: "Settings for Self-hosted LiveSync." });
|
||||||
|
containerEl.addClass("sls-setting");
|
||||||
|
containerEl.removeClass("isWizard");
|
||||||
|
|
||||||
|
|
||||||
const w = containerEl.createDiv("");
|
const w = containerEl.createDiv("");
|
||||||
const screenElements: { [key: string]: HTMLElement[] } = {};
|
const screenElements: { [key: string]: HTMLElement[] } = {};
|
||||||
@@ -39,15 +42,17 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
};
|
};
|
||||||
w.addClass("sls-setting-menu");
|
w.addClass("sls-setting-menu");
|
||||||
w.innerHTML = `
|
w.innerHTML = `
|
||||||
<label class='sls-setting-label selected'><input type='radio' name='disp' value='100' class='sls-setting-tab' checked><div class='sls-setting-menu-btn'>💬</div></label>
|
<label class='sls-setting-label c-100 wizardHidden'><input type='radio' name='disp' value='100' class='sls-setting-tab'><div class='sls-setting-menu-btn'>💬</div></label>
|
||||||
<label class='sls-setting-label'><input type='radio' name='disp' value='0' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🛰️</div></label>
|
<label class='sls-setting-label c-110'><input type='radio' name='disp' value='110' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🪄</div></label>
|
||||||
<label class='sls-setting-label'><input type='radio' name='disp' value='10' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>📦</div></label>
|
<label class='sls-setting-label c-0'><input type='radio' name='disp' value='0' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🛰️</div></label>
|
||||||
<label class='sls-setting-label'><input type='radio' name='disp' value='20' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>⚙️</div></label>
|
|
||||||
<label class='sls-setting-label'><input type='radio' name='disp' value='30' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🔁</div></label>
|
<label class='sls-setting-label c-10'><input type='radio' name='disp' value='10' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>📦</div></label>
|
||||||
<label class='sls-setting-label'><input type='radio' name='disp' value='40' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🔧</div></label>
|
<label class='sls-setting-label c-20 wizardHidden'><input type='radio' name='disp' value='20' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>⚙️</div></label>
|
||||||
<label class='sls-setting-label'><input type='radio' name='disp' value='50' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🧰</div></label>
|
<label class='sls-setting-label c-30 wizardHidden'><input type='radio' name='disp' value='30' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🔁</div></label>
|
||||||
<label class='sls-setting-label'><input type='radio' name='disp' value='60' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🔌</div></label>
|
<label class='sls-setting-label c-40'><input type='radio' name='disp' value='40' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🔧</div></label>
|
||||||
<label class='sls-setting-label'><input type='radio' name='disp' value='70' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🚑</div></label>
|
<label class='sls-setting-label c-50 wizardHidden'><input type='radio' name='disp' value='50' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🧰</div></label>
|
||||||
|
<label class='sls-setting-label c-60 wizardHidden'><input type='radio' name='disp' value='60' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🔌</div></label>
|
||||||
|
<label class='sls-setting-label c-70 wizardHidden'><input type='radio' name='disp' value='70' class='sls-setting-tab' ><div class='sls-setting-menu-btn'>🚑</div></label>
|
||||||
`;
|
`;
|
||||||
const menuTabs = w.querySelectorAll(".sls-setting-label");
|
const menuTabs = w.querySelectorAll(".sls-setting-label");
|
||||||
const changeDisplay = (screen: string) => {
|
const changeDisplay = (screen: string) => {
|
||||||
@@ -58,6 +63,16 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
screenElements[k].forEach((element) => element.addClass("setting-collapsed"));
|
screenElements[k].forEach((element) => element.addClass("setting-collapsed"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
w.querySelectorAll(`.sls-setting-label`).forEach((element) => {
|
||||||
|
element.removeClass("selected");
|
||||||
|
(element.querySelector("input[type=radio]") as HTMLInputElement).checked = false;
|
||||||
|
});
|
||||||
|
console.log(`.sls-setting-label.c-${screen}`)
|
||||||
|
w.querySelectorAll(`.sls-setting-label.c-${screen}`).forEach((element) => {
|
||||||
|
console.log(element)
|
||||||
|
element.addClass("selected");
|
||||||
|
(element.querySelector("input[type=radio]") as HTMLInputElement).checked = true;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
menuTabs.forEach((element) => {
|
menuTabs.forEach((element) => {
|
||||||
const e = element.querySelector(".sls-setting-tab");
|
const e = element.querySelector(".sls-setting-tab");
|
||||||
@@ -97,12 +112,6 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
|
|
||||||
|
|
||||||
addScreenElement("100", containerInformationEl);
|
addScreenElement("100", containerInformationEl);
|
||||||
const containerRemoteDatabaseEl = containerEl.createDiv();
|
|
||||||
containerRemoteDatabaseEl.createEl("h3", { text: "Remote Database configuration" });
|
|
||||||
const syncWarn = containerRemoteDatabaseEl.createEl("div", { text: `These settings are kept locked while any synchronization options are enabled. Disable these options in the "Sync Settings" tab to unlock.` });
|
|
||||||
syncWarn.addClass("op-warn-info");
|
|
||||||
syncWarn.addClass("sls-hidden");
|
|
||||||
|
|
||||||
const isAnySyncEnabled = (): boolean => {
|
const isAnySyncEnabled = (): boolean => {
|
||||||
if (this.plugin.settings.liveSync) return true;
|
if (this.plugin.settings.liveSync) return true;
|
||||||
if (this.plugin.settings.periodicReplication) return true;
|
if (this.plugin.settings.periodicReplication) return true;
|
||||||
@@ -113,6 +122,55 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
if (this.plugin.localDatabase.syncStatus == "PAUSED") return true;
|
if (this.plugin.localDatabase.syncStatus == "PAUSED") return true;
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
let inWizard = false;
|
||||||
|
|
||||||
|
const setupWizardEl = containerEl.createDiv();
|
||||||
|
setupWizardEl.createEl("h3", { text: "Setup wizard" });
|
||||||
|
new Setting(setupWizardEl)
|
||||||
|
.setName("Discard the existing configuration and set up")
|
||||||
|
.addButton((text) => {
|
||||||
|
text.setButtonText("Next").onClick(async () => {
|
||||||
|
if (JSON.stringify(this.plugin.settings) != JSON.stringify(DEFAULT_SETTINGS)) {
|
||||||
|
this.plugin.settings = { ...DEFAULT_SETTINGS };
|
||||||
|
this.plugin.saveSettings();
|
||||||
|
Logger("Configuration has been flushed, please open it again", LOG_LEVEL.NOTICE)
|
||||||
|
this.hide();
|
||||||
|
} else {
|
||||||
|
containerEl.addClass("isWizard");
|
||||||
|
applyDisplayEnabled();
|
||||||
|
inWizard = true;
|
||||||
|
changeDisplay("0")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
new Setting(setupWizardEl)
|
||||||
|
.setName("Do not discard the existing configuration and set up again")
|
||||||
|
.addButton((text) => {
|
||||||
|
text.setButtonText("Next").onClick(async () => {
|
||||||
|
await this.plugin.resetLocalDatabase();
|
||||||
|
this.plugin.settings.liveSync = false;
|
||||||
|
this.plugin.settings.periodicReplication = false;
|
||||||
|
this.plugin.settings.syncOnSave = false;
|
||||||
|
this.plugin.settings.syncOnStart = false;
|
||||||
|
this.plugin.settings.syncOnFileOpen = false;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
containerEl.addClass("isWizard");
|
||||||
|
applyDisplayEnabled();
|
||||||
|
inWizard = true;
|
||||||
|
changeDisplay("0")
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
addScreenElement("110", setupWizardEl);
|
||||||
|
|
||||||
|
const containerRemoteDatabaseEl = containerEl.createDiv();
|
||||||
|
containerRemoteDatabaseEl.createEl("h3", { text: "Remote Database configuration" });
|
||||||
|
const syncWarn = containerRemoteDatabaseEl.createEl("div", { text: `These settings are kept locked while any synchronization options are enabled. Disable these options in the "Sync Settings" tab to unlock.` });
|
||||||
|
syncWarn.addClass("op-warn-info");
|
||||||
|
syncWarn.addClass("sls-hidden");
|
||||||
|
|
||||||
|
|
||||||
const applyDisplayEnabled = () => {
|
const applyDisplayEnabled = () => {
|
||||||
if (isAnySyncEnabled()) {
|
if (isAnySyncEnabled()) {
|
||||||
dbSettings.forEach((e) => {
|
dbSettings.forEach((e) => {
|
||||||
@@ -200,11 +258,18 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
.setDesc("Encrypt contents on the remote database. If you use the plugin's synchronization feature, enabling this is recommend.")
|
.setDesc("Encrypt contents on the remote database. If you use the plugin's synchronization feature, enabling this is recommend.")
|
||||||
.addToggle((toggle) =>
|
.addToggle((toggle) =>
|
||||||
toggle.setValue(this.plugin.settings.workingEncrypt).onChange(async (value) => {
|
toggle.setValue(this.plugin.settings.workingEncrypt).onChange(async (value) => {
|
||||||
|
if (inWizard) {
|
||||||
|
this.plugin.settings.encrypt = value;
|
||||||
|
passphrase.setDisabled(!value);
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
} else {
|
||||||
this.plugin.settings.workingEncrypt = value;
|
this.plugin.settings.workingEncrypt = value;
|
||||||
passphrase.setDisabled(!value);
|
passphrase.setDisabled(!value);
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const passphrase = new Setting(containerRemoteDatabaseEl)
|
const passphrase = new Setting(containerRemoteDatabaseEl)
|
||||||
.setName("Passphrase")
|
.setName("Passphrase")
|
||||||
.setDesc("Encrypting passphrase. If you change the passphrase of a existing database, overwriting the remote database is strongly recommended.")
|
.setDesc("Encrypting passphrase. If you change the passphrase of a existing database, overwriting the remote database is strongly recommended.")
|
||||||
@@ -212,12 +277,18 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
text.setPlaceholder("")
|
text.setPlaceholder("")
|
||||||
.setValue(this.plugin.settings.workingPassphrase)
|
.setValue(this.plugin.settings.workingPassphrase)
|
||||||
.onChange(async (value) => {
|
.onChange(async (value) => {
|
||||||
|
if (inWizard) {
|
||||||
|
this.plugin.settings.passphrase = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
} else {
|
||||||
this.plugin.settings.workingPassphrase = value;
|
this.plugin.settings.workingPassphrase = value;
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
text.inputEl.setAttribute("type", "password");
|
text.inputEl.setAttribute("type", "password");
|
||||||
});
|
});
|
||||||
passphrase.setDisabled(!this.plugin.settings.workingEncrypt);
|
passphrase.setDisabled(!this.plugin.settings.workingEncrypt);
|
||||||
|
|
||||||
const checkWorkingPassphrase = async (): Promise<boolean> => {
|
const checkWorkingPassphrase = async (): Promise<boolean> => {
|
||||||
const settingForCheck: RemoteDBSettings = {
|
const settingForCheck: RemoteDBSettings = {
|
||||||
...this.plugin.settings,
|
...this.plugin.settings,
|
||||||
@@ -263,7 +334,6 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
this.plugin.settings.passphrase = this.plugin.settings.workingPassphrase;
|
this.plugin.settings.passphrase = this.plugin.settings.workingPassphrase;
|
||||||
|
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
// await this.plugin.resetLocalDatabase();
|
|
||||||
if (sendToServer) {
|
if (sendToServer) {
|
||||||
await this.plugin.initializeDatabase(true);
|
await this.plugin.initializeDatabase(true);
|
||||||
await this.plugin.markRemoteLocked();
|
await this.plugin.markRemoteLocked();
|
||||||
@@ -278,6 +348,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
new Setting(containerRemoteDatabaseEl)
|
new Setting(containerRemoteDatabaseEl)
|
||||||
.setName("Apply")
|
.setName("Apply")
|
||||||
.setDesc("Apply encryption settings")
|
.setDesc("Apply encryption settings")
|
||||||
|
.setClass("wizardHidden")
|
||||||
.addButton((button) =>
|
.addButton((button) =>
|
||||||
button
|
button
|
||||||
.setButtonText("Apply")
|
.setButtonText("Apply")
|
||||||
@@ -285,10 +356,11 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
.setDisabled(false)
|
.setDisabled(false)
|
||||||
.setClass("sls-btn-right")
|
.setClass("sls-btn-right")
|
||||||
.onClick(async () => {
|
.onClick(async () => {
|
||||||
await applyEncryption(false);
|
await applyEncryption(true);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
const rebuildDB = async (method: "localOnly" | "remoteOnly" | "rebuildBothByThisDevice") => {
|
const rebuildDB = async (method: "localOnly" | "remoteOnly" | "rebuildBothByThisDevice") => {
|
||||||
this.plugin.settings.liveSync = false;
|
this.plugin.settings.liveSync = false;
|
||||||
this.plugin.settings.periodicReplication = false;
|
this.plugin.settings.periodicReplication = false;
|
||||||
@@ -324,6 +396,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
new Setting(containerRemoteDatabaseEl)
|
new Setting(containerRemoteDatabaseEl)
|
||||||
.setName("Overwrite remote database")
|
.setName("Overwrite remote database")
|
||||||
.setDesc("Overwrite remote database with local DB and passphrase.")
|
.setDesc("Overwrite remote database with local DB and passphrase.")
|
||||||
|
.setClass("wizardHidden")
|
||||||
.addButton((button) =>
|
.addButton((button) =>
|
||||||
button
|
button
|
||||||
.setButtonText("Send")
|
.setButtonText("Send")
|
||||||
@@ -338,6 +411,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
new Setting(containerRemoteDatabaseEl)
|
new Setting(containerRemoteDatabaseEl)
|
||||||
.setName("Rebuild everything")
|
.setName("Rebuild everything")
|
||||||
.setDesc("Rebuild local and remote database with local files.")
|
.setDesc("Rebuild local and remote database with local files.")
|
||||||
|
.setClass("wizardHidden")
|
||||||
.addButton((button) =>
|
.addButton((button) =>
|
||||||
button
|
button
|
||||||
.setButtonText("Rebuild")
|
.setButtonText("Rebuild")
|
||||||
@@ -548,6 +622,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
new Setting(containerRemoteDatabaseEl)
|
new Setting(containerRemoteDatabaseEl)
|
||||||
.setName("Lock remote database")
|
.setName("Lock remote database")
|
||||||
.setDesc("Lock remote database to prevent synchronization with other devices.")
|
.setDesc("Lock remote database to prevent synchronization with other devices.")
|
||||||
|
.setClass("wizardHidden")
|
||||||
.addButton((button) =>
|
.addButton((button) =>
|
||||||
button
|
button
|
||||||
.setButtonText("Lock")
|
.setButtonText("Lock")
|
||||||
@@ -557,6 +632,50 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
await this.plugin.markRemoteLocked();
|
await this.plugin.markRemoteLocked();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
new Setting(containerRemoteDatabaseEl)
|
||||||
|
.setName("")
|
||||||
|
.setClass("wizardOnly")
|
||||||
|
.addButton((button) =>
|
||||||
|
button
|
||||||
|
.setButtonText("Next")
|
||||||
|
.setClass("mod-cta")
|
||||||
|
.setDisabled(false)
|
||||||
|
.onClick(async () => {
|
||||||
|
if (!this.plugin.settings.encrypt) {
|
||||||
|
this.plugin.settings.passphrase = "";
|
||||||
|
}
|
||||||
|
if (this.plugin.settings.couchDB_URI.contains(".cloudantnosqldb.")) {
|
||||||
|
this.plugin.settings.customChunkSize = 0;
|
||||||
|
} else {
|
||||||
|
this.plugin.settings.customChunkSize = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
changeDisplay("10")
|
||||||
|
})
|
||||||
|
);
|
||||||
|
new Setting(containerRemoteDatabaseEl)
|
||||||
|
.setName("")
|
||||||
|
.setClass("wizardOnly")
|
||||||
|
.addButton((button) =>
|
||||||
|
button
|
||||||
|
.setButtonText("Discard exist database and proceed")
|
||||||
|
.setDisabled(false)
|
||||||
|
.setWarning()
|
||||||
|
.onClick(async () => {
|
||||||
|
if (!this.plugin.settings.encrypt) {
|
||||||
|
this.plugin.settings.passphrase = "";
|
||||||
|
}
|
||||||
|
if (this.plugin.settings.couchDB_URI.contains(".cloudantnosqldb.")) {
|
||||||
|
this.plugin.settings.customChunkSize = 0;
|
||||||
|
} else {
|
||||||
|
this.plugin.settings.customChunkSize = 100;
|
||||||
|
}
|
||||||
|
this.plugin.saveSettings();
|
||||||
|
await this.plugin.tryResetRemoteDatabase();
|
||||||
|
changeDisplay("10")
|
||||||
|
})
|
||||||
|
);
|
||||||
addScreenElement("0", containerRemoteDatabaseEl);
|
addScreenElement("0", containerRemoteDatabaseEl);
|
||||||
const containerLocalDatabaseEl = containerEl.createDiv();
|
const containerLocalDatabaseEl = containerEl.createDiv();
|
||||||
containerLocalDatabaseEl.createEl("h3", { text: "Local Database configuration" });
|
containerLocalDatabaseEl.createEl("h3", { text: "Local Database configuration" });
|
||||||
@@ -576,18 +695,10 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
new Setting(containerLocalDatabaseEl).setName("Garbage check").addButton((button) =>
|
|
||||||
button
|
|
||||||
.setButtonText("Check now")
|
|
||||||
.setDisabled(false)
|
|
||||||
.onClick(async () => {
|
|
||||||
await this.plugin.garbageCheck();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
new Setting(containerLocalDatabaseEl)
|
new Setting(containerLocalDatabaseEl)
|
||||||
.setName("Fetch rebuilt DB")
|
.setName("Fetch rebuilt DB")
|
||||||
.setDesc("Restore or reconstruct local database from remote database.")
|
.setDesc("Restore or reconstruct local database from remote database.")
|
||||||
|
.setClass("wizardHidden")
|
||||||
.addButton((button) =>
|
.addButton((button) =>
|
||||||
button
|
button
|
||||||
.setButtonText("Fetch")
|
.setButtonText("Fetch")
|
||||||
@@ -603,7 +714,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
let newDatabaseName = this.plugin.settings.additionalSuffixOfDatabaseName + "";
|
let newDatabaseName = this.plugin.settings.additionalSuffixOfDatabaseName + "";
|
||||||
new Setting(containerLocalDatabaseEl)
|
new Setting(containerLocalDatabaseEl)
|
||||||
.setName("Database suffix")
|
.setName("Database suffix")
|
||||||
.setDesc("Set unique name for using same vault name on different directory.")
|
.setDesc("Optional: Set unique name for using same vault name on different directory.")
|
||||||
.addText((text) => {
|
.addText((text) => {
|
||||||
text.setPlaceholder("")
|
text.setPlaceholder("")
|
||||||
.setValue(newDatabaseName)
|
.setValue(newDatabaseName)
|
||||||
@@ -624,7 +735,17 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
await this.plugin.initializeDatabase();
|
await this.plugin.initializeDatabase();
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
new Setting(containerLocalDatabaseEl)
|
||||||
|
.setName("")
|
||||||
|
.setClass("wizardOnly")
|
||||||
|
.addButton((button) =>
|
||||||
|
button
|
||||||
|
.setButtonText("Next")
|
||||||
|
.setDisabled(false)
|
||||||
|
.onClick(async () => {
|
||||||
|
changeDisplay("40");
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
addScreenElement("10", containerLocalDatabaseEl);
|
addScreenElement("10", containerLocalDatabaseEl);
|
||||||
const containerGeneralSettingsEl = containerEl.createDiv();
|
const containerGeneralSettingsEl = containerEl.createDiv();
|
||||||
@@ -650,6 +771,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
);
|
);
|
||||||
new Setting(containerGeneralSettingsEl)
|
new Setting(containerGeneralSettingsEl)
|
||||||
.setName("Delete metadata of deleted files.")
|
.setName("Delete metadata of deleted files.")
|
||||||
|
.setClass("wizardHidden")
|
||||||
.addToggle((toggle) => {
|
.addToggle((toggle) => {
|
||||||
toggle.setValue(this.plugin.settings.deleteMetadataOfDeletedFiles).onChange(async (value) => {
|
toggle.setValue(this.plugin.settings.deleteMetadataOfDeletedFiles).onChange(async (value) => {
|
||||||
this.plugin.settings.deleteMetadataOfDeletedFiles = value;
|
this.plugin.settings.deleteMetadataOfDeletedFiles = value;
|
||||||
@@ -661,6 +783,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
addScreenElement("20", containerGeneralSettingsEl);
|
addScreenElement("20", containerGeneralSettingsEl);
|
||||||
const containerSyncSettingEl = containerEl.createDiv();
|
const containerSyncSettingEl = containerEl.createDiv();
|
||||||
containerSyncSettingEl.createEl("h3", { text: "Sync Settings" });
|
containerSyncSettingEl.createEl("h3", { text: "Sync Settings" });
|
||||||
|
containerSyncSettingEl.addClass("wizardHidden")
|
||||||
|
|
||||||
if (this.plugin.settings.versionUpFlash != "") {
|
if (this.plugin.settings.versionUpFlash != "") {
|
||||||
const c = containerSyncSettingEl.createEl("div", { text: this.plugin.settings.versionUpFlash });
|
const c = containerSyncSettingEl.createEl("div", { text: this.plugin.settings.versionUpFlash });
|
||||||
@@ -945,7 +1068,6 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
new Setting(containerSyncSettingEl)
|
new Setting(containerSyncSettingEl)
|
||||||
.setName("Chunk size")
|
.setName("Chunk size")
|
||||||
.setDesc("Customize chunk size for binary files (0.1MBytes). This cannot be increased when using IBM Cloudant.")
|
.setDesc("Customize chunk size for binary files (0.1MBytes). This cannot be increased when using IBM Cloudant.")
|
||||||
@@ -962,6 +1084,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
});
|
});
|
||||||
text.inputEl.setAttribute("type", "number");
|
text.inputEl.setAttribute("type", "number");
|
||||||
});
|
});
|
||||||
|
|
||||||
new Setting(containerSyncSettingEl)
|
new Setting(containerSyncSettingEl)
|
||||||
.setName("Read chunks online.")
|
.setName("Read chunks online.")
|
||||||
.setDesc("If this option is enabled, LiveSync reads chunks online directly instead of replicating them locally. Increasing Custom chunk size is recommended.")
|
.setDesc("If this option is enabled, LiveSync reads chunks online directly instead of replicating them locally. Increasing Custom chunk size is recommended.")
|
||||||
@@ -1027,24 +1150,16 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
new Setting(containerMiscellaneousEl)
|
let currentPreset = "NONE";
|
||||||
.setName("Check integrity on saving")
|
|
||||||
.setDesc("Check database integrity on saving to database")
|
|
||||||
.addToggle((toggle) =>
|
|
||||||
toggle.setValue(this.plugin.settings.checkIntegrityOnSave).onChange(async (value) => {
|
|
||||||
this.plugin.settings.checkIntegrityOnSave = value;
|
|
||||||
await this.plugin.saveSettings();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
let currentPrest = "NONE";
|
|
||||||
new Setting(containerMiscellaneousEl)
|
new Setting(containerMiscellaneousEl)
|
||||||
.setName("Presets")
|
.setName("Presets")
|
||||||
.setDesc("Apply preset configuration")
|
.setDesc("Apply preset configuration")
|
||||||
.addDropdown((dropdown) =>
|
.addDropdown((dropdown) =>
|
||||||
dropdown
|
dropdown
|
||||||
.addOptions({ NONE: "", LIVESYNC: "LiveSync", PERIODIC: "Periodic w/ batch", DISABLE: "Disable all sync" })
|
.addOptions({ NONE: "", LIVESYNC: "LiveSync", PERIODIC: "Periodic w/ batch", DISABLE: "Disable all sync" })
|
||||||
.setValue(currentPrest)
|
.setValue(currentPreset)
|
||||||
.onChange((value) => (currentPrest = value))
|
.onChange((value) => (currentPreset = value))
|
||||||
)
|
)
|
||||||
.addButton((button) =>
|
.addButton((button) =>
|
||||||
button
|
button
|
||||||
@@ -1052,7 +1167,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
.setDisabled(false)
|
.setDisabled(false)
|
||||||
.setCta()
|
.setCta()
|
||||||
.onClick(async () => {
|
.onClick(async () => {
|
||||||
if (currentPrest == "") {
|
if (currentPreset == "") {
|
||||||
Logger("Select any preset.", LOG_LEVEL.NOTICE);
|
Logger("Select any preset.", LOG_LEVEL.NOTICE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1062,10 +1177,10 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
this.plugin.settings.syncOnSave = false;
|
this.plugin.settings.syncOnSave = false;
|
||||||
this.plugin.settings.syncOnStart = false;
|
this.plugin.settings.syncOnStart = false;
|
||||||
this.plugin.settings.syncOnFileOpen = false;
|
this.plugin.settings.syncOnFileOpen = false;
|
||||||
if (currentPrest == "LIVESYNC") {
|
if (currentPreset == "LIVESYNC") {
|
||||||
this.plugin.settings.liveSync = true;
|
this.plugin.settings.liveSync = true;
|
||||||
Logger("Synchronization setting configured as LiveSync.", LOG_LEVEL.NOTICE);
|
Logger("Synchronization setting configured as LiveSync.", LOG_LEVEL.NOTICE);
|
||||||
} else if (currentPrest == "PERIODIC") {
|
} else if (currentPreset == "PERIODIC") {
|
||||||
this.plugin.settings.batchSave = true;
|
this.plugin.settings.batchSave = true;
|
||||||
this.plugin.settings.periodicReplication = true;
|
this.plugin.settings.periodicReplication = true;
|
||||||
this.plugin.settings.syncOnSave = false;
|
this.plugin.settings.syncOnSave = false;
|
||||||
@@ -1077,9 +1192,22 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
}
|
}
|
||||||
this.plugin.saveSettings();
|
this.plugin.saveSettings();
|
||||||
await this.plugin.realizeSettingSyncMode();
|
await this.plugin.realizeSettingSyncMode();
|
||||||
|
if (inWizard) {
|
||||||
|
this.hide();
|
||||||
|
await this.plugin.resetLocalDatabase();
|
||||||
|
await this.plugin.initializeDatabase(true)
|
||||||
|
await this.plugin.replicate(true);
|
||||||
|
Logger("All done! Please set up subsequent devices with 'Copy setup URI' and 'Open setup URI'.", LOG_LEVEL.NOTICE)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const infoApply = containerMiscellaneousEl.createEl("div", { text: `To finish setup, please select one of the presets` });
|
||||||
|
infoApply.addClass("op-warn-info");
|
||||||
|
infoApply.addClass("wizardOnly")
|
||||||
|
|
||||||
addScreenElement("40", containerMiscellaneousEl);
|
addScreenElement("40", containerMiscellaneousEl);
|
||||||
|
|
||||||
const containerHatchEl = containerEl.createDiv();
|
const containerHatchEl = containerEl.createDiv();
|
||||||
@@ -1143,36 +1271,6 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
Logger("done", LOG_LEVEL.NOTICE, "verify");
|
Logger("done", LOG_LEVEL.NOTICE, "verify");
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
new Setting(containerHatchEl)
|
|
||||||
.setName("Sanity check")
|
|
||||||
.setDesc("Verify")
|
|
||||||
.addButton((button) =>
|
|
||||||
button
|
|
||||||
.setButtonText("Sanity check")
|
|
||||||
.setDisabled(false)
|
|
||||||
.setWarning()
|
|
||||||
.onClick(async () => {
|
|
||||||
// const notice = NewNotice("", 0);
|
|
||||||
Logger(`Begin sanity check`, LOG_LEVEL.NOTICE, "sancheck");
|
|
||||||
await runWithLock("sancheck", true, async () => {
|
|
||||||
const db = this.plugin.localDatabase.localDatabase;
|
|
||||||
const wf = await db.allDocs();
|
|
||||||
const filesDatabase = wf.rows.filter((e) => !e.id.startsWith("h:") && !e.id.startsWith("ps:") && e.id != "obsydian_livesync_version").map((e) => e.id);
|
|
||||||
let count = 0;
|
|
||||||
for (const id of filesDatabase) {
|
|
||||||
count++;
|
|
||||||
Logger(`${count}/${filesDatabase.length}\n${id2path(id)}`, LOG_LEVEL.NOTICE, "sancheck");
|
|
||||||
const w = await db.get<EntryDoc>(id);
|
|
||||||
if (!(await this.plugin.localDatabase.sanCheck(w))) {
|
|
||||||
Logger(`The file ${id2path(id)} missing child(ren)`, LOG_LEVEL.NOTICE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Logger(`Done`, LOG_LEVEL.NOTICE, "sancheck");
|
|
||||||
// Logger("done", LOG_LEVEL.NOTICE);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
new Setting(containerHatchEl)
|
new Setting(containerHatchEl)
|
||||||
.setName("Suspend file watching")
|
.setName("Suspend file watching")
|
||||||
@@ -1184,40 +1282,11 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
containerHatchEl.createEl("div", {
|
|
||||||
text: sanitizeHTMLToDom(`Advanced buttons<br>
|
|
||||||
These buttons could break your database easily.`),
|
|
||||||
});
|
|
||||||
new Setting(containerHatchEl)
|
new Setting(containerHatchEl)
|
||||||
.setName("Reset remote database")
|
.setName("Discard local database to reset or uninstall Self-hosted LiveSync")
|
||||||
.setDesc("Reset remote database, this affects only database. If you replicate again, remote database will restored by local database.")
|
|
||||||
.addButton((button) =>
|
.addButton((button) =>
|
||||||
button
|
button
|
||||||
.setButtonText("Reset")
|
.setButtonText("Discard")
|
||||||
.setDisabled(false)
|
|
||||||
.setWarning()
|
|
||||||
.onClick(async () => {
|
|
||||||
await this.plugin.tryResetRemoteDatabase();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
new Setting(containerHatchEl)
|
|
||||||
.setName("Reset local database")
|
|
||||||
.setDesc("Reset local database, this affects only database. If you replicate again, local database will restored by remote database.")
|
|
||||||
.addButton((button) =>
|
|
||||||
button
|
|
||||||
.setButtonText("Reset")
|
|
||||||
.setDisabled(false)
|
|
||||||
.setWarning()
|
|
||||||
.onClick(async () => {
|
|
||||||
await this.plugin.resetLocalDatabase();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
new Setting(containerHatchEl)
|
|
||||||
.setName("Initialize local database again")
|
|
||||||
.setDesc("WARNING: Reset local database and reconstruct by storage data. It affects local database, but if you replicate remote as is, remote data will be merged or corrupted.")
|
|
||||||
.addButton((button) =>
|
|
||||||
button
|
|
||||||
.setButtonText("INITIALIZE")
|
|
||||||
.setWarning()
|
.setWarning()
|
||||||
.setDisabled(false)
|
.setDisabled(false)
|
||||||
.onClick(async () => {
|
.onClick(async () => {
|
||||||
@@ -1226,20 +1295,6 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
new Setting(containerHatchEl)
|
|
||||||
.setName("Drop old encrypted database")
|
|
||||||
.setDesc("WARNING: Please use this button only when you have failed on converting old-style local database at v0.10.0.")
|
|
||||||
.addButton((button) =>
|
|
||||||
button
|
|
||||||
.setButtonText("Drop")
|
|
||||||
.setWarning()
|
|
||||||
.setDisabled(false)
|
|
||||||
.onClick(async () => {
|
|
||||||
await this.plugin.resetLocalOldDatabase();
|
|
||||||
await this.plugin.initializeDatabase();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
addScreenElement("50", containerHatchEl);
|
addScreenElement("50", containerHatchEl);
|
||||||
// With great respect, thank you TfTHacker!
|
// With great respect, thank you TfTHacker!
|
||||||
// Refer: https://github.com/TfTHacker/obsidian42-brat/blob/main/src/features/BetaPlugins.ts
|
// Refer: https://github.com/TfTHacker/obsidian42-brat/blob/main/src/features/BetaPlugins.ts
|
||||||
@@ -1383,9 +1438,17 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
applyDisplayEnabled();
|
applyDisplayEnabled();
|
||||||
addScreenElement("70", containerCorruptedDataEl);
|
addScreenElement("70", containerCorruptedDataEl);
|
||||||
if (lastVersion != this.plugin.settings.lastReadUpdates) {
|
if (lastVersion != this.plugin.settings.lastReadUpdates) {
|
||||||
|
if (JSON.stringify(this.plugin.settings) != JSON.stringify(DEFAULT_SETTINGS)) {
|
||||||
changeDisplay("100");
|
changeDisplay("100");
|
||||||
} else {
|
} else {
|
||||||
|
changeDisplay("110")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isAnySyncEnabled()) {
|
||||||
changeDisplay("0");
|
changeDisplay("0");
|
||||||
|
} else {
|
||||||
|
changeDisplay("110")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user