mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2025-12-22 22:21:29 +00:00
Merge pull request #716 from chriscross12324/bugfix/setting-panel-hierarchy
bugfix/setting-panel-hierarchy: Fixed visual inconsistencies
This commit is contained in:
@@ -21,7 +21,7 @@ export function paneCustomisationSync(
|
|||||||
text: "Please set device name to identify this device. This name should be unique among your devices. While not configured, we cannot enable this feature.",
|
text: "Please set device name to identify this device. This name should be unique among your devices. While not configured, we cannot enable this feature.",
|
||||||
cls: "op-warn",
|
cls: "op-warn",
|
||||||
},
|
},
|
||||||
(c) => {},
|
(c) => { },
|
||||||
visibleOnly(() => this.isConfiguredAs("deviceAndVaultName", ""))
|
visibleOnly(() => this.isConfiguredAs("deviceAndVaultName", ""))
|
||||||
);
|
);
|
||||||
this.createEl(
|
this.createEl(
|
||||||
@@ -31,7 +31,7 @@ export function paneCustomisationSync(
|
|||||||
text: "We cannot change the device name while this feature is enabled. Please disable this feature to change the device name.",
|
text: "We cannot change the device name while this feature is enabled. Please disable this feature to change the device name.",
|
||||||
cls: "op-warn-info",
|
cls: "op-warn-info",
|
||||||
},
|
},
|
||||||
(c) => {},
|
(c) => { },
|
||||||
visibleOnly(() => this.isConfiguredAs("usePluginSync", true))
|
visibleOnly(() => this.isConfiguredAs("usePluginSync", true))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -119,8 +119,8 @@ export function paneHatch(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement,
|
|||||||
const scheme = pluginConfig.couchDB_URI.startsWith("http:")
|
const scheme = pluginConfig.couchDB_URI.startsWith("http:")
|
||||||
? "(HTTP)"
|
? "(HTTP)"
|
||||||
: pluginConfig.couchDB_URI.startsWith("https:")
|
: pluginConfig.couchDB_URI.startsWith("https:")
|
||||||
? "(HTTPS)"
|
? "(HTTPS)"
|
||||||
: "";
|
: "";
|
||||||
pluginConfig.couchDB_URI = isCloudantURI(pluginConfig.couchDB_URI)
|
pluginConfig.couchDB_URI = isCloudantURI(pluginConfig.couchDB_URI)
|
||||||
? "cloudant"
|
? "cloudant"
|
||||||
: `self-hosted${scheme}`;
|
: `self-hosted${scheme}`;
|
||||||
@@ -150,8 +150,8 @@ export function paneHatch(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement,
|
|||||||
const endpointScheme = pluginConfig.endpoint.startsWith("http:")
|
const endpointScheme = pluginConfig.endpoint.startsWith("http:")
|
||||||
? "(HTTP)"
|
? "(HTTP)"
|
||||||
: pluginConfig.endpoint.startsWith("https:")
|
: pluginConfig.endpoint.startsWith("https:")
|
||||||
? "(HTTPS)"
|
? "(HTTPS)"
|
||||||
: "";
|
: "";
|
||||||
pluginConfig.endpoint = `${endpoint.indexOf(".r2.cloudflarestorage.") !== -1 ? "R2" : "self-hosted?"}(${endpointScheme})`;
|
pluginConfig.endpoint = `${endpoint.indexOf(".r2.cloudflarestorage.") !== -1 ? "R2" : "self-hosted?"}(${endpointScheme})`;
|
||||||
}
|
}
|
||||||
const obsidianInfo = {
|
const obsidianInfo = {
|
||||||
@@ -166,9 +166,9 @@ ${stringifyYaml(responseConfig)}
|
|||||||
---
|
---
|
||||||
# ---- Plug-in config ----
|
# ---- Plug-in config ----
|
||||||
${stringifyYaml({
|
${stringifyYaml({
|
||||||
version: this.manifestVersion,
|
version: this.manifestVersion,
|
||||||
...pluginConfig,
|
...pluginConfig,
|
||||||
})}`;
|
})}`;
|
||||||
console.log(msgConfig);
|
console.log(msgConfig);
|
||||||
await navigator.clipboard.writeText(msgConfig);
|
await navigator.clipboard.writeText(msgConfig);
|
||||||
Logger(
|
Logger(
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ export function paneMaintenance(
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(paneEl, "Syncing", () => {}, this.onlyOnCouchDBOrMinIO).then((paneEl) => {
|
void addPanel(paneEl, "Syncing", () => { }, this.onlyOnCouchDBOrMinIO).then((paneEl) => {
|
||||||
new Setting(paneEl)
|
new Setting(paneEl)
|
||||||
.setName("Resend")
|
.setName("Resend")
|
||||||
.setDesc("Resend all chunks to the remote.")
|
.setDesc("Resend all chunks to the remote.")
|
||||||
@@ -283,7 +283,7 @@ export function paneMaintenance(
|
|||||||
.addOnUpdate(this.onlyOnCouchDB);
|
.addOnUpdate(this.onlyOnCouchDB);
|
||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(paneEl, "Total Overhaul", () => {}, this.onlyOnCouchDBOrMinIO).then((paneEl) => {
|
void addPanel(paneEl, "Total Overhaul", () => { }, this.onlyOnCouchDBOrMinIO).then((paneEl) => {
|
||||||
new Setting(paneEl)
|
new Setting(paneEl)
|
||||||
.setName("Rebuild everything")
|
.setName("Rebuild everything")
|
||||||
.setDesc("Rebuild local and remote database with local files.")
|
.setDesc("Rebuild local and remote database with local files.")
|
||||||
@@ -307,7 +307,7 @@ export function paneMaintenance(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
void addPanel(paneEl, "Rebuilding Operations (Remote Only)", () => {}, this.onlyOnCouchDBOrMinIO).then((paneEl) => {
|
void addPanel(paneEl, "Rebuilding Operations (Remote Only)", () => { }, this.onlyOnCouchDBOrMinIO).then((paneEl) => {
|
||||||
new Setting(paneEl)
|
new Setting(paneEl)
|
||||||
.setName("Perform cleanup")
|
.setName("Perform cleanup")
|
||||||
.setDesc(
|
.setDesc(
|
||||||
|
|||||||
@@ -321,282 +321,283 @@ export function paneRemoteConfig(
|
|||||||
},
|
},
|
||||||
onUpdate: this.enableOnlySyncDisabled,
|
onUpdate: this.enableOnlySyncDisabled,
|
||||||
});
|
});
|
||||||
void addPanel(paneEl, "Peer-to-Peer", undefined, this.onlyOnOnlyP2P).then((paneEl) => {
|
});
|
||||||
const syncWarnP2P = this.createEl(paneEl, "div", {
|
|
||||||
text: "",
|
void addPanel(paneEl, "Peer-to-Peer", undefined, this.onlyOnOnlyP2P).then((paneEl) => {
|
||||||
});
|
const syncWarnP2P = this.createEl(paneEl, "div", {
|
||||||
const p2pMessage = `This feature is a Work In Progress, and configurable on \`P2P Replicator\` Pane.
|
text: "",
|
||||||
|
});
|
||||||
|
const p2pMessage = `This feature is a Work In Progress, and configurable on \`P2P Replicator\` Pane.
|
||||||
The pane also can be launched by \`P2P Replicator\` command from the Command Palette.
|
The pane also can be launched by \`P2P Replicator\` command from the Command Palette.
|
||||||
`;
|
`;
|
||||||
|
|
||||||
void MarkdownRenderer.render(this.plugin.app, p2pMessage, syncWarnP2P, "/", this.plugin);
|
void MarkdownRenderer.render(this.plugin.app, p2pMessage, syncWarnP2P, "/", this.plugin);
|
||||||
syncWarnP2P.addClass("op-warn-info");
|
syncWarnP2P.addClass("op-warn-info");
|
||||||
new Setting(paneEl).setName("Apply Settings").setClass("wizardHidden").addApplyButton(["remoteType"]);
|
new Setting(paneEl).setName("Apply Settings").setClass("wizardHidden").addApplyButton(["remoteType"]);
|
||||||
// .addOnUpdate(onlyOnMinIO);
|
// .addOnUpdate(onlyOnMinIO);
|
||||||
// new Setting(paneEl).addButton((button) =>
|
// new Setting(paneEl).addButton((button) =>
|
||||||
// button
|
// button
|
||||||
// .setButtonText("Open P2P Replicator")
|
// .setButtonText("Open P2P Replicator")
|
||||||
// .onClick(() => {
|
// .onClick(() => {
|
||||||
// const addOn = this.plugin.getAddOn<P2PReplicator>(P2PReplicator.name);
|
// const addOn = this.plugin.getAddOn<P2PReplicator>(P2PReplicator.name);
|
||||||
// void addOn?.openPane();
|
// void addOn?.openPane();
|
||||||
// this.closeSetting();
|
// this.closeSetting();
|
||||||
// })
|
// })
|
||||||
// );
|
// );
|
||||||
});
|
});
|
||||||
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleMinioS3R2"), undefined, this.onlyOnMinIO).then(
|
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleMinioS3R2"), undefined, this.onlyOnMinIO).then(
|
||||||
(paneEl) => {
|
(paneEl) => {
|
||||||
const syncWarnMinio = this.createEl(paneEl, "div", {
|
const syncWarnMinio = this.createEl(paneEl, "div", {
|
||||||
text: "",
|
text: "",
|
||||||
});
|
});
|
||||||
const ObjectStorageMessage = $msg("obsidianLiveSyncSettingTab.msgObjectStorageWarning");
|
const ObjectStorageMessage = $msg("obsidianLiveSyncSettingTab.msgObjectStorageWarning");
|
||||||
|
|
||||||
void MarkdownRenderer.render(this.plugin.app, ObjectStorageMessage, syncWarnMinio, "/", this.plugin);
|
void MarkdownRenderer.render(this.plugin.app, ObjectStorageMessage, syncWarnMinio, "/", this.plugin);
|
||||||
syncWarnMinio.addClass("op-warn-info");
|
syncWarnMinio.addClass("op-warn-info");
|
||||||
|
|
||||||
new Setting(paneEl).autoWireText("endpoint", { holdValue: true });
|
new Setting(paneEl).autoWireText("endpoint", { holdValue: true });
|
||||||
new Setting(paneEl).autoWireToggle("forcePathStyle", { holdValue: true });
|
new Setting(paneEl).autoWireToggle("forcePathStyle", { holdValue: true });
|
||||||
new Setting(paneEl).autoWireText("accessKey", { holdValue: true });
|
new Setting(paneEl).autoWireText("accessKey", { holdValue: true });
|
||||||
|
|
||||||
new Setting(paneEl).autoWireText("secretKey", {
|
new Setting(paneEl).autoWireText("secretKey", {
|
||||||
holdValue: true,
|
holdValue: true,
|
||||||
isPassword: true,
|
isPassword: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
new Setting(paneEl).autoWireText("region", { holdValue: true });
|
new Setting(paneEl).autoWireText("region", { holdValue: true });
|
||||||
|
|
||||||
new Setting(paneEl).autoWireText("bucket", { holdValue: true });
|
new Setting(paneEl).autoWireText("bucket", { holdValue: true });
|
||||||
new Setting(paneEl).autoWireText("bucketPrefix", {
|
new Setting(paneEl).autoWireText("bucketPrefix", {
|
||||||
holdValue: true,
|
holdValue: true,
|
||||||
placeHolder: "vaultname/",
|
placeHolder: "vaultname/",
|
||||||
});
|
});
|
||||||
|
|
||||||
new Setting(paneEl).autoWireToggle("useCustomRequestHandler", { holdValue: true });
|
new Setting(paneEl).autoWireToggle("useCustomRequestHandler", { holdValue: true });
|
||||||
new Setting(paneEl).autoWireTextArea("bucketCustomHeaders", {
|
new Setting(paneEl).autoWireTextArea("bucketCustomHeaders", {
|
||||||
holdValue: true,
|
holdValue: true,
|
||||||
placeHolder: "x-custom-header: value\n x-custom-header2: value2",
|
placeHolder: "x-custom-header: value\n x-custom-header2: value2",
|
||||||
});
|
});
|
||||||
new Setting(paneEl).setName($msg("obsidianLiveSyncSettingTab.nameTestConnection")).addButton((button) =>
|
new Setting(paneEl).setName($msg("obsidianLiveSyncSettingTab.nameTestConnection")).addButton((button) =>
|
||||||
|
button
|
||||||
|
.setButtonText($msg("obsidianLiveSyncSettingTab.btnTest"))
|
||||||
|
.setDisabled(false)
|
||||||
|
.onClick(async () => {
|
||||||
|
await this.testConnection(this.editingSettings);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
new Setting(paneEl)
|
||||||
|
.setName($msg("obsidianLiveSyncSettingTab.nameApplySettings"))
|
||||||
|
.setClass("wizardHidden")
|
||||||
|
.addApplyButton([
|
||||||
|
"remoteType",
|
||||||
|
"endpoint",
|
||||||
|
"region",
|
||||||
|
"accessKey",
|
||||||
|
"secretKey",
|
||||||
|
"bucket",
|
||||||
|
"useCustomRequestHandler",
|
||||||
|
"bucketCustomHeaders",
|
||||||
|
"bucketPrefix",
|
||||||
|
])
|
||||||
|
.addOnUpdate(this.onlyOnMinIO);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleCouchDB"), undefined, this.onlyOnCouchDB).then(
|
||||||
|
(paneEl) => {
|
||||||
|
if (this.plugin.$$isMobile()) {
|
||||||
|
this.createEl(
|
||||||
|
paneEl,
|
||||||
|
"div",
|
||||||
|
{
|
||||||
|
text: $msg("obsidianLiveSyncSettingTab.msgNonHTTPSWarning"),
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
visibleOnly(() => !this.editingSettings.couchDB_URI.startsWith("https://"))
|
||||||
|
).addClass("op-warn");
|
||||||
|
} else {
|
||||||
|
this.createEl(
|
||||||
|
paneEl,
|
||||||
|
"div",
|
||||||
|
{
|
||||||
|
text: $msg("obsidianLiveSyncSettingTab.msgNonHTTPSInfo"),
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
visibleOnly(() => !this.editingSettings.couchDB_URI.startsWith("https://"))
|
||||||
|
).addClass("op-warn-info");
|
||||||
|
}
|
||||||
|
|
||||||
|
new Setting(paneEl).autoWireText("couchDB_URI", {
|
||||||
|
holdValue: true,
|
||||||
|
onUpdate: this.enableOnlySyncDisabled,
|
||||||
|
});
|
||||||
|
new Setting(paneEl).autoWireToggle("useJWT", {
|
||||||
|
holdValue: true,
|
||||||
|
onUpdate: this.enableOnlySyncDisabled,
|
||||||
|
});
|
||||||
|
new Setting(paneEl).autoWireText("couchDB_USER", {
|
||||||
|
holdValue: true,
|
||||||
|
onUpdate: combineOnUpdate(
|
||||||
|
this.enableOnlySyncDisabled,
|
||||||
|
visibleOnly(() => !this.editingSettings.useJWT)
|
||||||
|
),
|
||||||
|
});
|
||||||
|
new Setting(paneEl).autoWireText("couchDB_PASSWORD", {
|
||||||
|
holdValue: true,
|
||||||
|
isPassword: true,
|
||||||
|
onUpdate: combineOnUpdate(
|
||||||
|
this.enableOnlySyncDisabled,
|
||||||
|
visibleOnly(() => !this.editingSettings.useJWT)
|
||||||
|
),
|
||||||
|
});
|
||||||
|
const algorithms = {
|
||||||
|
["HS256"]: "HS256",
|
||||||
|
["HS512"]: "HS512",
|
||||||
|
["ES256"]: "ES256",
|
||||||
|
["ES512"]: "ES512",
|
||||||
|
} as const;
|
||||||
|
new Setting(paneEl).autoWireDropDown("jwtAlgorithm", {
|
||||||
|
options: algorithms,
|
||||||
|
onUpdate: combineOnUpdate(
|
||||||
|
this.enableOnlySyncDisabled,
|
||||||
|
visibleOnly(() => this.editingSettings.useJWT)
|
||||||
|
),
|
||||||
|
});
|
||||||
|
new Setting(paneEl).autoWireTextArea("jwtKey", {
|
||||||
|
holdValue: true,
|
||||||
|
onUpdate: combineOnUpdate(
|
||||||
|
this.enableOnlySyncDisabled,
|
||||||
|
visibleOnly(() => this.editingSettings.useJWT)
|
||||||
|
),
|
||||||
|
});
|
||||||
|
// eslint-disable-next-line prefer-const
|
||||||
|
let generatedKeyDivEl: HTMLDivElement;
|
||||||
|
new Setting(paneEl)
|
||||||
|
.setDesc("Generate ES256 Keypair for testing")
|
||||||
|
.addButton((button) =>
|
||||||
|
button.setButtonText("Generate").onClick(async () => {
|
||||||
|
const crypto = await getWebCrypto();
|
||||||
|
const keyPair = await crypto.subtle.generateKey(
|
||||||
|
{ name: "ECDSA", namedCurve: "P-256" },
|
||||||
|
true,
|
||||||
|
["sign", "verify"]
|
||||||
|
);
|
||||||
|
const pubKey = await crypto.subtle.exportKey("spki", keyPair.publicKey);
|
||||||
|
const privateKey = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
|
||||||
|
const encodedPublicKey = await arrayBufferToBase64Single(pubKey);
|
||||||
|
const encodedPrivateKey = await arrayBufferToBase64Single(privateKey);
|
||||||
|
|
||||||
|
const privateKeyPem = `> -----BEGIN PRIVATE KEY-----\n> ${encodedPrivateKey}\n> -----END PRIVATE KEY-----`;
|
||||||
|
const publicKeyPem = `> -----BEGIN PUBLIC KEY-----\\n${encodedPublicKey}\\n-----END PUBLIC KEY-----`;
|
||||||
|
|
||||||
|
const title = $msg("Setting.GenerateKeyPair.Title");
|
||||||
|
const msg = $msg("Setting.GenerateKeyPair.Desc", {
|
||||||
|
public_key: publicKeyPem,
|
||||||
|
private_key: privateKeyPem,
|
||||||
|
});
|
||||||
|
await MarkdownRenderer.render(
|
||||||
|
this.plugin.app,
|
||||||
|
"## " + title + "\n\n" + msg,
|
||||||
|
generatedKeyDivEl,
|
||||||
|
"/",
|
||||||
|
this.plugin
|
||||||
|
);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.addOnUpdate(
|
||||||
|
combineOnUpdate(
|
||||||
|
this.enableOnlySyncDisabled,
|
||||||
|
visibleOnly(() => this.editingSettings.useJWT)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
generatedKeyDivEl = this.createEl(
|
||||||
|
paneEl,
|
||||||
|
"div",
|
||||||
|
{ text: "" },
|
||||||
|
(el) => { },
|
||||||
|
visibleOnly(() => this.editingSettings.useJWT)
|
||||||
|
);
|
||||||
|
|
||||||
|
new Setting(paneEl).autoWireText("jwtKid", {
|
||||||
|
holdValue: true,
|
||||||
|
onUpdate: combineOnUpdate(
|
||||||
|
this.enableOnlySyncDisabled,
|
||||||
|
visibleOnly(() => this.editingSettings.useJWT)
|
||||||
|
),
|
||||||
|
});
|
||||||
|
new Setting(paneEl).autoWireText("jwtSub", {
|
||||||
|
holdValue: true,
|
||||||
|
onUpdate: combineOnUpdate(
|
||||||
|
this.enableOnlySyncDisabled,
|
||||||
|
visibleOnly(() => this.editingSettings.useJWT)
|
||||||
|
),
|
||||||
|
});
|
||||||
|
new Setting(paneEl).autoWireNumeric("jwtExpDuration", {
|
||||||
|
holdValue: true,
|
||||||
|
onUpdate: combineOnUpdate(
|
||||||
|
this.enableOnlySyncDisabled,
|
||||||
|
visibleOnly(() => this.editingSettings.useJWT)
|
||||||
|
),
|
||||||
|
});
|
||||||
|
new Setting(paneEl).autoWireText("couchDB_DBNAME", {
|
||||||
|
holdValue: true,
|
||||||
|
onUpdate: this.enableOnlySyncDisabled,
|
||||||
|
});
|
||||||
|
new Setting(paneEl).autoWireTextArea("couchDB_CustomHeaders", { holdValue: true });
|
||||||
|
new Setting(paneEl).autoWireToggle("useRequestAPI", {
|
||||||
|
holdValue: true,
|
||||||
|
onUpdate: this.enableOnlySyncDisabled,
|
||||||
|
});
|
||||||
|
new Setting(paneEl)
|
||||||
|
.setName($msg("obsidianLiveSyncSettingTab.nameTestDatabaseConnection"))
|
||||||
|
.setClass("wizardHidden")
|
||||||
|
.setDesc($msg("obsidianLiveSyncSettingTab.descTestDatabaseConnection"))
|
||||||
|
.addButton((button) =>
|
||||||
button
|
button
|
||||||
.setButtonText($msg("obsidianLiveSyncSettingTab.btnTest"))
|
.setButtonText($msg("obsidianLiveSyncSettingTab.btnTest"))
|
||||||
.setDisabled(false)
|
.setDisabled(false)
|
||||||
.onClick(async () => {
|
.onClick(async () => {
|
||||||
await this.testConnection(this.editingSettings);
|
await this.testConnection();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
new Setting(paneEl)
|
|
||||||
.setName($msg("obsidianLiveSyncSettingTab.nameApplySettings"))
|
|
||||||
.setClass("wizardHidden")
|
|
||||||
.addApplyButton([
|
|
||||||
"remoteType",
|
|
||||||
"endpoint",
|
|
||||||
"region",
|
|
||||||
"accessKey",
|
|
||||||
"secretKey",
|
|
||||||
"bucket",
|
|
||||||
"useCustomRequestHandler",
|
|
||||||
"bucketCustomHeaders",
|
|
||||||
"bucketPrefix",
|
|
||||||
])
|
|
||||||
.addOnUpdate(this.onlyOnMinIO);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleCouchDB"), undefined, this.onlyOnCouchDB).then(
|
new Setting(paneEl)
|
||||||
(paneEl) => {
|
.setName($msg("obsidianLiveSyncSettingTab.nameValidateDatabaseConfig"))
|
||||||
if (this.plugin.$$isMobile()) {
|
.setDesc($msg("obsidianLiveSyncSettingTab.descValidateDatabaseConfig"))
|
||||||
this.createEl(
|
.addButton((button) =>
|
||||||
paneEl,
|
button
|
||||||
"div",
|
.setButtonText($msg("obsidianLiveSyncSettingTab.btnCheck"))
|
||||||
{
|
.setDisabled(false)
|
||||||
text: $msg("obsidianLiveSyncSettingTab.msgNonHTTPSWarning"),
|
.onClick(async () => {
|
||||||
},
|
await checkConfig(checkResultDiv);
|
||||||
undefined,
|
|
||||||
visibleOnly(() => !this.editingSettings.couchDB_URI.startsWith("https://"))
|
|
||||||
).addClass("op-warn");
|
|
||||||
} else {
|
|
||||||
this.createEl(
|
|
||||||
paneEl,
|
|
||||||
"div",
|
|
||||||
{
|
|
||||||
text: $msg("obsidianLiveSyncSettingTab.msgNonHTTPSInfo"),
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
visibleOnly(() => !this.editingSettings.couchDB_URI.startsWith("https://"))
|
|
||||||
).addClass("op-warn-info");
|
|
||||||
}
|
|
||||||
|
|
||||||
new Setting(paneEl).autoWireText("couchDB_URI", {
|
|
||||||
holdValue: true,
|
|
||||||
onUpdate: this.enableOnlySyncDisabled,
|
|
||||||
});
|
|
||||||
new Setting(paneEl).autoWireToggle("useJWT", {
|
|
||||||
holdValue: true,
|
|
||||||
onUpdate: this.enableOnlySyncDisabled,
|
|
||||||
});
|
|
||||||
new Setting(paneEl).autoWireText("couchDB_USER", {
|
|
||||||
holdValue: true,
|
|
||||||
onUpdate: combineOnUpdate(
|
|
||||||
this.enableOnlySyncDisabled,
|
|
||||||
visibleOnly(() => !this.editingSettings.useJWT)
|
|
||||||
),
|
|
||||||
});
|
|
||||||
new Setting(paneEl).autoWireText("couchDB_PASSWORD", {
|
|
||||||
holdValue: true,
|
|
||||||
isPassword: true,
|
|
||||||
onUpdate: combineOnUpdate(
|
|
||||||
this.enableOnlySyncDisabled,
|
|
||||||
visibleOnly(() => !this.editingSettings.useJWT)
|
|
||||||
),
|
|
||||||
});
|
|
||||||
const algorithms = {
|
|
||||||
["HS256"]: "HS256",
|
|
||||||
["HS512"]: "HS512",
|
|
||||||
["ES256"]: "ES256",
|
|
||||||
["ES512"]: "ES512",
|
|
||||||
} as const;
|
|
||||||
new Setting(paneEl).autoWireDropDown("jwtAlgorithm", {
|
|
||||||
options: algorithms,
|
|
||||||
onUpdate: combineOnUpdate(
|
|
||||||
this.enableOnlySyncDisabled,
|
|
||||||
visibleOnly(() => this.editingSettings.useJWT)
|
|
||||||
),
|
|
||||||
});
|
|
||||||
new Setting(paneEl).autoWireTextArea("jwtKey", {
|
|
||||||
holdValue: true,
|
|
||||||
onUpdate: combineOnUpdate(
|
|
||||||
this.enableOnlySyncDisabled,
|
|
||||||
visibleOnly(() => this.editingSettings.useJWT)
|
|
||||||
),
|
|
||||||
});
|
|
||||||
// eslint-disable-next-line prefer-const
|
|
||||||
let generatedKeyDivEl: HTMLDivElement;
|
|
||||||
new Setting(paneEl)
|
|
||||||
.setDesc("Generate ES256 Keypair for testing")
|
|
||||||
.addButton((button) =>
|
|
||||||
button.setButtonText("Generate").onClick(async () => {
|
|
||||||
const crypto = await getWebCrypto();
|
|
||||||
const keyPair = await crypto.subtle.generateKey(
|
|
||||||
{ name: "ECDSA", namedCurve: "P-256" },
|
|
||||||
true,
|
|
||||||
["sign", "verify"]
|
|
||||||
);
|
|
||||||
const pubKey = await crypto.subtle.exportKey("spki", keyPair.publicKey);
|
|
||||||
const privateKey = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
|
|
||||||
const encodedPublicKey = await arrayBufferToBase64Single(pubKey);
|
|
||||||
const encodedPrivateKey = await arrayBufferToBase64Single(privateKey);
|
|
||||||
|
|
||||||
const privateKeyPem = `> -----BEGIN PRIVATE KEY-----\n> ${encodedPrivateKey}\n> -----END PRIVATE KEY-----`;
|
|
||||||
const publicKeyPem = `> -----BEGIN PUBLIC KEY-----\\n${encodedPublicKey}\\n-----END PUBLIC KEY-----`;
|
|
||||||
|
|
||||||
const title = $msg("Setting.GenerateKeyPair.Title");
|
|
||||||
const msg = $msg("Setting.GenerateKeyPair.Desc", {
|
|
||||||
public_key: publicKeyPem,
|
|
||||||
private_key: privateKeyPem,
|
|
||||||
});
|
|
||||||
await MarkdownRenderer.render(
|
|
||||||
this.plugin.app,
|
|
||||||
"## " + title + "\n\n" + msg,
|
|
||||||
generatedKeyDivEl,
|
|
||||||
"/",
|
|
||||||
this.plugin
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
)
|
|
||||||
.addOnUpdate(
|
|
||||||
combineOnUpdate(
|
|
||||||
this.enableOnlySyncDisabled,
|
|
||||||
visibleOnly(() => this.editingSettings.useJWT)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
generatedKeyDivEl = this.createEl(
|
|
||||||
paneEl,
|
|
||||||
"div",
|
|
||||||
{ text: "" },
|
|
||||||
(el) => {},
|
|
||||||
visibleOnly(() => this.editingSettings.useJWT)
|
|
||||||
);
|
);
|
||||||
|
checkResultDiv = this.createEl(paneEl, "div", {
|
||||||
|
text: "",
|
||||||
|
});
|
||||||
|
|
||||||
new Setting(paneEl).autoWireText("jwtKid", {
|
new Setting(paneEl)
|
||||||
holdValue: true,
|
.setName($msg("obsidianLiveSyncSettingTab.nameApplySettings"))
|
||||||
onUpdate: combineOnUpdate(
|
.setClass("wizardHidden")
|
||||||
this.enableOnlySyncDisabled,
|
.addApplyButton([
|
||||||
visibleOnly(() => this.editingSettings.useJWT)
|
"remoteType",
|
||||||
),
|
"couchDB_URI",
|
||||||
});
|
"couchDB_USER",
|
||||||
new Setting(paneEl).autoWireText("jwtSub", {
|
"couchDB_PASSWORD",
|
||||||
holdValue: true,
|
"couchDB_DBNAME",
|
||||||
onUpdate: combineOnUpdate(
|
"jwtAlgorithm",
|
||||||
this.enableOnlySyncDisabled,
|
"jwtExpDuration",
|
||||||
visibleOnly(() => this.editingSettings.useJWT)
|
"jwtKey",
|
||||||
),
|
"jwtSub",
|
||||||
});
|
"jwtKid",
|
||||||
new Setting(paneEl).autoWireNumeric("jwtExpDuration", {
|
"useJWT",
|
||||||
holdValue: true,
|
"couchDB_CustomHeaders",
|
||||||
onUpdate: combineOnUpdate(
|
"useRequestAPI",
|
||||||
this.enableOnlySyncDisabled,
|
])
|
||||||
visibleOnly(() => this.editingSettings.useJWT)
|
.addOnUpdate(this.onlyOnCouchDB);
|
||||||
),
|
}
|
||||||
});
|
);
|
||||||
new Setting(paneEl).autoWireText("couchDB_DBNAME", {
|
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleNotification"), () => { }, this.onlyOnCouchDB).then(
|
||||||
holdValue: true,
|
|
||||||
onUpdate: this.enableOnlySyncDisabled,
|
|
||||||
});
|
|
||||||
new Setting(paneEl).autoWireTextArea("couchDB_CustomHeaders", { holdValue: true });
|
|
||||||
new Setting(paneEl).autoWireToggle("useRequestAPI", {
|
|
||||||
holdValue: true,
|
|
||||||
onUpdate: this.enableOnlySyncDisabled,
|
|
||||||
});
|
|
||||||
new Setting(paneEl)
|
|
||||||
.setName($msg("obsidianLiveSyncSettingTab.nameTestDatabaseConnection"))
|
|
||||||
.setClass("wizardHidden")
|
|
||||||
.setDesc($msg("obsidianLiveSyncSettingTab.descTestDatabaseConnection"))
|
|
||||||
.addButton((button) =>
|
|
||||||
button
|
|
||||||
.setButtonText($msg("obsidianLiveSyncSettingTab.btnTest"))
|
|
||||||
.setDisabled(false)
|
|
||||||
.onClick(async () => {
|
|
||||||
await this.testConnection();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
new Setting(paneEl)
|
|
||||||
.setName($msg("obsidianLiveSyncSettingTab.nameValidateDatabaseConfig"))
|
|
||||||
.setDesc($msg("obsidianLiveSyncSettingTab.descValidateDatabaseConfig"))
|
|
||||||
.addButton((button) =>
|
|
||||||
button
|
|
||||||
.setButtonText($msg("obsidianLiveSyncSettingTab.btnCheck"))
|
|
||||||
.setDisabled(false)
|
|
||||||
.onClick(async () => {
|
|
||||||
await checkConfig(checkResultDiv);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
checkResultDiv = this.createEl(paneEl, "div", {
|
|
||||||
text: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
new Setting(paneEl)
|
|
||||||
.setName($msg("obsidianLiveSyncSettingTab.nameApplySettings"))
|
|
||||||
.setClass("wizardHidden")
|
|
||||||
.addApplyButton([
|
|
||||||
"remoteType",
|
|
||||||
"couchDB_URI",
|
|
||||||
"couchDB_USER",
|
|
||||||
"couchDB_PASSWORD",
|
|
||||||
"couchDB_DBNAME",
|
|
||||||
"jwtAlgorithm",
|
|
||||||
"jwtExpDuration",
|
|
||||||
"jwtKey",
|
|
||||||
"jwtSub",
|
|
||||||
"jwtKid",
|
|
||||||
"useJWT",
|
|
||||||
"couchDB_CustomHeaders",
|
|
||||||
"useRequestAPI",
|
|
||||||
])
|
|
||||||
.addOnUpdate(this.onlyOnCouchDB);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleNotification"), () => {}, this.onlyOnCouchDB).then(
|
|
||||||
(paneEl) => {
|
(paneEl) => {
|
||||||
paneEl.addClass("wizardHidden");
|
paneEl.addClass("wizardHidden");
|
||||||
new Setting(paneEl).autoWireNumeric("notifyThresholdOfRemoteStorageSize", {}).setClass("wizardHidden");
|
new Setting(paneEl).autoWireNumeric("notifyThresholdOfRemoteStorageSize", {}).setClass("wizardHidden");
|
||||||
|
|||||||
@@ -25,16 +25,16 @@ export function paneSyncSettings(
|
|||||||
const options: Record<string, string> =
|
const options: Record<string, string> =
|
||||||
this.editingSettings.remoteType == REMOTE_COUCHDB
|
this.editingSettings.remoteType == REMOTE_COUCHDB
|
||||||
? {
|
? {
|
||||||
NONE: "",
|
NONE: "",
|
||||||
LIVESYNC: $msg("obsidianLiveSyncSettingTab.optionLiveSync"),
|
LIVESYNC: $msg("obsidianLiveSyncSettingTab.optionLiveSync"),
|
||||||
PERIODIC: $msg("obsidianLiveSyncSettingTab.optionPeriodicWithBatch"),
|
PERIODIC: $msg("obsidianLiveSyncSettingTab.optionPeriodicWithBatch"),
|
||||||
DISABLE: $msg("obsidianLiveSyncSettingTab.optionDisableAllAutomatic"),
|
DISABLE: $msg("obsidianLiveSyncSettingTab.optionDisableAllAutomatic"),
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
NONE: "",
|
NONE: "",
|
||||||
PERIODIC: $msg("obsidianLiveSyncSettingTab.optionPeriodicWithBatch"),
|
PERIODIC: $msg("obsidianLiveSyncSettingTab.optionPeriodicWithBatch"),
|
||||||
DISABLE: $msg("obsidianLiveSyncSettingTab.optionDisableAllAutomatic"),
|
DISABLE: $msg("obsidianLiveSyncSettingTab.optionDisableAllAutomatic"),
|
||||||
};
|
};
|
||||||
|
|
||||||
new Setting(paneEl)
|
new Setting(paneEl)
|
||||||
.autoWireDropDown("preset", {
|
.autoWireDropDown("preset", {
|
||||||
@@ -144,14 +144,14 @@ export function paneSyncSettings(
|
|||||||
const optionsSyncMode =
|
const optionsSyncMode =
|
||||||
this.editingSettings.remoteType == REMOTE_COUCHDB
|
this.editingSettings.remoteType == REMOTE_COUCHDB
|
||||||
? {
|
? {
|
||||||
ONEVENTS: $msg("obsidianLiveSyncSettingTab.optionOnEvents"),
|
ONEVENTS: $msg("obsidianLiveSyncSettingTab.optionOnEvents"),
|
||||||
PERIODIC: $msg("obsidianLiveSyncSettingTab.optionPeriodicAndEvents"),
|
PERIODIC: $msg("obsidianLiveSyncSettingTab.optionPeriodicAndEvents"),
|
||||||
LIVESYNC: $msg("obsidianLiveSyncSettingTab.optionLiveSync"),
|
LIVESYNC: $msg("obsidianLiveSyncSettingTab.optionLiveSync"),
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
ONEVENTS: $msg("obsidianLiveSyncSettingTab.optionOnEvents"),
|
ONEVENTS: $msg("obsidianLiveSyncSettingTab.optionOnEvents"),
|
||||||
PERIODIC: $msg("obsidianLiveSyncSettingTab.optionPeriodicAndEvents"),
|
PERIODIC: $msg("obsidianLiveSyncSettingTab.optionPeriodicAndEvents"),
|
||||||
};
|
};
|
||||||
|
|
||||||
new Setting(paneEl)
|
new Setting(paneEl)
|
||||||
.autoWireDropDown("syncMode", {
|
.autoWireDropDown("syncMode", {
|
||||||
|
|||||||
22
styles.css
22
styles.css
@@ -110,10 +110,10 @@
|
|||||||
div.sls-setting-menu-btn {
|
div.sls-setting-menu-btn {
|
||||||
color: var(--text-normal);
|
color: var(--text-normal);
|
||||||
background-color: var(--background-secondary-alt);
|
background-color: var(--background-secondary-alt);
|
||||||
border-radius: 4px 4px 0 0;
|
border-radius: 8px;
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-right: 12px;
|
margin-right: 2px;
|
||||||
font-family: "Inter", sans-serif;
|
font-family: "Inter", sans-serif;
|
||||||
outline: none;
|
outline: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@@ -140,9 +140,9 @@ div.sls-setting-menu-btn {
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
background-color: rgba(var(--background-primary), 0.3);
|
backdrop-filter: blur(15px);
|
||||||
backdrop-filter: blur(4px);
|
padding: 4px;
|
||||||
border-radius: 4px;
|
border-radius: 10px;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,13 +437,11 @@ div.workspace-leaf-content[data-type=bases] .livesync-status {
|
|||||||
|
|
||||||
.sls-setting-panel-title {
|
.sls-setting-panel-title {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
}
|
font-size: medium;
|
||||||
|
top: 2.5em;
|
||||||
.sls-setting-panel-title {
|
background-color: var(--background-secondary-alt);
|
||||||
top: 2em;
|
border-radius: 10px;
|
||||||
background-color: rgba(var(--background-primary), 0.3);
|
padding: 0.5em 1.0em;
|
||||||
backdrop-filter: blur(4px);
|
|
||||||
border-radius: 30%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sls-dialogue-note-wrapper {
|
.sls-dialogue-note-wrapper {
|
||||||
|
|||||||
Reference in New Issue
Block a user