Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
581c6237cc | ||
|
|
257c995090 | ||
|
|
fd095a9093 | ||
|
|
acc9233611 | ||
|
|
4456db11cf | ||
|
|
54449dd207 | ||
|
|
822941f1c3 | ||
|
|
62b176d709 | ||
|
|
9553bff44a | ||
|
|
ede1f4e1bc | ||
|
|
97f4c0c427 | ||
|
|
94a56dabdd |
@@ -92,6 +92,7 @@ Additionally, the plugin author may occasionally visit Obsidian official forum a
|
||||
- If you decide to authorize this plugin to connect to OneDrive, please go to plugin's settings, and choose OneDrive then follow the instructions.
|
||||
- Password-based end-to-end encryption is also supported. But please be aware that **the vault name itself is not encrypted**.
|
||||
- If you want to sync the files across multiple devices, **your vault name should be the same** while using default settings.
|
||||
- You might also want to checkout [faq for OneDrive](./docs/remote_services/onedrive/README.md).
|
||||
|
||||
### webdav
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# OneDrive
|
||||
|
||||
- **This plugin is NOT an official Microsoft / OneDrive product.** The plugin just uses Microsoft's [OneDrive's public API](https://docs.microsoft.com/en-us/onedrive/developer/rest-api).
|
||||
- After the authorization, the plugin can read your name and email, and read and write files in your OneDrive's `/Apps/remotely-save` folder.
|
||||
- If you decide to authorize this plugin to connect to OneDrive, please go to plugin's settings, and choose OneDrive then follow the instructions.
|
||||
- Password-based end-to-end encryption is also supported. But please be aware that **the vault name itself is not encrypted**.
|
||||
- If you want to sync the files across multiple devices, **your vault name should be the same** while using default settings.
|
||||
|
||||
## FAQ
|
||||
|
||||
### How about OneDrive for Business?
|
||||
|
||||
This plugin only works for "OneDrive for personal", and not works for "OneDrive for Business" (yet). See [#11](https://github.com/fyears/remotely-save/issues/11) to further details.
|
||||
|
||||
### I cannot find `/Apps/remotely-save` folder
|
||||
|
||||
Mystically some users report that their OneDrive generate `/Application/Graph` instead of `/Apps/remotely-save`. See [#517](https://github.com/remotely-save/remotely-save/issues/517).
|
||||
|
||||
The solution is simple:
|
||||
|
||||
1. Backup your vault manually.
|
||||
2. Go to onedrive website (<https://onedrive.live.com/>), and rename `/Application/Graph` to `/Application/remotely-save` (right click on the folder and you will see rename option)
|
||||
3. Come back to Obsidian and try to sync!
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "remotely-save",
|
||||
"name": "Remotely Save",
|
||||
"version": "0.4.3",
|
||||
"version": "0.4.7",
|
||||
"minAppVersion": "0.13.21",
|
||||
"description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.",
|
||||
"author": "fyears",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "remotely-save",
|
||||
"version": "0.4.3",
|
||||
"version": "0.4.7",
|
||||
"description": "This is yet another sync plugin for Obsidian app.",
|
||||
"scripts": {
|
||||
"dev2": "node esbuild.config.mjs --watch",
|
||||
|
||||
@@ -115,6 +115,10 @@ export interface RemotelySavePluginSettings {
|
||||
protectModifyPercentage?: number;
|
||||
syncDirection?: SyncDirectionType;
|
||||
|
||||
obfuscateSettingFile?: boolean;
|
||||
|
||||
enableMobileStatusBar?: boolean;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
+13
-9
@@ -7,25 +7,25 @@
|
||||
"sometext": "Here are some texts.",
|
||||
"syncrun_alreadyrunning": "{{pluginName}} already running in stage {{syncStatus}}!",
|
||||
"syncrun_syncingribbon": "{{pluginName}}: syncing from {{triggerSource}}",
|
||||
"syncrun_step0": "0/8 Remotely Save running in dry mode, not actual file changes would happen.",
|
||||
"syncrun_step1": "1/8 Remotely Save Sync Preparing ({{serviceType}})",
|
||||
"syncrun_step0": "0/8 Remotely Save is running in dry mode, thus not actual file changes would happen.",
|
||||
"syncrun_step1": "1/8 Remotely Save is preparing ({{serviceType}})",
|
||||
"syncrun_step2": "2/8 Starting to fetch remote meta data.",
|
||||
"syncrun_step3": "3/8 Checking password correct or not.",
|
||||
"syncrun_passworderr": "Something goes wrong while checking password.",
|
||||
"syncrun_step4": "4/8 Starting to fetch local meta data.",
|
||||
"syncrun_step5": "5/8 Starting to fetch local prev sync data.",
|
||||
"syncrun_step6": "6/8 Starting to generate sync plan.",
|
||||
"syncrun_step7": "7/8 Remotely Save Sync data exchanging!",
|
||||
"syncrun_step7": "7/8 Remotely Save Sync data is exchanging!",
|
||||
"syncrun_step7skip": "7/8 Remotely Save real sync is skipped in dry run mode.",
|
||||
"syncrun_step8": "8/8 Remotely Save finish!",
|
||||
"syncrun_shortstep0": "0/2 Remotely Save running in dry mode, not actual file changes would happen.",
|
||||
"syncrun_shortstep1": "1/2 Remotely Save Sync Start Running ({{serviceType}})",
|
||||
"syncrun_step8": "8/8 Remotely Save finished!",
|
||||
"syncrun_shortstep0": "0/2 Remotely Save is running in dry mode, not actual file changes would happen.",
|
||||
"syncrun_shortstep1": "1/2 Remotely Save starts running ({{serviceType}})",
|
||||
"syncrun_shortstep2skip": "2/2 Remotely Save real sync is skipped in dry run mode.",
|
||||
"syncrun_shortstep2": "2/2 Remotely Save finish!",
|
||||
"syncrun_shortstep2": "2/2 Remotely Save finished!",
|
||||
"syncrun_abort": "{{manifestID}}-{{theDate}}: abort sync, triggerSource={{triggerSource}}, error while {{syncStatus}}",
|
||||
"syncrun_abort_protectmodifypercentage": "Abort! you set changing files >= {{protectModifyPercentage}}% is not allowed but {{realModifyDeleteCount}}/{{allFilesCount}}={{percent}}% is going to be modified or deleted! If you are sure you want this sync, please adjust the allowed ratio in the settings.",
|
||||
"protocol_saveqr": "New not-oauth2 settings for {{manifestName}} saved. Reopen the plugin Settings to the effect.",
|
||||
"protocol_callbacknotsupported": "Your uri call a callback that's not supported yet: {{params}}",
|
||||
"protocol_saveqr": "New not-oauth2 settings for {{manifestName}} is saved. Reopen the plugin settings to make it effective.",
|
||||
"protocol_callbacknotsupported": "Your uri calls a callback that's not supported yet: {{params}}",
|
||||
"protocol_dropbox_connecting": "Connecting to Dropbox...\nPlease DO NOT close this modal.",
|
||||
"protocol_dropbox_connect_succ": "Good! We've connected to Dropbox as user {{username}}!",
|
||||
"protocol_dropbox_connect_succ_revoke": "You've connected as user {{username}}. If you want to disconnect, click this button.",
|
||||
@@ -264,6 +264,8 @@
|
||||
"setting_syncdirection_bidirectional_desc": "Bidirectional (default)",
|
||||
"setting_syncdirection_incremental_push_only_desc": "Incremental Push Only (aka backup mode)",
|
||||
"setting_syncdirection_incremental_pull_only_desc": "Incremental Pull Only",
|
||||
"settings_enablemobilestatusbar": "Enable Mobile Status Bar Or Not",
|
||||
"settings_enablemobilestatusbar_desc": "By default Obsidian mobile hides status bar. But some users want to show it up. So here is a hack.",
|
||||
"settings_importexport": "Import and Export Partial Settings",
|
||||
"settings_export": "Export",
|
||||
"settings_export_desc": "Export not-oauth2 settings by generating a qrcode.",
|
||||
@@ -277,6 +279,8 @@
|
||||
"settings_outputsettingsconsole_desc": "The settings save on disk in encoded. Click this to see the decoded settings in console.",
|
||||
"settings_outputsettingsconsole_button": "Output",
|
||||
"settings_outputsettingsconsole_notice": "Finished outputing in console.",
|
||||
"settings_obfuscatesettingfile": "Obfuscate The Setting File Or Not",
|
||||
"settings_obfuscatesettingfile_desc": "The setting file (data.json) has some sensitive information. It's strongly recommended to obfuscate it to avoid unexpected read and modification. If you are sure to view and edit it manually, you can disable the obfuscation.",
|
||||
"settings_viewconsolelog": "View Console Log",
|
||||
"settings_viewconsolelog_desc": "On desktop, please press \"ctrl+shift+i\" or \"cmd+shift+i\" to view the log. On mobile, please install the third-party plugin <a href='https://obsidian.md/plugins?search=Logstravaganza'>Logstravaganza</a> to export the console log to a note.",
|
||||
"settings_syncplans": "Export Sync Plans",
|
||||
|
||||
@@ -264,6 +264,8 @@
|
||||
"setting_syncdirection_bidirectional_desc": "双向同步(默认)",
|
||||
"setting_syncdirection_incremental_push_only_desc": "只增量推送(也即:备份模式)",
|
||||
"setting_syncdirection_incremental_pull_only_desc": "只增量拉取",
|
||||
"settings_enablemobilestatusbar": "是否显示手机的状态栏",
|
||||
"settings_enablemobilestatusbar_desc": "Obsidian 手机版默认隐藏了状态栏。有些用户希望展示它。这里提供了设置选项。",
|
||||
"settings_importexport": "导入导出部分设置",
|
||||
"settings_export": "导出",
|
||||
"settings_export_desc": "用 QR 码导出非 oauth2 的设置信息。",
|
||||
@@ -277,6 +279,8 @@
|
||||
"settings_outputsettingsconsole_desc": "硬盘上的设置文件是编码过的,点击这里从而解码并输出到终端。",
|
||||
"settings_outputsettingsconsole_button": "输出",
|
||||
"settings_outputsettingsconsole_notice": "已输出到终端",
|
||||
"settings_obfuscatesettingfile": "是否混淆保存设置文件",
|
||||
"settings_obfuscatesettingfile_desc": "设置文件(data.json)含有敏感信息。强烈建议混淆后保存它,从而避免出乎意料的读取和修改。如果您确认要手动查看和修改它,可以关闭混淆保存。",
|
||||
"settings_viewconsolelog": "查看终端输出",
|
||||
"settings_viewconsolelog_desc": "电脑上,输入“ctrl+shift+i”或“cmd+shift+i”来查看终端输出。手机上,安装第三方插件 <a href='https://obsidian.md/plugins?search=Logstravaganza'>Logstravaganza</a> 来导出终端输出到一篇笔记上。",
|
||||
"settings_syncplans": "导出同步计划",
|
||||
|
||||
@@ -264,6 +264,8 @@
|
||||
"setting_syncdirection_bidirectional_desc": "雙向同步(預設)",
|
||||
"setting_syncdirection_incremental_push_only_desc": "只增量推送(也即:備份模式)",
|
||||
"setting_syncdirection_incremental_pull_only_desc": "只增量拉取",
|
||||
"settings_enablemobilestatusbar": "是否顯示手機的狀態列",
|
||||
"settings_enablemobilestatusbar_desc": "Obsidian 手機版預設隱藏了狀態列。有些使用者希望展示它。這裡提供了設定選項。",
|
||||
"settings_importexport": "匯入匯出部分設定",
|
||||
"settings_export": "匯出",
|
||||
"settings_export_desc": "用 QR 碼匯出非 oauth2 的設定資訊。",
|
||||
@@ -277,6 +279,8 @@
|
||||
"settings_outputsettingsconsole_desc": "硬碟上的設定檔案是編碼過的,點選這裡從而解碼並輸出到終端。",
|
||||
"settings_outputsettingsconsole_button": "輸出",
|
||||
"settings_outputsettingsconsole_notice": "已輸出到終端",
|
||||
"settings_obfuscatesettingfile": "是否混淆儲存設定檔案",
|
||||
"settings_obfuscatesettingfile_desc": "設定檔案(data.json)含有敏感資訊。強烈建議混淆後儲存它,從而避免出乎意料的讀取和修改。如果您確認要手動檢視和修改它,可以關閉混淆儲存。",
|
||||
"settings_viewconsolelog": "檢視終端輸出",
|
||||
"settings_viewconsolelog_desc": "電腦上,輸入“ctrl+shift+i”或“cmd+shift+i”來檢視終端輸出。手機上,安裝第三方外掛 <a href='https://obsidian.md/plugins?search=Logstravaganza'>Logstravaganza</a> 來匯出終端輸出到一篇筆記上。",
|
||||
"settings_syncplans": "匯出同步計劃",
|
||||
|
||||
+29
-3
@@ -66,7 +66,7 @@ import { SyncAlgoV3Modal } from "./syncAlgoV3Notice";
|
||||
|
||||
import AggregateError from "aggregate-error";
|
||||
import { exportVaultSyncPlansToFiles } from "./debugMode";
|
||||
import { compareVersion } from "./misc";
|
||||
import { changeMobileStatusBar, compareVersion } from "./misc";
|
||||
|
||||
const DEFAULT_SETTINGS: RemotelySavePluginSettings = {
|
||||
s3: DEFAULT_S3_CONFIG,
|
||||
@@ -95,6 +95,8 @@ const DEFAULT_SETTINGS: RemotelySavePluginSettings = {
|
||||
howToCleanEmptyFolder: "skip",
|
||||
protectModifyPercentage: 50,
|
||||
syncDirection: "bidirectional",
|
||||
obfuscateSettingFile: true,
|
||||
enableMobileStatusBar: false,
|
||||
};
|
||||
|
||||
interface OAuth2Info {
|
||||
@@ -721,8 +723,14 @@ export default class RemotelySavePlugin extends Plugin {
|
||||
async () => this.syncRun("manual")
|
||||
);
|
||||
|
||||
// Create Status Bar Item (not supported on mobile)
|
||||
if (!Platform.isMobileApp && this.settings.enableStatusBarInfo === true) {
|
||||
this.enableMobileStatusBarIfSet();
|
||||
|
||||
// Create Status Bar Item
|
||||
if (
|
||||
(!Platform.isMobile ||
|
||||
(Platform.isMobile && this.settings.enableMobileStatusBar)) &&
|
||||
this.settings.enableStatusBarInfo === true
|
||||
) {
|
||||
const statusBarItem = this.addStatusBarItem();
|
||||
this.statusBarElement = statusBarItem.createEl("span");
|
||||
this.statusBarElement.setAttribute("data-tooltip-position", "top");
|
||||
@@ -895,11 +903,23 @@ export default class RemotelySavePlugin extends Plugin {
|
||||
this.settings.syncDirection = "bidirectional";
|
||||
}
|
||||
|
||||
if (this.settings.obfuscateSettingFile === undefined) {
|
||||
this.settings.obfuscateSettingFile = true;
|
||||
}
|
||||
|
||||
if (this.settings.enableMobileStatusBar === undefined) {
|
||||
this.settings.enableMobileStatusBar = false;
|
||||
}
|
||||
|
||||
await this.saveSettings();
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
if (this.settings.obfuscateSettingFile) {
|
||||
await this.saveData(normalConfigToMessy(this.settings));
|
||||
} else {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1126,6 +1146,12 @@ export default class RemotelySavePlugin extends Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
enableMobileStatusBarIfSet() {
|
||||
if (Platform.isMobile && this.settings.enableMobileStatusBar) {
|
||||
changeMobileStatusBar("enable");
|
||||
}
|
||||
}
|
||||
|
||||
async saveAgreeToUseNewSyncAlgorithm() {
|
||||
this.settings.agreeToUseSyncV3 = true;
|
||||
await this.saveSettings();
|
||||
|
||||
+17
@@ -503,3 +503,20 @@ export const stringToFragment = (string: string) => {
|
||||
wrapper.innerHTML = string;
|
||||
return wrapper.content;
|
||||
};
|
||||
|
||||
/**
|
||||
* https://forum.obsidian.md/t/css-to-show-status-bar-on-mobile-devices/77185
|
||||
* @param op
|
||||
*/
|
||||
export const changeMobileStatusBar = (op: "enable" | "disable") => {
|
||||
const bar = document.querySelector(
|
||||
".is-mobile .app-container .status-bar"
|
||||
) as HTMLElement;
|
||||
if (op === "enable") {
|
||||
bar.style.setProperty("display", "flex");
|
||||
bar.style.setProperty("margin-bottom", "40px");
|
||||
} else {
|
||||
bar.style.removeProperty("display");
|
||||
bar.style.removeProperty("margin-bottom");
|
||||
}
|
||||
};
|
||||
|
||||
+52
-71
@@ -1,5 +1,5 @@
|
||||
import { Buffer } from "buffer";
|
||||
import { Vault, requestUrl } from "obsidian";
|
||||
import { Platform, Vault, requestUrl } from "obsidian";
|
||||
|
||||
import { Queue } from "@fyears/tsqueue";
|
||||
import chunk from "lodash/chunk";
|
||||
@@ -26,43 +26,70 @@ function onlyAscii(str: string) {
|
||||
return !/[^\u0000-\u00ff]/g.test(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* https://stackoverflow.com/questions/12539574/
|
||||
* @param obj
|
||||
* @returns
|
||||
*/
|
||||
function objKeyToLower(obj: Record<string, string>) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(obj).map(([k, v]) => [k.toLowerCase(), v])
|
||||
);
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
import { getPatcher } from "webdav/dist/web/index.js";
|
||||
if (VALID_REQURL) {
|
||||
getPatcher().patch(
|
||||
"request",
|
||||
async (options: RequestOptionsWithState): Promise<Response> => {
|
||||
const transformedHeaders = { ...options.headers };
|
||||
const transformedHeaders = objKeyToLower({ ...options.headers });
|
||||
delete transformedHeaders["host"];
|
||||
delete transformedHeaders["Host"];
|
||||
delete transformedHeaders["content-length"];
|
||||
delete transformedHeaders["Content-Length"];
|
||||
|
||||
const r = await requestUrl({
|
||||
const reqContentType =
|
||||
transformedHeaders["accept"] ?? transformedHeaders["content-type"];
|
||||
|
||||
console.debug(`before request:`);
|
||||
console.debug(`url: ${options.url}`);
|
||||
console.debug(`method: ${options.method}`);
|
||||
console.debug(`headers: ${JSON.stringify(transformedHeaders, null, 2)}`);
|
||||
console.debug(`reqContentType: ${reqContentType}`);
|
||||
|
||||
let r = await requestUrl({
|
||||
url: options.url,
|
||||
method: options.method,
|
||||
body: options.data as string | ArrayBuffer,
|
||||
headers: transformedHeaders,
|
||||
contentType: reqContentType,
|
||||
throw: false,
|
||||
});
|
||||
|
||||
let contentType: string | undefined =
|
||||
r.headers["Content-Type"] || r.headers["content-type"];
|
||||
if (options.headers !== undefined) {
|
||||
contentType =
|
||||
contentType ||
|
||||
options.headers["Content-Type"] ||
|
||||
options.headers["content-type"] ||
|
||||
options.headers["Accept"] ||
|
||||
options.headers["accept"];
|
||||
if (
|
||||
r.status === 401 &&
|
||||
Platform.isIosApp &&
|
||||
!options.url.endsWith("/") &&
|
||||
!options.url.endsWith(".md") &&
|
||||
options.method.toUpperCase() === "PROPFIND"
|
||||
) {
|
||||
// don't ask me why,
|
||||
// some webdav servers have some mysterious behaviours,
|
||||
// if a folder doesn't exist without slash, the servers return 401 instead of 404
|
||||
// here is a dirty hack that works
|
||||
console.debug(`so we have 401, try appending request url with slash`);
|
||||
r = await requestUrl({
|
||||
url: `${options.url}/`,
|
||||
method: options.method,
|
||||
body: options.data as string | ArrayBuffer,
|
||||
headers: transformedHeaders,
|
||||
contentType: reqContentType,
|
||||
throw: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (contentType !== undefined) {
|
||||
contentType = contentType.toLowerCase();
|
||||
}
|
||||
const rspHeaders = { ...r.headers };
|
||||
console.log("rspHeaders");
|
||||
console.log(rspHeaders);
|
||||
console.debug(`after request:`);
|
||||
const rspHeaders = objKeyToLower({ ...r.headers });
|
||||
console.debug(`rspHeaders: ${JSON.stringify(rspHeaders, null, 2)}`);
|
||||
for (let key in rspHeaders) {
|
||||
if (rspHeaders.hasOwnProperty(key)) {
|
||||
// avoid the error:
|
||||
@@ -79,74 +106,28 @@ if (VALID_REQURL) {
|
||||
// }
|
||||
// }
|
||||
if (!onlyAscii(rspHeaders[key])) {
|
||||
console.debug(`rspHeaders[key] needs encode: ${key}`);
|
||||
rspHeaders[key] = encodeURIComponent(rspHeaders[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// console.info(`requesting url=${options.url}`);
|
||||
// console.info(`contentType=${contentType}`);
|
||||
// console.info(`rspHeaders=${JSON.stringify(rspHeaders)}`)
|
||||
|
||||
// let r2: Response = undefined;
|
||||
// if (contentType.includes("xml")) {
|
||||
// r2 = new Response(r.text, {
|
||||
// status: r.status,
|
||||
// statusText: getReasonPhrase(r.status),
|
||||
// headers: rspHeaders,
|
||||
// });
|
||||
// } else if (
|
||||
// contentType.includes("json") ||
|
||||
// contentType.includes("javascript")
|
||||
// ) {
|
||||
// console.info('inside json branch');
|
||||
// // const j = r.json;
|
||||
// // console.info(j);
|
||||
// r2 = new Response(
|
||||
// r.text, // yea, here is the text because Response constructor expects a text
|
||||
// {
|
||||
// status: r.status,
|
||||
// statusText: getReasonPhrase(r.status),
|
||||
// headers: rspHeaders,
|
||||
// });
|
||||
// } else if (contentType.includes("text")) {
|
||||
// // avoid text/json,
|
||||
// // so we split this out from the above xml or json branch
|
||||
// r2 = new Response(r.text, {
|
||||
// status: r.status,
|
||||
// statusText: getReasonPhrase(r.status),
|
||||
// headers: rspHeaders,
|
||||
// });
|
||||
// } else if (
|
||||
// contentType.includes("octet-stream") ||
|
||||
// contentType.includes("binary") ||
|
||||
// contentType.includes("buffer")
|
||||
// ) {
|
||||
// // application/octet-stream
|
||||
// r2 = new Response(r.arrayBuffer, {
|
||||
// status: r.status,
|
||||
// statusText: getReasonPhrase(r.status),
|
||||
// headers: rspHeaders,
|
||||
// });
|
||||
// } else {
|
||||
// throw Error(
|
||||
// `do not know how to deal with requested content type = ${contentType}`
|
||||
// );
|
||||
// }
|
||||
|
||||
let r2: Response | undefined = undefined;
|
||||
const statusText = getReasonPhrase(r.status);
|
||||
console.debug(`statusText: ${statusText}`);
|
||||
if ([101, 103, 204, 205, 304].includes(r.status)) {
|
||||
// A null body status is a status that is 101, 103, 204, 205, or 304.
|
||||
// https://fetch.spec.whatwg.org/#statuses
|
||||
// fix this: Failed to construct 'Response': Response with null body status cannot have body
|
||||
r2 = new Response(null, {
|
||||
status: r.status,
|
||||
statusText: getReasonPhrase(r.status),
|
||||
statusText: statusText,
|
||||
headers: rspHeaders,
|
||||
});
|
||||
} else {
|
||||
r2 = new Response(r.arrayBuffer, {
|
||||
status: r.status,
|
||||
statusText: getReasonPhrase(r.status),
|
||||
statusText: statusText,
|
||||
headers: rspHeaders,
|
||||
});
|
||||
}
|
||||
|
||||
+59
-1
@@ -45,7 +45,11 @@ import {
|
||||
} from "./remoteForOnedrive";
|
||||
import { messyConfigToNormal } from "./configPersist";
|
||||
import type { TransItemType } from "./i18n";
|
||||
import { checkHasSpecialCharForDir, stringToFragment } from "./misc";
|
||||
import {
|
||||
changeMobileStatusBar,
|
||||
checkHasSpecialCharForDir,
|
||||
stringToFragment,
|
||||
} from "./misc";
|
||||
import { simpleTransRemotePrefix } from "./remoteForS3";
|
||||
|
||||
class PasswordModal extends Modal {
|
||||
@@ -2017,6 +2021,36 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
|
||||
});
|
||||
});
|
||||
|
||||
if (Platform.isMobile) {
|
||||
new Setting(advDiv)
|
||||
.setName(t("settings_enablemobilestatusbar"))
|
||||
.setDesc(t("settings_enablemobilestatusbar_desc"))
|
||||
.addDropdown(async (dropdown) => {
|
||||
dropdown
|
||||
.addOption("enable", t("enable"))
|
||||
.addOption("disable", t("disable"));
|
||||
|
||||
dropdown
|
||||
.setValue(
|
||||
`${
|
||||
this.plugin.settings.enableMobileStatusBar
|
||||
? "enable"
|
||||
: "disable"
|
||||
}`
|
||||
)
|
||||
.onChange(async (val) => {
|
||||
if (val === "enable") {
|
||||
this.plugin.settings.enableMobileStatusBar = true;
|
||||
changeMobileStatusBar("enable");
|
||||
} else {
|
||||
this.plugin.settings.enableMobileStatusBar = false;
|
||||
changeMobileStatusBar("disable");
|
||||
}
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// below for import and export functions
|
||||
//////////////////////////////////////////////////
|
||||
@@ -2075,6 +2109,30 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(debugDiv)
|
||||
.setName(t("settings_obfuscatesettingfile"))
|
||||
.setDesc(t("settings_obfuscatesettingfile_desc"))
|
||||
.addDropdown(async (dropdown) => {
|
||||
dropdown
|
||||
.addOption("enable", t("enable"))
|
||||
.addOption("disable", t("disable"));
|
||||
|
||||
dropdown
|
||||
.setValue(
|
||||
`${
|
||||
this.plugin.settings.obfuscateSettingFile ? "enable" : "disable"
|
||||
}`
|
||||
)
|
||||
.onChange(async (val) => {
|
||||
if (val === "enable") {
|
||||
this.plugin.settings.obfuscateSettingFile = true;
|
||||
} else {
|
||||
this.plugin.settings.obfuscateSettingFile = false;
|
||||
}
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(debugDiv)
|
||||
.setName(t("settings_viewconsolelog"))
|
||||
.setDesc(stringToFragment(t("settings_viewconsolelog_desc")));
|
||||
|
||||
@@ -491,6 +491,8 @@ export const ensembleMixedEnties = async (
|
||||
}
|
||||
}
|
||||
|
||||
console.debug("in the end of ensembleMixedEnties, finalMappings is:");
|
||||
console.debug(finalMappings);
|
||||
return finalMappings;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user