fix folder sync
This commit is contained in:
parent
adacda7ee5
commit
9f67d41786
@ -2,13 +2,6 @@
|
|||||||
import AggregateError from "aggregate-error";
|
import AggregateError from "aggregate-error";
|
||||||
import PQueue from "p-queue";
|
import PQueue from "p-queue";
|
||||||
import XRegExp from "xregexp";
|
import XRegExp from "xregexp";
|
||||||
import { checkProRunnableAndFixInplace } from "../pro/src/account";
|
|
||||||
import { duplicateFile, isMergable, mergeFile } from "../pro/src/conflictLogic";
|
|
||||||
import {
|
|
||||||
clearFileContentHistoryByVaultAndProfile,
|
|
||||||
getFileContentHistoryByVaultAndProfile,
|
|
||||||
upsertFileContentHistoryByVaultAndProfile,
|
|
||||||
} from "../pro/src/localdb";
|
|
||||||
import type {
|
import type {
|
||||||
ConflictActionType,
|
ConflictActionType,
|
||||||
EmptyFolderCleanType,
|
EmptyFolderCleanType,
|
||||||
@ -18,21 +11,21 @@ import type {
|
|||||||
SUPPORTED_SERVICES_TYPE,
|
SUPPORTED_SERVICES_TYPE,
|
||||||
SyncDirectionType,
|
SyncDirectionType,
|
||||||
SyncTriggerSourceType,
|
SyncTriggerSourceType,
|
||||||
} from "./baseTypes";
|
} from "../../src/baseTypes";
|
||||||
import { copyFile, copyFileOrFolder, copyFolder } from "./copyLogic";
|
import { copyFile, copyFileOrFolder, copyFolder } from "../../src/copyLogic";
|
||||||
import type { FakeFs } from "./fsAll";
|
import type { FakeFs } from "../../src/fsAll";
|
||||||
import type { FakeFsEncrypt } from "./fsEncrypt";
|
import type { FakeFsEncrypt } from "../../src/fsEncrypt";
|
||||||
import {
|
import {
|
||||||
type InternalDBs,
|
type InternalDBs,
|
||||||
clearPrevSyncRecordByVaultAndProfile,
|
clearPrevSyncRecordByVaultAndProfile,
|
||||||
getAllPrevSyncRecordsByVaultAndProfile,
|
getAllPrevSyncRecordsByVaultAndProfile,
|
||||||
insertSyncPlanRecordByVault,
|
insertSyncPlanRecordByVault,
|
||||||
upsertPrevSyncRecordByVaultAndProfile,
|
upsertPrevSyncRecordByVaultAndProfile,
|
||||||
} from "./localdb";
|
} from "../../src/localdb";
|
||||||
import {
|
import {
|
||||||
DEFAULT_FILE_NAME_FOR_METADATAONREMOTE,
|
DEFAULT_FILE_NAME_FOR_METADATAONREMOTE,
|
||||||
DEFAULT_FILE_NAME_FOR_METADATAONREMOTE2,
|
DEFAULT_FILE_NAME_FOR_METADATAONREMOTE2,
|
||||||
} from "./metadataOnRemote";
|
} from "../../src/metadataOnRemote";
|
||||||
import {
|
import {
|
||||||
atWhichLevel,
|
atWhichLevel,
|
||||||
getParentFolder,
|
getParentFolder,
|
||||||
@ -40,8 +33,15 @@ import {
|
|||||||
isSpecialFolderNameToSkip,
|
isSpecialFolderNameToSkip,
|
||||||
roughSizeOfObject,
|
roughSizeOfObject,
|
||||||
unixTimeToStr,
|
unixTimeToStr,
|
||||||
} from "./misc";
|
} from "../../src/misc";
|
||||||
import type { Profiler } from "./profiler";
|
import type { Profiler } from "../../src/profiler";
|
||||||
|
import { checkProRunnableAndFixInplace } from "./account";
|
||||||
|
import { duplicateFile, isMergable, mergeFile } from "./conflictLogic";
|
||||||
|
import {
|
||||||
|
clearFileContentHistoryByVaultAndProfile,
|
||||||
|
getFileContentHistoryByVaultAndProfile,
|
||||||
|
upsertFileContentHistoryByVaultAndProfile,
|
||||||
|
} from "./localdb";
|
||||||
|
|
||||||
const copyEntityAndFixTimeFormat = (
|
const copyEntityAndFixTimeFormat = (
|
||||||
src: Entity,
|
src: Entity,
|
||||||
@ -291,7 +291,6 @@ const ensembleMixedEnties = async (
|
|||||||
*/
|
*/
|
||||||
const getSyncPlanInplace = async (
|
const getSyncPlanInplace = async (
|
||||||
mixedEntityMappings: Record<string, MixedEntity>,
|
mixedEntityMappings: Record<string, MixedEntity>,
|
||||||
howToCleanEmptyFolder: EmptyFolderCleanType,
|
|
||||||
skipSizeLargerThan: number,
|
skipSizeLargerThan: number,
|
||||||
conflictAction: ConflictActionType,
|
conflictAction: ConflictActionType,
|
||||||
syncDirection: SyncDirectionType,
|
syncDirection: SyncDirectionType,
|
||||||
@ -309,7 +308,6 @@ const getSyncPlanInplace = async (
|
|||||||
profiler?.insertSize("sizeof sortedKeys", sortedKeys);
|
profiler?.insertSize("sizeof sortedKeys", sortedKeys);
|
||||||
|
|
||||||
const keptFolder = new Set<string>();
|
const keptFolder = new Set<string>();
|
||||||
const mayDeleteFolder = new Set<string>();
|
|
||||||
|
|
||||||
for (let i = 0; i < sortedKeys.length; ++i) {
|
for (let i = 0; i < sortedKeys.length; ++i) {
|
||||||
if (i % 100 === 0) {
|
if (i % 100 === 0) {
|
||||||
@ -331,7 +329,6 @@ const getSyncPlanInplace = async (
|
|||||||
// parent should also be kept
|
// parent should also be kept
|
||||||
// console.debug(`${key} in keptFolder`)
|
// console.debug(`${key} in keptFolder`)
|
||||||
keptFolder.add(getParentFolder(key));
|
keptFolder.add(getParentFolder(key));
|
||||||
mayDeleteFolder.delete(getParentFolder(key));
|
|
||||||
// should fill the missing part
|
// should fill the missing part
|
||||||
if (local !== undefined && remote !== undefined) {
|
if (local !== undefined && remote !== undefined) {
|
||||||
mixedEntry.decisionBranch = 101;
|
mixedEntry.decisionBranch = 101;
|
||||||
@ -366,110 +363,102 @@ const getSyncPlanInplace = async (
|
|||||||
mixedEntry.change = true;
|
mixedEntry.change = true;
|
||||||
}
|
}
|
||||||
keptFolder.delete(key); // no need to save it in the Set later
|
keptFolder.delete(key); // no need to save it in the Set later
|
||||||
mayDeleteFolder.delete(key); // must ignore this
|
|
||||||
} else {
|
} else {
|
||||||
if (howToCleanEmptyFolder === "skip") {
|
if (local !== undefined && remote !== undefined) {
|
||||||
mixedEntry.decisionBranch = 105;
|
// both exist, do nothing
|
||||||
mixedEntry.decision = "folder_to_skip";
|
mixedEntry.decisionBranch = 121;
|
||||||
|
mixedEntry.decision = "folder_existed_both_then_do_nothing";
|
||||||
mixedEntry.change = false;
|
mixedEntry.change = false;
|
||||||
keptFolder.add(getParentFolder(key)); // we want to keep parent!
|
keptFolder.add(getParentFolder(key));
|
||||||
mayDeleteFolder.delete(getParentFolder(key)); // we don't want to delete parent!
|
} else if (local !== undefined && remote === undefined) {
|
||||||
} else if (howToCleanEmptyFolder === "clean_both") {
|
if (prevSync !== undefined) {
|
||||||
if (local !== undefined && remote !== undefined) {
|
// then the folder is deleted on remote
|
||||||
if (syncDirection === "bidirectional") {
|
if (syncDirection === "incremental_push_only") {
|
||||||
if (mayDeleteFolder.has(key)) {
|
mixedEntry.decisionBranch = 122;
|
||||||
// from 0.5.6 and on,
|
mixedEntry.decision = "folder_to_skip";
|
||||||
// we only delete the folders caused by file deletion
|
keptFolder.add(getParentFolder(key));
|
||||||
mixedEntry.decisionBranch = 106;
|
mixedEntry.change = false;
|
||||||
mixedEntry.decision = "folder_to_be_deleted_on_both";
|
} else if (syncDirection === "incremental_pull_only") {
|
||||||
mixedEntry.change = true;
|
mixedEntry.decisionBranch = 123;
|
||||||
mayDeleteFolder.add(getParentFolder(key));
|
|
||||||
mayDeleteFolder.delete(key); // good to remove now
|
|
||||||
} else {
|
|
||||||
mixedEntry.decisionBranch = 115;
|
|
||||||
mixedEntry.decision = "folder_existed_both_then_do_nothing";
|
|
||||||
mixedEntry.change = false;
|
|
||||||
keptFolder.add(getParentFolder(key)); // we want to keep parent!
|
|
||||||
mayDeleteFolder.delete(getParentFolder(key)); // we don't want to delete parent!
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// right now it does nothing because of "incremental"
|
|
||||||
// TODO: should we delete??
|
|
||||||
mixedEntry.decisionBranch = 109;
|
|
||||||
mixedEntry.decision = "folder_to_skip";
|
mixedEntry.decision = "folder_to_skip";
|
||||||
mixedEntry.change = false;
|
mixedEntry.change = false;
|
||||||
keptFolder.add(getParentFolder(key)); // we want to keep parent!
|
keptFolder.add(getParentFolder(key));
|
||||||
mayDeleteFolder.delete(getParentFolder(key)); // we don't want to delete parent!
|
|
||||||
}
|
|
||||||
} else if (local !== undefined && remote === undefined) {
|
|
||||||
if (syncDirection === "bidirectional") {
|
|
||||||
if (mayDeleteFolder.has(key)) {
|
|
||||||
// from 0.5.6 and on,
|
|
||||||
// we only delete the folders caused by file deletion
|
|
||||||
mixedEntry.decisionBranch = 110;
|
|
||||||
mixedEntry.decision = "folder_to_be_deleted_on_local";
|
|
||||||
mixedEntry.change = true;
|
|
||||||
mayDeleteFolder.add(getParentFolder(key));
|
|
||||||
mayDeleteFolder.delete(key); // good to remove now
|
|
||||||
} else {
|
|
||||||
// the folder might be created locally
|
|
||||||
// so we want to create it remotely as well.
|
|
||||||
mixedEntry.decisionBranch = 116;
|
|
||||||
mixedEntry.decision =
|
|
||||||
"folder_existed_local_then_also_create_remote";
|
|
||||||
mixedEntry.change = false;
|
|
||||||
keptFolder.add(getParentFolder(key)); // we want to keep parent!
|
|
||||||
mayDeleteFolder.delete(getParentFolder(key)); // we don't want to delete parent!
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// right now it does nothing because of "incremental"
|
// bidirectional
|
||||||
// TODO: should we delete??
|
mixedEntry.decisionBranch = 124;
|
||||||
mixedEntry.decisionBranch = 111;
|
mixedEntry.decision = "folder_to_be_deleted_on_local";
|
||||||
mixedEntry.decision = "folder_to_skip";
|
mixedEntry.change = true;
|
||||||
mixedEntry.change = false;
|
|
||||||
keptFolder.add(getParentFolder(key)); // we want to keep parent!
|
|
||||||
mayDeleteFolder.delete(getParentFolder(key)); // we don't want to delete parent!
|
|
||||||
}
|
|
||||||
} else if (local === undefined && remote !== undefined) {
|
|
||||||
if (syncDirection === "bidirectional") {
|
|
||||||
if (mayDeleteFolder.has(key)) {
|
|
||||||
// from 0.5.6 and on,
|
|
||||||
// we only delete the folders caused by file deletion
|
|
||||||
mixedEntry.decisionBranch = 112;
|
|
||||||
mixedEntry.decision = "folder_to_be_deleted_on_remote";
|
|
||||||
mixedEntry.change = true;
|
|
||||||
mayDeleteFolder.add(getParentFolder(key));
|
|
||||||
mayDeleteFolder.delete(key); // good to remove now
|
|
||||||
} else {
|
|
||||||
// the folder might be created remotely
|
|
||||||
// so we want to create it locally as well.
|
|
||||||
mixedEntry.decisionBranch = 117;
|
|
||||||
mixedEntry.decision =
|
|
||||||
"folder_existed_remote_then_also_create_local";
|
|
||||||
mixedEntry.change = false;
|
|
||||||
keptFolder.add(getParentFolder(key)); // we want to keep parent!
|
|
||||||
mayDeleteFolder.delete(getParentFolder(key)); // we don't want to delete parent!
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// right now it does nothing because of "incremental"
|
|
||||||
// TODO: should we delete??
|
|
||||||
mixedEntry.decisionBranch = 113;
|
|
||||||
mixedEntry.decision = "folder_to_skip";
|
|
||||||
mixedEntry.change = false;
|
|
||||||
keptFolder.add(getParentFolder(key)); // we want to keep parent!
|
|
||||||
mayDeleteFolder.delete(getParentFolder(key)); // we don't want to delete parent!
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// local === undefined && remote === undefined
|
// then the folder is created on local
|
||||||
// no folder to delete, do nothing
|
|
||||||
mixedEntry.decisionBranch = 114;
|
if (syncDirection === "incremental_push_only") {
|
||||||
mixedEntry.decision = "folder_to_skip";
|
mixedEntry.decisionBranch = 125;
|
||||||
mixedEntry.change = false;
|
mixedEntry.decision =
|
||||||
|
"folder_existed_local_then_also_create_remote";
|
||||||
|
mixedEntry.change = true;
|
||||||
|
keptFolder.add(getParentFolder(key));
|
||||||
|
} else if (syncDirection === "incremental_pull_only") {
|
||||||
|
mixedEntry.decisionBranch = 126;
|
||||||
|
mixedEntry.decision = "folder_to_skip";
|
||||||
|
mixedEntry.change = false;
|
||||||
|
keptFolder.add(getParentFolder(key));
|
||||||
|
} else {
|
||||||
|
// bidirectional
|
||||||
|
mixedEntry.decisionBranch = 127;
|
||||||
|
mixedEntry.decision =
|
||||||
|
"folder_existed_local_then_also_create_remote";
|
||||||
|
mixedEntry.change = true;
|
||||||
|
keptFolder.add(getParentFolder(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (local === undefined && remote !== undefined) {
|
||||||
|
if (prevSync !== undefined) {
|
||||||
|
// then the folder is deleted on local
|
||||||
|
if (syncDirection === "incremental_push_only") {
|
||||||
|
mixedEntry.decisionBranch = 128;
|
||||||
|
mixedEntry.decision = "folder_to_skip";
|
||||||
|
mixedEntry.change = false;
|
||||||
|
keptFolder.add(getParentFolder(key));
|
||||||
|
} else if (syncDirection === "incremental_pull_only") {
|
||||||
|
mixedEntry.decisionBranch = 129;
|
||||||
|
mixedEntry.decision = "folder_to_skip";
|
||||||
|
mixedEntry.change = false;
|
||||||
|
keptFolder.add(getParentFolder(key));
|
||||||
|
} else {
|
||||||
|
// bidirectional
|
||||||
|
mixedEntry.decisionBranch = 130;
|
||||||
|
mixedEntry.decision = "folder_to_be_deleted_on_remote";
|
||||||
|
mixedEntry.change = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// then the folder is created on remote
|
||||||
|
if (syncDirection === "incremental_push_only") {
|
||||||
|
mixedEntry.decisionBranch = 131;
|
||||||
|
mixedEntry.decision = "folder_to_skip";
|
||||||
|
mixedEntry.change = false;
|
||||||
|
keptFolder.add(getParentFolder(key));
|
||||||
|
} else if (syncDirection === "incremental_pull_only") {
|
||||||
|
mixedEntry.decisionBranch = 132;
|
||||||
|
mixedEntry.decision =
|
||||||
|
"folder_existed_remote_then_also_create_local";
|
||||||
|
mixedEntry.change = true;
|
||||||
|
keptFolder.add(getParentFolder(key));
|
||||||
|
} else {
|
||||||
|
// bidirectional
|
||||||
|
mixedEntry.decisionBranch = 133;
|
||||||
|
mixedEntry.decision =
|
||||||
|
"folder_existed_remote_then_also_create_local";
|
||||||
|
mixedEntry.change = true;
|
||||||
|
keptFolder.add(getParentFolder(key));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw Error(
|
// local === undefined && remote === undefined
|
||||||
`do not know how to deal with empty folder ${mixedEntry.key}`
|
// no folder to delete or create, do nothing
|
||||||
);
|
mixedEntry.decisionBranch = 134;
|
||||||
|
mixedEntry.decision = "folder_to_skip";
|
||||||
|
mixedEntry.change = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -712,7 +701,6 @@ const getSyncPlanInplace = async (
|
|||||||
mixedEntry.decisionBranch = 4;
|
mixedEntry.decisionBranch = 4;
|
||||||
mixedEntry.decision = "local_is_deleted_thus_also_delete_remote";
|
mixedEntry.decision = "local_is_deleted_thus_also_delete_remote";
|
||||||
mixedEntry.change = true;
|
mixedEntry.change = true;
|
||||||
mayDeleteFolder.add(getParentFolder(key));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if B is in the previous list and MODIFIED, B has been deleted by A but modified by B
|
// if B is in the previous list and MODIFIED, B has been deleted by A but modified by B
|
||||||
@ -780,7 +768,6 @@ const getSyncPlanInplace = async (
|
|||||||
mixedEntry.decisionBranch = 7;
|
mixedEntry.decisionBranch = 7;
|
||||||
mixedEntry.decision = "remote_is_deleted_thus_also_delete_local";
|
mixedEntry.decision = "remote_is_deleted_thus_also_delete_local";
|
||||||
mixedEntry.change = true;
|
mixedEntry.change = true;
|
||||||
mayDeleteFolder.add(getParentFolder(key));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if A is in the previous list and MODIFIED, A has been deleted by B but modified by A
|
// if A is in the previous list and MODIFIED, A has been deleted by B but modified by A
|
||||||
@ -826,9 +813,6 @@ const getSyncPlanInplace = async (
|
|||||||
|
|
||||||
keptFolder.delete("/");
|
keptFolder.delete("/");
|
||||||
keptFolder.delete("");
|
keptFolder.delete("");
|
||||||
mayDeleteFolder.delete("/");
|
|
||||||
mayDeleteFolder.delete("");
|
|
||||||
|
|
||||||
if (keptFolder.size > 0) {
|
if (keptFolder.size > 0) {
|
||||||
throw Error(`unexpectedly keptFolder no decisions: ${[...keptFolder]}`);
|
throw Error(`unexpectedly keptFolder no decisions: ${[...keptFolder]}`);
|
||||||
}
|
}
|
||||||
@ -1643,7 +1627,6 @@ export async function syncer(
|
|||||||
|
|
||||||
mixedEntityMappings = await getSyncPlanInplace(
|
mixedEntityMappings = await getSyncPlanInplace(
|
||||||
mixedEntityMappings,
|
mixedEntityMappings,
|
||||||
settings.howToCleanEmptyFolder ?? "clean_both",
|
|
||||||
settings.skipSizeLargerThan ?? -1,
|
settings.skipSizeLargerThan ?? -1,
|
||||||
settings.conflictAction ?? "keep_newer",
|
settings.conflictAction ?? "keep_newer",
|
||||||
settings.syncDirection ?? "bidirectional",
|
settings.syncDirection ?? "bidirectional",
|
||||||
@ -165,7 +165,6 @@ export interface RemotelySavePluginSettings {
|
|||||||
enableStatusBarInfo?: boolean;
|
enableStatusBarInfo?: boolean;
|
||||||
deleteToWhere?: "system" | "obsidian";
|
deleteToWhere?: "system" | "obsidian";
|
||||||
conflictAction?: ConflictActionType;
|
conflictAction?: ConflictActionType;
|
||||||
howToCleanEmptyFolder?: EmptyFolderCleanType;
|
|
||||||
|
|
||||||
protectModifyPercentage?: number;
|
protectModifyPercentage?: number;
|
||||||
syncDirection?: SyncDirectionType;
|
syncDirection?: SyncDirectionType;
|
||||||
@ -194,6 +193,11 @@ export interface RemotelySavePluginSettings {
|
|||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
logToDB?: boolean;
|
logToDB?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
howToCleanEmptyFolder?: EmptyFolderCleanType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const COMMAND_URI = "remotely-save";
|
export const COMMAND_URI = "remotely-save";
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import type { Vault } from "obsidian";
|
import type { Vault } from "obsidian";
|
||||||
|
|
||||||
|
import type { SyncPlanType } from "../pro/src/sync";
|
||||||
import {
|
import {
|
||||||
DEFAULT_DEBUG_FOLDER,
|
DEFAULT_DEBUG_FOLDER,
|
||||||
DEFAULT_PROFILER_RESULT_FILE_PREFIX,
|
DEFAULT_PROFILER_RESULT_FILE_PREFIX,
|
||||||
@ -11,7 +12,6 @@ import {
|
|||||||
} from "./localdb";
|
} from "./localdb";
|
||||||
import type { InternalDBs } from "./localdb";
|
import type { InternalDBs } from "./localdb";
|
||||||
import { mkdirpInVault } from "./misc";
|
import { mkdirpInVault } from "./misc";
|
||||||
import type { SyncPlanType } from "./sync";
|
|
||||||
|
|
||||||
const getSubsetOfSyncPlan = (x: string, onlyChange: boolean) => {
|
const getSubsetOfSyncPlan = (x: string, onlyChange: boolean) => {
|
||||||
if (!onlyChange) {
|
if (!onlyChange) {
|
||||||
|
|||||||
@ -6,9 +6,9 @@ ep2(localforage);
|
|||||||
export type LocalForage = typeof localforage;
|
export type LocalForage = typeof localforage;
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
|
|
||||||
|
import type { SyncPlanType } from "../pro/src/sync";
|
||||||
import type { Entity, SUPPORTED_SERVICES_TYPE } from "./baseTypes";
|
import type { Entity, SUPPORTED_SERVICES_TYPE } from "./baseTypes";
|
||||||
import { unixTimeToStr } from "./misc";
|
import { unixTimeToStr } from "./misc";
|
||||||
import type { SyncPlanType } from "./sync";
|
|
||||||
|
|
||||||
const DB_VERSION_NUMBER_IN_HISTORY = [20211114, 20220108, 20220326, 20240220];
|
const DB_VERSION_NUMBER_IN_HISTORY = [20211114, 20220108, 20220326, 20240220];
|
||||||
export const DEFAULT_DB_VERSION_NUMBER: number = 20240220;
|
export const DEFAULT_DB_VERSION_NUMBER: number = 20240220;
|
||||||
|
|||||||
@ -48,6 +48,7 @@ import {
|
|||||||
sendAuthReq as sendAuthReqYandexDisk,
|
sendAuthReq as sendAuthReqYandexDisk,
|
||||||
setConfigBySuccessfullAuthInplace as setConfigBySuccessfullAuthInplaceYandexDisk,
|
setConfigBySuccessfullAuthInplace as setConfigBySuccessfullAuthInplaceYandexDisk,
|
||||||
} from "../pro/src/fsYandexDisk";
|
} from "../pro/src/fsYandexDisk";
|
||||||
|
import { syncer } from "../pro/src/sync";
|
||||||
import type {
|
import type {
|
||||||
RemotelySavePluginSettings,
|
RemotelySavePluginSettings,
|
||||||
SyncTriggerSourceType,
|
SyncTriggerSourceType,
|
||||||
@ -93,7 +94,6 @@ import {
|
|||||||
import { changeMobileStatusBar } from "./misc";
|
import { changeMobileStatusBar } from "./misc";
|
||||||
import { DEFAULT_PROFILER_CONFIG, type Profiler } from "./profiler";
|
import { DEFAULT_PROFILER_CONFIG, type Profiler } from "./profiler";
|
||||||
import { RemotelySaveSettingTab } from "./settings";
|
import { RemotelySaveSettingTab } from "./settings";
|
||||||
import { syncer } from "./sync";
|
|
||||||
import { SyncAlgoV3Modal } from "./syncAlgoV3Notice";
|
import { SyncAlgoV3Modal } from "./syncAlgoV3Notice";
|
||||||
|
|
||||||
const DEFAULT_SETTINGS: RemotelySavePluginSettings = {
|
const DEFAULT_SETTINGS: RemotelySavePluginSettings = {
|
||||||
|
|||||||
@ -2250,24 +2250,6 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
new Setting(advDiv)
|
|
||||||
.setName(t("settings_cleanemptyfolder"))
|
|
||||||
.setDesc(t("settings_cleanemptyfolder_desc"))
|
|
||||||
.addDropdown((dropdown) => {
|
|
||||||
dropdown.addOption("skip", t("settings_cleanemptyfolder_skip"));
|
|
||||||
dropdown.addOption(
|
|
||||||
"clean_both",
|
|
||||||
t("settings_cleanemptyfolder_clean_both")
|
|
||||||
);
|
|
||||||
dropdown
|
|
||||||
.setValue(this.plugin.settings.howToCleanEmptyFolder ?? "clean_both")
|
|
||||||
.onChange(async (val) => {
|
|
||||||
this.plugin.settings.howToCleanEmptyFolder =
|
|
||||||
val as EmptyFolderCleanType;
|
|
||||||
await this.plugin.saveSettings();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const percentage1 = new Setting(advDiv)
|
const percentage1 = new Setting(advDiv)
|
||||||
.setName(t("settings_protectmodifypercentage"))
|
.setName(t("settings_protectmodifypercentage"))
|
||||||
.setDesc(t("settings_protectmodifypercentage_desc"));
|
.setDesc(t("settings_protectmodifypercentage_desc"));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user