Compare commits

...
11 Commits
Author SHA1 Message Date
fyears 92183e0fb6 bump to 0.3.25
Release A New Version / build (16.x) (push) Failing after 43s
2022-05-10 21:25:20 +08:00
fyears 28bd861c9e fix stat on Android, add operations to nan ctime mtime and undefined size 2022-05-10 21:15:30 +08:00
fyears 4e8bec9511 bump to 0.3.24
Release A New Version / build (16.x) (push) Failing after 33s
2022-05-04 00:23:31 +08:00
fyears c98d91ab60 make auth settings styles cleaner 2022-05-04 00:22:55 +08:00
fyears 8bd456b08e make settings styles much cleaner 2022-05-04 00:12:03 +08:00
fyears a5c25aecd0 normalize words 2022-05-03 23:00:03 +08:00
fyears 806438964c fix import export settings styles 2022-05-03 22:48:03 +08:00
fyears 069e993fb0 split chooser and basic settings 2022-05-03 22:45:23 +08:00
fyears 7c2a17c404 fix format 2022-05-03 22:43:53 +08:00
fyears f26e491922 bump to 0.3.23
Release A New Version / build (16.x) (push) Failing after 47s
2022-05-03 10:06:25 +08:00
fyears dbf80c3359 properly deal with cache-control for onedrive 2022-05-03 10:04:36 +08:00
12 changed files with 223 additions and 194 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"id": "remotely-save", "id": "remotely-save",
"name": "Remotely Save", "name": "Remotely Save",
"version": "0.3.22", "version": "0.3.25",
"minAppVersion": "0.13.21", "minAppVersion": "0.13.21",
"description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.", "description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.",
"author": "fyears", "author": "fyears",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "remotely-save", "name": "remotely-save",
"version": "0.3.22", "version": "0.3.25",
"description": "This is yet another sync plugin for Obsidian app.", "description": "This is yet another sync plugin for Obsidian app.",
"scripts": { "scripts": {
"dev2": "node esbuild.config.mjs", "dev2": "node esbuild.config.mjs",
+7 -5
View File
@@ -166,18 +166,20 @@ export const decryptBase64urlToString = async (
}; };
export const getSizeFromOrigToEnc = (x: number) => { export const getSizeFromOrigToEnc = (x: number) => {
if (x < 0 || !Number.isInteger(x)) { if (x < 0 || Number.isNaN(x) || !Number.isInteger(x)) {
throw Error(`x=${x} is not a valid size`); throw Error(`getSizeFromOrigToEnc: x=${x} is not a valid size`);
} }
return (Math.floor(x / 16) + 1) * 16 + 16; return (Math.floor(x / 16) + 1) * 16 + 16;
}; };
export const getSizeFromEncToOrig = (x: number) => { export const getSizeFromEncToOrig = (x: number) => {
if (x < 32 || !Number.isInteger(x)) { if (x < 32 || Number.isNaN(x) || !Number.isInteger(x)) {
throw Error(`${x} is not a valid size`); throw Error(`getSizeFromEncToOrig: ${x} is not a valid size`);
} }
if (x % 16 !== 0) { if (x % 16 !== 0) {
throw Error(`${x} is not a valid encrypted file size`); throw Error(
`getSizeFromEncToOrig: ${x} is not a valid encrypted file size`
);
} }
return { return {
minSize: ((x - 16) / 16 - 1) * 16, minSize: ((x - 16) / 16 - 1) * 16,
+2 -2
View File
@@ -5,7 +5,7 @@ import { requireApiVersion, TAbstractFile, TFile, TFolder } from "obsidian";
import { API_VER_STAT_FOLDER, SUPPORTED_SERVICES_TYPE } from "./baseTypes"; import { API_VER_STAT_FOLDER, SUPPORTED_SERVICES_TYPE } from "./baseTypes";
import type { SyncPlanType } from "./sync"; import type { SyncPlanType } from "./sync";
import { toText, unixTimeToStr } from "./misc"; import { statFix, toText, unixTimeToStr } from "./misc";
import { log } from "./moreOnLog"; import { log } from "./moreOnLog";
@@ -417,7 +417,7 @@ export const insertRenameRecordByVault = async (
if (requireApiVersion(API_VER_STAT_FOLDER)) { if (requireApiVersion(API_VER_STAT_FOLDER)) {
// TAbstractFile does not contain these info // TAbstractFile does not contain these info
// but from API_VER_STAT_FOLDER we can manually stat them by path. // but from API_VER_STAT_FOLDER we can manually stat them by path.
const s = await fileOrFolder.vault.adapter.stat(fileOrFolder.path); const s = await statFix(fileOrFolder.vault, fileOrFolder.path);
ctime = s.ctime; ctime = s.ctime;
mtime = s.mtime; mtime = s.mtime;
} }
+23 -4
View File
@@ -339,12 +339,9 @@ export const checkHasSpecialCharForDir = (x: string) => {
}; };
export const unixTimeToStr = (x: number | undefined | null) => { export const unixTimeToStr = (x: number | undefined | null) => {
if (x === undefined) { if (x === undefined || x === null || Number.isNaN(x)) {
return undefined; return undefined;
} }
if (x === null) {
return null;
}
return window.moment(x).format() as string; return window.moment(x).format() as string;
}; };
@@ -408,3 +405,25 @@ export const toText = (x: any) => {
return `${x}`; return `${x}`;
} }
}; };
/**
* On Android the stat has bugs for folders. So we need a fixed version.
* @param vault
* @param path
*/
export const statFix = async (vault: Vault, path: string) => {
const s = await vault.adapter.stat(path);
if (s.ctime === undefined || s.ctime === null || Number.isNaN(s.ctime)) {
s.ctime = undefined;
}
if (s.mtime === undefined || s.mtime === null || Number.isNaN(s.mtime)) {
s.mtime = undefined;
}
if (
(s.size === undefined || s.size === null || Number.isNaN(s.size)) &&
s.type === "folder"
) {
s.size = 0;
}
return s;
};
+4 -2
View File
@@ -2,6 +2,7 @@ import { Vault, Stat, ListedFiles } from "obsidian";
import { Queue } from "@fyears/tsqueue"; import { Queue } from "@fyears/tsqueue";
import chunk from "lodash/chunk"; import chunk from "lodash/chunk";
import flatten from "lodash/flatten"; import flatten from "lodash/flatten";
import { statFix } from "./misc";
export interface ObsConfigDirFileType { export interface ObsConfigDirFileType {
key: string; key: string;
@@ -12,7 +13,7 @@ export interface ObsConfigDirFileType {
} }
const isFolderToSkip = (x: string) => { const isFolderToSkip = (x: string) => {
let specialFolders = [".git", ".svn", "node_modules"]; let specialFolders = [".git", ".github", ".gitlab", ".svn", "node_modules"];
for (const iterator of specialFolders) { for (const iterator of specialFolders) {
if ( if (
x === iterator || x === iterator ||
@@ -75,7 +76,8 @@ export const listFilesInObsFolder = async (
const itemsToFetchChunks = chunk(itemsToFetch, CHUNK_SIZE); const itemsToFetchChunks = chunk(itemsToFetch, CHUNK_SIZE);
for (const singleChunk of itemsToFetchChunks) { for (const singleChunk of itemsToFetchChunks) {
const r = singleChunk.map(async (x) => { const r = singleChunk.map(async (x) => {
const statRes = await vault.adapter.stat(x); const statRes = await statFix(vault, x);
const isFolder = statRes.type === "folder"; const isFolder = statRes.type === "folder";
let children: ListedFiles = undefined; let children: ListedFiles = undefined;
if (isFolder) { if (isFolder) {
+2 -13
View File
@@ -461,7 +461,6 @@ export class WrappedOnedriveClient {
body: JSON.stringify(payload), body: JSON.stringify(payload),
headers: { headers: {
Authorization: `Bearer ${await this.authGetter.getAccessToken()}`, Authorization: `Bearer ${await this.authGetter.getAccessToken()}`,
"Cache-Control": "no-cache",
}, },
}) })
); );
@@ -478,7 +477,6 @@ export class WrappedOnedriveClient {
body: JSON.stringify(payload), body: JSON.stringify(payload),
headers: { headers: {
Authorization: `Bearer ${await this.authGetter.getAccessToken()}`, Authorization: `Bearer ${await this.authGetter.getAccessToken()}`,
"Cache-Control": "no-cache",
}, },
}) })
); );
@@ -493,7 +491,6 @@ export class WrappedOnedriveClient {
method: "DELETE", method: "DELETE",
headers: { headers: {
Authorization: `Bearer ${await this.authGetter.getAccessToken()}`, Authorization: `Bearer ${await this.authGetter.getAccessToken()}`,
"Cache-Control": "no-cache",
}, },
}); });
} else { } else {
@@ -501,7 +498,6 @@ export class WrappedOnedriveClient {
method: "DELETE", method: "DELETE",
headers: { headers: {
Authorization: `Bearer ${await this.authGetter.getAccessToken()}`, Authorization: `Bearer ${await this.authGetter.getAccessToken()}`,
"Cache-Control": "no-cache",
}, },
}); });
} }
@@ -522,7 +518,6 @@ export class WrappedOnedriveClient {
headers: { headers: {
"Content-Type": DEFAULT_CONTENT_TYPE, "Content-Type": DEFAULT_CONTENT_TYPE,
Authorization: `Bearer ${await this.authGetter.getAccessToken()}`, Authorization: `Bearer ${await this.authGetter.getAccessToken()}`,
"Cache-Control": "no-cache",
}, },
}); });
} else { } else {
@@ -532,7 +527,6 @@ export class WrappedOnedriveClient {
headers: { headers: {
"Content-Type": DEFAULT_CONTENT_TYPE, "Content-Type": DEFAULT_CONTENT_TYPE,
Authorization: `Bearer ${await this.authGetter.getAccessToken()}`, Authorization: `Bearer ${await this.authGetter.getAccessToken()}`,
"Cache-Control": "no-cache",
}, },
}); });
} }
@@ -826,13 +820,8 @@ const downloadFromRemoteRaw = async (
).arrayBuffer; ).arrayBuffer;
return content; return content;
} else { } else {
const content = await ( const content = await // cannot set no-cache here, will have cors error
await fetch(downloadUrl, { (await fetch(downloadUrl)).arrayBuffer();
headers: {
"Cache-Control": "no-cache",
},
})
).arrayBuffer();
return content; return content;
} }
}; };
+156 -156
View File
@@ -675,123 +675,12 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
containerEl.createEl("h1", { text: "Remotely Save" }); containerEl.createEl("h1", { text: "Remotely Save" });
////////////////////////////////////////////////// //////////////////////////////////////////////////
// below for general // below for service chooser (part 1/2)
//////////////////////////////////////////////////
const generalDiv = containerEl.createEl("div");
generalDiv.createEl("h2", { text: t("settings_general") });
const passwordDiv = generalDiv.createEl("div");
let newPassword = `${this.plugin.settings.password}`;
new Setting(passwordDiv)
.setName(t("settings_password"))
.setDesc(t("settings_password_desc"))
.addText((text) => {
wrapTextWithPasswordHide(text);
text
.setPlaceholder("")
.setValue(`${this.plugin.settings.password}`)
.onChange(async (value) => {
newPassword = value.trim();
});
})
.addButton(async (button) => {
button.setButtonText(t("confirm"));
button.onClick(async () => {
new PasswordModal(this.app, this.plugin, newPassword).open();
});
});
const scheduleDiv = generalDiv.createEl("div");
new Setting(scheduleDiv)
.setName(t("settings_autorun"))
.setDesc(t("settings_autorun_desc"))
.addDropdown((dropdown) => {
dropdown.addOption("-1", t("settings_autorun_notset"));
dropdown.addOption(`${1000 * 60 * 1}`, t("settings_autorun_1min"));
dropdown.addOption(`${1000 * 60 * 5}`, t("settings_autorun_5min"));
dropdown.addOption(`${1000 * 60 * 10}`, t("settings_autorun_10min"));
dropdown.addOption(`${1000 * 60 * 30}`, t("settings_autorun_30min"));
dropdown
.setValue(`${this.plugin.settings.autoRunEveryMilliseconds}`)
.onChange(async (val: string) => {
const realVal = parseInt(val);
this.plugin.settings.autoRunEveryMilliseconds = realVal;
await this.plugin.saveSettings();
if (
(realVal === undefined || realVal === null || realVal <= 0) &&
this.plugin.autoRunIntervalID !== undefined
) {
// clear
window.clearInterval(this.plugin.autoRunIntervalID);
this.plugin.autoRunIntervalID = undefined;
} else if (
realVal !== undefined &&
realVal !== null &&
realVal > 0
) {
const intervalID = window.setInterval(() => {
this.plugin.syncRun("auto");
}, realVal);
this.plugin.autoRunIntervalID = intervalID;
this.plugin.registerInterval(intervalID);
}
});
});
const runOnceStartUpDiv = generalDiv.createEl("div");
new Setting(runOnceStartUpDiv)
.setName(t("settings_runoncestartup"))
.setDesc(t("settings_runoncestartup_desc"))
.addDropdown((dropdown) => {
dropdown.addOption("-1", t("settings_runoncestartup_notset"));
dropdown.addOption(
`${1000 * 1 * 1}`,
t("settings_runoncestartup_1sec")
);
dropdown.addOption(
`${1000 * 10 * 1}`,
t("settings_runoncestartup_10sec")
);
dropdown.addOption(
`${1000 * 30 * 1}`,
t("settings_runoncestartup_30sec")
);
dropdown
.setValue(`${this.plugin.settings.initRunAfterMilliseconds}`)
.onChange(async (val: string) => {
const realVal = parseInt(val);
this.plugin.settings.initRunAfterMilliseconds = realVal;
await this.plugin.saveSettings();
});
});
const skipLargeFilesDiv = generalDiv.createEl("div");
new Setting(skipLargeFilesDiv)
.setName(t("settings_skiplargefiles"))
.setDesc(t("settings_skiplargefiles_desc"))
.addDropdown((dropdown) => {
dropdown.addOption("-1", t("settings_skiplargefiles_notset"));
const mbs = [1, 5, 10, 50, 100, 500, 1000];
for (const mb of mbs) {
dropdown.addOption(`${mb * 1000 * 1000}`, `${mb} MB`);
}
dropdown
.setValue(`${this.plugin.settings.skipSizeLargerThan}`)
.onChange(async (val) => {
this.plugin.settings.skipSizeLargerThan = parseInt(val);
await this.plugin.saveSettings();
});
});
//////////////////////////////////////////////////
// below for general chooser (part 1/2)
////////////////////////////////////////////////// //////////////////////////////////////////////////
// we need to create the div in advance of any other service divs // we need to create the div in advance of any other service divs
const serviceChooserDiv = generalDiv.createEl("div"); const serviceChooserDiv = containerEl.createDiv();
serviceChooserDiv.createEl("h2", { text: t("settings_chooseservice") });
////////////////////////////////////////////////// //////////////////////////////////////////////////
// below for s3 // below for s3
@@ -801,27 +690,29 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
s3Div.toggleClass("s3-hide", this.plugin.settings.serviceType !== "s3"); s3Div.toggleClass("s3-hide", this.plugin.settings.serviceType !== "s3");
s3Div.createEl("h2", { text: t("settings_s3") }); s3Div.createEl("h2", { text: t("settings_s3") });
const s3LongDescDiv = s3Div.createEl("div", { cls: "settings-long-desc" });
for (const c of [ for (const c of [
t("settings_s3_disclaimer1"), t("settings_s3_disclaimer1"),
t("settings_s3_disclaimer2"), t("settings_s3_disclaimer2"),
]) { ]) {
s3Div.createEl("p", { s3LongDescDiv.createEl("p", {
text: c, text: c,
cls: "s3-disclaimer", cls: "s3-disclaimer",
}); });
} }
if (!VALID_REQURL) { if (!VALID_REQURL) {
s3Div.createEl("p", { s3LongDescDiv.createEl("p", {
text: t("settings_s3_cors"), text: t("settings_s3_cors"),
}); });
} }
s3Div.createEl("p", { s3LongDescDiv.createEl("p", {
text: t("settings_s3_prod"), text: t("settings_s3_prod"),
}); });
const s3LinksUl = s3Div.createEl("div").createEl("ul"); const s3LinksUl = s3LongDescDiv.createEl("ul");
s3LinksUl.createEl("li").createEl("a", { s3LinksUl.createEl("li").createEl("a", {
href: "https://docs.aws.amazon.com/general/latest/gr/s3.html", href: "https://docs.aws.amazon.com/general/latest/gr/s3.html",
@@ -954,8 +845,7 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
}); });
} }
const partsConcurrencyDiv = s3Div.createEl("div"); new Setting(s3Div)
new Setting(partsConcurrencyDiv)
.setName(t("settings_s3_parts")) .setName(t("settings_s3_parts"))
.setDesc(t("settings_s3_parts_desc")) .setDesc(t("settings_s3_parts_desc"))
.addDropdown((dropdown) => { .addDropdown((dropdown) => {
@@ -1007,16 +897,20 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
this.plugin.settings.serviceType !== "dropbox" this.plugin.settings.serviceType !== "dropbox"
); );
dropboxDiv.createEl("h2", { text: t("settings_dropbox") }); dropboxDiv.createEl("h2", { text: t("settings_dropbox") });
const dropboxLongDescDiv = dropboxDiv.createEl("div", {
cls: "settings-long-desc",
});
for (const c of [ for (const c of [
t("settings_dropbox_disclaimer1"), t("settings_dropbox_disclaimer1"),
t("settings_dropbox_disclaimer2"), t("settings_dropbox_disclaimer2"),
]) { ]) {
dropboxDiv.createEl("p", { dropboxLongDescDiv.createEl("p", {
text: c, text: c,
cls: "dropbox-disclaimer", cls: "dropbox-disclaimer",
}); });
} }
dropboxDiv.createEl("p", { dropboxLongDescDiv.createEl("p", {
text: t("settings_dropbox_folder", { text: t("settings_dropbox_folder", {
pluginID: this.plugin.manifest.id, pluginID: this.plugin.manifest.id,
remoteBaseDir: remoteBaseDir:
@@ -1027,10 +921,10 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
const dropboxSelectAuthDiv = dropboxDiv.createDiv(); const dropboxSelectAuthDiv = dropboxDiv.createDiv();
const dropboxAuthDiv = dropboxSelectAuthDiv.createDiv({ const dropboxAuthDiv = dropboxSelectAuthDiv.createDiv({
cls: "dropbox-auth-button-hide", cls: "dropbox-auth-button-hide settings-auth-related",
}); });
const dropboxRevokeAuthDiv = dropboxSelectAuthDiv.createDiv({ const dropboxRevokeAuthDiv = dropboxSelectAuthDiv.createDiv({
cls: "dropbox-revoke-auth-button-hide", cls: "dropbox-revoke-auth-button-hide settings-auth-related",
}); });
const dropboxRevokeAuthSetting = new Setting(dropboxRevokeAuthDiv) const dropboxRevokeAuthSetting = new Setting(dropboxRevokeAuthDiv)
@@ -1193,17 +1087,20 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
this.plugin.settings.serviceType !== "onedrive" this.plugin.settings.serviceType !== "onedrive"
); );
onedriveDiv.createEl("h2", { text: t("settings_onedrive") }); onedriveDiv.createEl("h2", { text: t("settings_onedrive") });
const onedriveLongDescDiv = onedriveDiv.createEl("div", {
cls: "settings-long-desc",
});
for (const c of [ for (const c of [
t("settings_onedrive_disclaimer1"), t("settings_onedrive_disclaimer1"),
t("settings_onedrive_disclaimer2"), t("settings_onedrive_disclaimer2"),
]) { ]) {
onedriveDiv.createEl("p", { onedriveLongDescDiv.createEl("p", {
text: c, text: c,
cls: "onedrive-disclaimer", cls: "onedrive-disclaimer",
}); });
} }
onedriveDiv.createEl("p", { onedriveLongDescDiv.createEl("p", {
text: t("settings_onedrive_folder", { text: t("settings_onedrive_folder", {
pluginID: this.plugin.manifest.id, pluginID: this.plugin.manifest.id,
remoteBaseDir: remoteBaseDir:
@@ -1212,16 +1109,16 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
}), }),
}); });
onedriveDiv.createEl("p", { onedriveLongDescDiv.createEl("p", {
text: t("settings_onedrive_nobiz"), text: t("settings_onedrive_nobiz"),
}); });
const onedriveSelectAuthDiv = onedriveDiv.createDiv(); const onedriveSelectAuthDiv = onedriveDiv.createDiv();
const onedriveAuthDiv = onedriveSelectAuthDiv.createDiv({ const onedriveAuthDiv = onedriveSelectAuthDiv.createDiv({
cls: "onedrive-auth-button-hide", cls: "onedrive-auth-button-hide settings-auth-related",
}); });
const onedriveRevokeAuthDiv = onedriveSelectAuthDiv.createDiv({ const onedriveRevokeAuthDiv = onedriveSelectAuthDiv.createDiv({
cls: "onedrive-revoke-auth-button-hide", cls: "onedrive-revoke-auth-button-hide settings-auth-related",
}); });
const onedriveRevokeAuthSetting = new Setting(onedriveRevokeAuthDiv) const onedriveRevokeAuthSetting = new Setting(onedriveRevokeAuthDiv)
@@ -1341,22 +1238,26 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
webdavDiv.createEl("h2", { text: t("settings_webdav") }); webdavDiv.createEl("h2", { text: t("settings_webdav") });
webdavDiv.createEl("p", { const webdavLongDescDiv = webdavDiv.createEl("div", {
cls: "settings-long-desc",
});
webdavLongDescDiv.createEl("p", {
text: t("settings_webdav_disclaimer1"), text: t("settings_webdav_disclaimer1"),
cls: "webdav-disclaimer", cls: "webdav-disclaimer",
}); });
if (!VALID_REQURL) { if (!VALID_REQURL) {
webdavDiv.createEl("p", { webdavLongDescDiv.createEl("p", {
text: t("settings_webdav_cors_os"), text: t("settings_webdav_cors_os"),
}); });
webdavDiv.createEl("p", { webdavLongDescDiv.createEl("p", {
text: t("settings_webdav_cors"), text: t("settings_webdav_cors"),
}); });
} }
webdavDiv.createEl("p", { webdavLongDescDiv.createEl("p", {
text: t("settings_webdav_folder", { text: t("settings_webdav_folder", {
remoteBaseDir: remoteBaseDir:
this.plugin.settings.webdav.remoteBaseDir || this.app.vault.getName(), this.plugin.settings.webdav.remoteBaseDir || this.app.vault.getName(),
@@ -1588,6 +1489,113 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
}); });
}); });
//////////////////////////////////////////////////
// below for basic settings
//////////////////////////////////////////////////
const basicDiv = containerEl.createEl("div");
basicDiv.createEl("h2", { text: t("settings_basic") });
let newPassword = `${this.plugin.settings.password}`;
new Setting(basicDiv)
.setName(t("settings_password"))
.setDesc(t("settings_password_desc"))
.addText((text) => {
wrapTextWithPasswordHide(text);
text
.setPlaceholder("")
.setValue(`${this.plugin.settings.password}`)
.onChange(async (value) => {
newPassword = value.trim();
});
})
.addButton(async (button) => {
button.setButtonText(t("confirm"));
button.onClick(async () => {
new PasswordModal(this.app, this.plugin, newPassword).open();
});
});
new Setting(basicDiv)
.setName(t("settings_autorun"))
.setDesc(t("settings_autorun_desc"))
.addDropdown((dropdown) => {
dropdown.addOption("-1", t("settings_autorun_notset"));
dropdown.addOption(`${1000 * 60 * 1}`, t("settings_autorun_1min"));
dropdown.addOption(`${1000 * 60 * 5}`, t("settings_autorun_5min"));
dropdown.addOption(`${1000 * 60 * 10}`, t("settings_autorun_10min"));
dropdown.addOption(`${1000 * 60 * 30}`, t("settings_autorun_30min"));
dropdown
.setValue(`${this.plugin.settings.autoRunEveryMilliseconds}`)
.onChange(async (val: string) => {
const realVal = parseInt(val);
this.plugin.settings.autoRunEveryMilliseconds = realVal;
await this.plugin.saveSettings();
if (
(realVal === undefined || realVal === null || realVal <= 0) &&
this.plugin.autoRunIntervalID !== undefined
) {
// clear
window.clearInterval(this.plugin.autoRunIntervalID);
this.plugin.autoRunIntervalID = undefined;
} else if (
realVal !== undefined &&
realVal !== null &&
realVal > 0
) {
const intervalID = window.setInterval(() => {
this.plugin.syncRun("auto");
}, realVal);
this.plugin.autoRunIntervalID = intervalID;
this.plugin.registerInterval(intervalID);
}
});
});
new Setting(basicDiv)
.setName(t("settings_runoncestartup"))
.setDesc(t("settings_runoncestartup_desc"))
.addDropdown((dropdown) => {
dropdown.addOption("-1", t("settings_runoncestartup_notset"));
dropdown.addOption(
`${1000 * 1 * 1}`,
t("settings_runoncestartup_1sec")
);
dropdown.addOption(
`${1000 * 10 * 1}`,
t("settings_runoncestartup_10sec")
);
dropdown.addOption(
`${1000 * 30 * 1}`,
t("settings_runoncestartup_30sec")
);
dropdown
.setValue(`${this.plugin.settings.initRunAfterMilliseconds}`)
.onChange(async (val: string) => {
const realVal = parseInt(val);
this.plugin.settings.initRunAfterMilliseconds = realVal;
await this.plugin.saveSettings();
});
});
new Setting(basicDiv)
.setName(t("settings_skiplargefiles"))
.setDesc(t("settings_skiplargefiles_desc"))
.addDropdown((dropdown) => {
dropdown.addOption("-1", t("settings_skiplargefiles_notset"));
const mbs = [1, 5, 10, 50, 100, 500, 1000];
for (const mb of mbs) {
dropdown.addOption(`${mb * 1000 * 1000}`, `${mb} MB`);
}
dropdown
.setValue(`${this.plugin.settings.skipSizeLargerThan}`)
.onChange(async (val) => {
this.plugin.settings.skipSizeLargerThan = parseInt(val);
await this.plugin.saveSettings();
});
});
////////////////////////////////////////////////// //////////////////////////////////////////////////
// below for advanced settings // below for advanced settings
////////////////////////////////////////////////// //////////////////////////////////////////////////
@@ -1596,8 +1604,7 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
text: t("settings_adv"), text: t("settings_adv"),
}); });
const concurrencyDiv = advDiv.createEl("div"); new Setting(advDiv)
new Setting(concurrencyDiv)
.setName(t("settings_concurrency")) .setName(t("settings_concurrency"))
.setDesc(t("settings_concurrency_desc")) .setDesc(t("settings_concurrency_desc"))
.addDropdown((dropdown) => { .addDropdown((dropdown) => {
@@ -1618,8 +1625,7 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
}); });
}); });
const syncUnderscoreItemsDiv = advDiv.createEl("div"); new Setting(advDiv)
new Setting(syncUnderscoreItemsDiv)
.setName(t("settings_syncunderscore")) .setName(t("settings_syncunderscore"))
.setDesc(t("settings_syncunderscore_desc")) .setDesc(t("settings_syncunderscore_desc"))
.addDropdown((dropdown) => { .addDropdown((dropdown) => {
@@ -1635,8 +1641,7 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
}); });
}); });
const syncConfigDirDiv = advDiv.createEl("div"); new Setting(advDiv)
new Setting(syncConfigDirDiv)
.setName(t("settings_configdir")) .setName(t("settings_configdir"))
.setDesc( .setDesc(
t("settings_configdir_desc", { t("settings_configdir_desc", {
@@ -1700,8 +1705,7 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
const debugDiv = containerEl.createEl("div"); const debugDiv = containerEl.createEl("div");
debugDiv.createEl("h2", { text: t("settings_debug") }); debugDiv.createEl("h2", { text: t("settings_debug") });
const setConsoleLogLevelDiv = debugDiv.createDiv("div"); new Setting(debugDiv)
new Setting(setConsoleLogLevelDiv)
.setName(t("settings_debuglevel")) .setName(t("settings_debuglevel"))
.setDesc(t("settings_debuglevel_desc")) .setDesc(t("settings_debuglevel_desc"))
.addDropdown(async (dropdown) => { .addDropdown(async (dropdown) => {
@@ -1716,8 +1720,8 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
log.info(`the log level is changed to ${val}`); log.info(`the log level is changed to ${val}`);
}); });
}); });
const outputCurrSettingsDiv = debugDiv.createDiv("div");
new Setting(outputCurrSettingsDiv) new Setting(debugDiv)
.setName(t("settings_outputsettingsconsole")) .setName(t("settings_outputsettingsconsole"))
.setDesc(t("settings_outputsettingsconsole_desc")) .setDesc(t("settings_outputsettingsconsole_desc"))
.addButton(async (button) => { .addButton(async (button) => {
@@ -1728,8 +1732,8 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
new Notice(t("settings_outputsettingsconsole_notice")); new Notice(t("settings_outputsettingsconsole_notice"));
}); });
}); });
const syncPlanDiv = debugDiv.createEl("div");
new Setting(syncPlanDiv) new Setting(debugDiv)
.setName(t("settings_syncplans")) .setName(t("settings_syncplans"))
.setDesc(t("settings_syncplans_desc")) .setDesc(t("settings_syncplans_desc"))
.addButton(async (button) => { .addButton(async (button) => {
@@ -1756,7 +1760,7 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
new Notice(t("settings_syncplans_notice")); new Notice(t("settings_syncplans_notice"));
}); });
}); });
new Setting(syncPlanDiv) new Setting(debugDiv)
.setName(t("settings_delsyncplans")) .setName(t("settings_delsyncplans"))
.setDesc(t("settings_delsyncplans_desc")) .setDesc(t("settings_delsyncplans_desc"))
.addButton(async (button) => { .addButton(async (button) => {
@@ -1767,8 +1771,7 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
}); });
}); });
const logToDBDiv = debugDiv.createEl("div"); new Setting(debugDiv)
new Setting(logToDBDiv)
.setName(t("settings_logtodb")) .setName(t("settings_logtodb"))
.setDesc(t("settings_logtodb_desc")) .setDesc(t("settings_logtodb_desc"))
.addDropdown(async (dropdown) => { .addDropdown(async (dropdown) => {
@@ -1795,7 +1798,7 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
}); });
}); });
new Setting(logToDBDiv) new Setting(debugDiv)
.setName(t("settings_logtodbexport")) .setName(t("settings_logtodbexport"))
.setDesc( .setDesc(
t("settings_logtodbexport_desc", { t("settings_logtodbexport_desc", {
@@ -1814,7 +1817,7 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
}); });
}); });
new Setting(logToDBDiv) new Setting(debugDiv)
.setName(t("settings_logtodbclear")) .setName(t("settings_logtodbclear"))
.setDesc(t("settings_logtodbclear_desc")) .setDesc(t("settings_logtodbclear_desc"))
.addButton(async (button) => { .addButton(async (button) => {
@@ -1825,8 +1828,7 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
}); });
}); });
const syncMappingDiv = debugDiv.createEl("div"); new Setting(debugDiv)
new Setting(syncMappingDiv)
.setName(t("settings_delsyncmap")) .setName(t("settings_delsyncmap"))
.setDesc(t("settings_delsyncmap_desc")) .setDesc(t("settings_delsyncmap_desc"))
.addButton(async (button) => { .addButton(async (button) => {
@@ -1837,8 +1839,7 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
}); });
}); });
const outputCurrBasePathVaultIDDiv = debugDiv.createDiv("div"); new Setting(debugDiv)
new Setting(outputCurrBasePathVaultIDDiv)
.setName(t("settings_outputbasepathvaultid")) .setName(t("settings_outputbasepathvaultid"))
.setDesc(t("settings_outputbasepathvaultid_desc")) .setDesc(t("settings_outputbasepathvaultid_desc"))
.addButton(async (button) => { .addButton(async (button) => {
@@ -1849,8 +1850,7 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
}); });
}); });
const dbsResetDiv = debugDiv.createEl("div"); new Setting(debugDiv)
new Setting(dbsResetDiv)
.setName(t("settings_resetcache")) .setName(t("settings_resetcache"))
.setDesc(t("settings_resetcache_desc")) .setDesc(t("settings_resetcache_desc"))
.addButton(async (button) => { .addButton(async (button) => {
+20 -8
View File
@@ -37,6 +37,7 @@ import {
getParentFolder, getParentFolder,
atWhichLevel, atWhichLevel,
unixTimeToStr, unixTimeToStr,
statFix,
} from "./misc"; } from "./misc";
import { RemoteClient } from "./remote"; import { RemoteClient } from "./remote";
import { import {
@@ -336,7 +337,7 @@ const ensembleMixedStates = async (
// ignore // ignore
continue; continue;
} else if (entry instanceof TFile) { } else if (entry instanceof TFile) {
const mtimeLocal = Math.max(entry.stat.mtime || 0, entry.stat.ctime || 0); const mtimeLocal = Math.max(entry.stat.mtime ?? 0, entry.stat.ctime ?? 0);
r = { r = {
key: entry.path, key: entry.path,
existLocal: true, existLocal: true,
@@ -380,7 +381,10 @@ const ensembleMixedStates = async (
if (syncConfigDir && localConfigDirContents !== undefined) { if (syncConfigDir && localConfigDirContents !== undefined) {
for (const entry of localConfigDirContents) { for (const entry of localConfigDirContents) {
const key = entry.key; const key = entry.key;
const mtimeLocal = Math.max(entry.mtime, entry.ctime); let mtimeLocal = Math.max(entry.mtime ?? 0, entry.ctime ?? 0);
if (Number.isNaN(mtimeLocal) || mtimeLocal === 0) {
mtimeLocal = undefined;
}
const r: FileOrFolderMixedState = { const r: FileOrFolderMixedState = {
key: key, key: key,
existLocal: true, existLocal: true,
@@ -468,10 +472,13 @@ const ensembleMixedStates = async (
changeLocalMtimeUsingMapping: true, changeLocalMtimeUsingMapping: true,
}; };
if (results.hasOwnProperty(key)) { if (results.hasOwnProperty(key)) {
const mtimeLocal = Math.max( let mtimeLocal = Math.max(
r.mtimeLocal || 0, r.mtimeLocal ?? 0,
results[key].mtimeLocal || 0 results[key].mtimeLocal ?? 0
); );
if (Number.isNaN(mtimeLocal) || mtimeLocal === 0) {
mtimeLocal = undefined;
}
results[key].mtimeLocal = mtimeLocal; results[key].mtimeLocal = mtimeLocal;
results[key].mtimeLocalFmt = unixTimeToStr(mtimeLocal); results[key].mtimeLocalFmt = unixTimeToStr(mtimeLocal);
results[key].changeLocalMtimeUsingMapping = results[key].changeLocalMtimeUsingMapping =
@@ -838,9 +845,14 @@ const assignOperationToFolderInplace = async (
// if it was created after deletion, we should keep it as is // if it was created after deletion, we should keep it as is
if (requireApiVersion(API_VER_STAT_FOLDER)) { if (requireApiVersion(API_VER_STAT_FOLDER)) {
if (r.existLocal) { if (r.existLocal) {
const { ctime, mtime } = await vault.adapter.stat(r.key); const { ctime, mtime } = await statFix(vault, r.key);
const cmtime = Math.max(ctime, mtime); const cmtime = Math.max(ctime ?? 0, mtime ?? 0);
if (cmtime > 0 && cmtime >= deltimeLocal && cmtime >= deltimeRemote) { if (
!Number.isNaN(cmtime) &&
cmtime > 0 &&
cmtime >= deltimeLocal &&
cmtime >= deltimeRemote
) {
keptFolder.add(getParentFolder(r.key)); keptFolder.add(getParentFolder(r.key));
if (r.existLocal && r.existRemote) { if (r.existLocal && r.existRemote) {
r.decision = "skipFolder"; r.decision = "skipFolder";
+5
View File
@@ -8,6 +8,11 @@
font-weight: bold; font-weight: bold;
} }
.settings-auth-related {
border-top: 1px solid var(--background-modifier-border);
padding-top: 18px;
}
.s3-disclaimer { .s3-disclaimer {
font-weight: bold; font-weight: bold;
} }
+1 -1
View File
@@ -1,4 +1,4 @@
{ {
"0.3.2": "0.12.15", "0.3.2": "0.12.15",
"0.3.22": "0.13.21" "0.3.25": "0.13.21"
} }