sync v3 notice draft

This commit is contained in:
fyears 2024-02-24 08:41:43 +08:00
parent 10d22cb912
commit e341c4f780
6 changed files with 36 additions and 130 deletions

View File

@ -94,17 +94,22 @@ export interface RemotelySavePluginSettings {
autoRunEveryMilliseconds?: number; autoRunEveryMilliseconds?: number;
initRunAfterMilliseconds?: number; initRunAfterMilliseconds?: number;
syncOnSaveAfterMilliseconds?: number; syncOnSaveAfterMilliseconds?: number;
agreeToUploadExtraMetadata?: boolean;
concurrency?: number; concurrency?: number;
syncConfigDir?: boolean; syncConfigDir?: boolean;
syncUnderscoreItems?: boolean; syncUnderscoreItems?: boolean;
lang?: LangTypeAndAuto; lang?: LangTypeAndAuto;
agreeToUseSyncV3?: boolean;
skipSizeLargerThan?: number; skipSizeLargerThan?: number;
ignorePaths?: string[]; ignorePaths?: string[];
enableStatusBarInfo?: boolean; enableStatusBarInfo?: boolean;
deleteToWhere?: "system" | "obsidian"; deleteToWhere?: "system" | "obsidian";
/**
* @deprecated
*/
agreeToUploadExtraMetadata?: boolean;
/** /**
* @deprecated * @deprecated
*/ */
@ -131,32 +136,6 @@ export interface UriParams {
// 80 days // 80 days
export const OAUTH2_FORCE_EXPIRE_MILLISECONDS = 1000 * 60 * 60 * 24 * 80; export const OAUTH2_FORCE_EXPIRE_MILLISECONDS = 1000 * 60 * 60 * 24 * 80;
type DecisionTypeForFile =
| "skipUploading" // special, mtimeLocal === mtimeRemote
| "uploadLocalDelHistToRemote" // "delLocalIfExists && delRemoteIfExists && cleanLocalDelHist && uploadLocalDelHistToRemote"
| "keepRemoteDelHist" // "delLocalIfExists && delRemoteIfExists && cleanLocalDelHist && keepRemoteDelHist"
| "uploadLocalToRemote" // "skipLocal && uploadLocalToRemote && cleanLocalDelHist && cleanRemoteDelHist"
| "downloadRemoteToLocal"; // "downloadRemoteToLocal && skipRemote && cleanLocalDelHist && cleanRemoteDelHist"
type DecisionTypeForFileSize =
| "skipUploadingTooLarge"
| "skipDownloadingTooLarge"
| "skipUsingLocalDelTooLarge"
| "skipUsingRemoteDelTooLarge"
| "errorLocalTooLargeConflictRemote"
| "errorRemoteTooLargeConflictLocal";
type DecisionTypeForFolder =
| "createFolder"
| "uploadLocalDelHistToRemoteFolder"
| "keepRemoteDelHistFolder"
| "skipFolder";
export type DecisionType =
| DecisionTypeForFile
| DecisionTypeForFileSize
| DecisionTypeForFolder;
export type EmptyFolderCleanType = "skip" | "clean_both"; export type EmptyFolderCleanType = "skip" | "clean_both";
export type ConflictActionType = "keep_newer" | "keep_larger" | "rename_both"; export type ConflictActionType = "keep_newer" | "keep_larger" | "rename_both";
@ -233,7 +212,7 @@ export interface FileOrFolderMixedState {
sizeRemoteEnc?: number; sizeRemoteEnc?: number;
changeRemoteMtimeUsingMapping?: boolean; changeRemoteMtimeUsingMapping?: boolean;
changeLocalMtimeUsingMapping?: boolean; changeLocalMtimeUsingMapping?: boolean;
decision?: DecisionType; decision?: string; // old DecisionType is deleted, fallback to string
decisionBranch?: number; decisionBranch?: number;
syncDone?: "done"; syncDone?: "done";
remoteEncryptedKey?: string; remoteEncryptedKey?: string;

View File

@ -284,10 +284,8 @@
"settings_resetcache_desc": "Reset local internal caches/databases (for debugging purposes). You would want to reload the plugin after resetting this. This option will not empty the {s3, password...} settings.", "settings_resetcache_desc": "Reset local internal caches/databases (for debugging purposes). You would want to reload the plugin after resetting this. This option will not empty the {s3, password...} settings.",
"settings_resetcache_button": "Reset", "settings_resetcache_button": "Reset",
"settings_resetcache_notice": "Local internal cache/databases deleted. Please manually reload the plugin.", "settings_resetcache_notice": "Local internal cache/databases deleted. Please manually reload the plugin.",
"syncalgov2_title": "Remotely Save has a better sync algorithm", "syncalgov3_title": "Remotely Save has HUGE update on sync algorithm",
"syncalgov2_texts": "Welcome to use Remotely Save!\nFrom version 0.3.0, a new algorithm has been developed, but it needs uploading extra meta data files _remotely-save-metadata-on-remote.{json,bin} to YOUR configured cloud destinations, besides your notes.\nSo that, for example, the second device can know that what files/folders have been deleted on the first device by reading those files.\nIf you agree, plase click the button \"Agree\", and enjoy the plugin! AND PLEASE REMEMBER TO BACKUP YOUR VAULT FIRSTLY!\nIf you do not agree, you should stop using the current and later versions of Remotely Save. You could consider manually install the old version 0.2.14 which uses old algorithm and does not upload any extra meta data files. By clicking the \"Do Not Agree\" button, the plugin will unload itself, and you need to manually disable it in Obsidian settings.", "syncalgov3_texts": "Welcome to use Remotely Save!\nFrom this version, a new algorithm has been developed. If you agree, plase click the button \"Agree\", and enjoy the plugin! AND PLEASE REMEMBER TO BACKUP YOUR VAULT FIRSTLY!\nIf you do not agree, you should stop using the current and later versions of Remotely Save. By clicking the \"Do Not Agree\" button, the plugin will unload itself, and you need to manually disable it in Obsidian settings.",
"syncalgov2_button_agree": "Agree", "syncalgov3_button_agree": "Agree",
"syncalgov2_button_disagree": "Do Not Agree", "syncalgov3_button_disagree": "Do Not Agree"
"official_notice_2024_first_party": "Plugin Remotely-Save is back to the party and get a HUGE update!🎉🎉🎉 Try it yourself or see the release note on https://github.com/remotely-save/remotely-save/releases."
} }

View File

@ -284,10 +284,8 @@
"settings_resetcache_desc": "(出于调试原因)重设本地缓存和数据库。您需要在重设之后重新载入此插件。本重设不会删除 s3密码……等设定。", "settings_resetcache_desc": "(出于调试原因)重设本地缓存和数据库。您需要在重设之后重新载入此插件。本重设不会删除 s3密码……等设定。",
"settings_resetcache_button": "重设", "settings_resetcache_button": "重设",
"settings_resetcache_notice": "本地同步缓存和数据库已被删除。请手动重新载入此插件。", "settings_resetcache_notice": "本地同步缓存和数据库已被删除。请手动重新载入此插件。",
"syncalgov2_title": "Remotely Save 的同步算法得到优化", "syncalgov3_title": "Remotely Save 的同步算法重大优化",
"syncalgov2_texts": "欢迎使用 Remotely Save!\n从版本 0.3.0 开始,它带来了新的同步算法,但是,除了您的笔记之外,它还需要上传额外的带有元信息的文件 _remotely-save-metadata-on-remote.{json,bin} 到您的云服务目的地上。\n从而比如说通过读取这些信息另一台设备可以知道什么文件或文件夹在第一台设备上被删除了。\n如果您同意此策略请点击按钮 \"同意\"然后开始享用此插件且特别要注意使用插件之前请首先备份好您的库Vault\n如果您不同意此策略您应该停止使用此版本和之后版本的 Remotely Save。您可以考虑手动安装旧版 0.2.14,它使用旧的同步算法,并不上传额外元信息文件。点击 \"不同意\" 之后插件会自动停止运行unload然后您需要 Obsidian 设置里手动停用disable此插件。", "syncalgov3_texts": "欢迎使用 Remotely Save!\n从这个版本 0.3.0 开始,它带来了新的同步算法\n如果您同意使用请点击按钮 \"同意\"然后开始享用此插件且特别要注意使用插件之前请首先备份好您的库Vault\n如果您不同意此策略您应该停止使用此版本和之后版本的 Remotely Save。点击 \"不同意\" 之后插件会自动停止运行unload然后您需要 Obsidian 设置里手动停用disable此插件。",
"syncalgov2_button_agree": "同意", "syncalgov3_button_agree": "同意",
"syncalgov2_button_disagree": "不同意", "syncalgov3_button_disagree": "不同意"
"official_notice_2024_first_party": "插件 Remotely-Save 回来了,更新了一大堆功能!🎉🎉🎉请自行使用,或参阅更新文档: https://github.com/remotely-save/remotely-save/releases 。"
} }

View File

@ -284,9 +284,8 @@
"settings_resetcache_desc": "(出於除錯原因)重設本地快取和資料庫。您需要在重設之後重新載入此外掛。本重設不會刪除 s3密碼……等設定。", "settings_resetcache_desc": "(出於除錯原因)重設本地快取和資料庫。您需要在重設之後重新載入此外掛。本重設不會刪除 s3密碼……等設定。",
"settings_resetcache_button": "重設", "settings_resetcache_button": "重設",
"settings_resetcache_notice": "本地同步快取和資料庫已被刪除。請手動重新載入此外掛。", "settings_resetcache_notice": "本地同步快取和資料庫已被刪除。請手動重新載入此外掛。",
"syncalgov2_title": "Remotely Save 的同步演算法得到最佳化", "syncalgov3_title": "Remotely Save 的同步演算法重大最佳化",
"syncalgov2_texts": "歡迎使用 Remotely Save!\n從版本 0.3.0 開始,它帶來了新的同步演算法,但是,除了您的筆記之外,它還需要上傳額外的帶有元資訊的檔案 _remotely-save-metadata-on-remote.{json,bin} 到您的雲服務目的地上。\n從而比如說透過讀取這些資訊另一臺裝置可以知道什麼檔案或資料夾在第一臺裝置上被刪除了。\n如果您同意此策略請點選按鈕 \"同意\"然後開始享用此外掛且特別要注意使用外掛之前請首先備份好您的儲存庫Vault\n如果您不同意此策略您應該停止使用此版本和之後版本的 Remotely Save。您可以考慮手動安裝舊版 0.2.14,它使用舊的同步演算法,並不上傳額外元資訊檔案。點選 \"不同意\" 之後外掛會自動停止執行unload然後您需要 Obsidian 設定裡手動停用disable此外掛。", "syncalgov3_texts": "歡迎使用 Remotely Save!\n從這個版本 0.3.0 開始,它帶來了新的同步演算法\n如果您同意使用請點選按鈕 \"同意\"然後開始享用此外掛且特別要注意使用外掛之前請首先備份好您的庫Vault\n如果您不同意此策略您應該停止使用此版本和之後版本的 Remotely Save。點選 \"不同意\" 之後外掛會自動停止執行unload然後您需要 Obsidian 設定裡手動停用disable此外掛。",
"syncalgov2_button_agree": "同意", "syncalgov3_button_agree": "同意",
"syncalgov2_button_disagree": "不同意", "syncalgov3_button_disagree": "不同意"
"official_notice_2024_first_party": "外掛 Remotely-Save 回來了,更新了一大堆功能!🎉🎉🎉請自行使用,或參閱更新文件: https://github.com/remotely-save/remotely-save/releases 。"
} }

View File

@ -15,7 +15,6 @@ import {
import cloneDeep from "lodash/cloneDeep"; import cloneDeep from "lodash/cloneDeep";
import { createElement, RotateCcw, RefreshCcw, FileText } from "lucide"; import { createElement, RotateCcw, RefreshCcw, FileText } from "lucide";
import type { import type {
FileOrFolderMixedState,
RemotelySavePluginSettings, RemotelySavePluginSettings,
SyncTriggerSourceType, SyncTriggerSourceType,
} from "./baseTypes"; } from "./baseTypes";
@ -29,10 +28,7 @@ import {
} from "./baseTypes"; } from "./baseTypes";
import { importQrCodeUri } from "./importExport"; import { importQrCodeUri } from "./importExport";
import { import {
insertDeleteRecordByVault,
insertRenameRecordByVault,
insertSyncPlanRecordByVault, insertSyncPlanRecordByVault,
loadFileHistoryTableByVault,
prepareDBs, prepareDBs,
InternalDBs, InternalDBs,
clearExpiredSyncPlanRecords, clearExpiredSyncPlanRecords,
@ -57,15 +53,15 @@ import {
import { DEFAULT_S3_CONFIG } from "./remoteForS3"; import { DEFAULT_S3_CONFIG } from "./remoteForS3";
import { DEFAULT_WEBDAV_CONFIG } from "./remoteForWebdav"; import { DEFAULT_WEBDAV_CONFIG } from "./remoteForWebdav";
import { RemotelySaveSettingTab } from "./settings"; import { RemotelySaveSettingTab } from "./settings";
import { fetchMetadataFile, parseRemoteItems, SyncStatusType } from "./sync"; import { parseRemoteItems, SyncStatusType } from "./sync";
import { doActualSync, getSyncPlan, isPasswordOk } from "./sync"; import { doActualSync, getSyncPlan, isPasswordOk } from "./sync";
import { messyConfigToNormal, normalConfigToMessy } from "./configPersist"; import { messyConfigToNormal, normalConfigToMessy } from "./configPersist";
import { ObsConfigDirFileType, listFilesInObsFolder } from "./obsFolderLister"; import { getLocalEntityList } from "./local";
import { I18n } from "./i18n"; import { I18n } from "./i18n";
import type { LangType, LangTypeAndAuto, TransItemType } from "./i18n"; import type { LangType, LangTypeAndAuto, TransItemType } from "./i18n";
import { DeletionOnRemote, MetadataOnRemote } from "./metadataOnRemote"; import { DeletionOnRemote, MetadataOnRemote } from "./metadataOnRemote";
import { SyncAlgoV2Modal } from "./syncAlgoV2Notice"; import { SyncAlgoV3Modal } from "./syncAlgoV3Notice";
import { applyLogWriterInplace, log } from "./moreOnLog"; import { applyLogWriterInplace, log } from "./moreOnLog";
import AggregateError from "aggregate-error"; import AggregateError from "aggregate-error";
@ -271,12 +267,6 @@ export default class RemotelySavePlugin extends Plugin {
client.serviceType, client.serviceType,
this.settings.password this.settings.password
); );
const origMetadataOnRemote = await fetchMetadataFile(
metadataFile,
client,
this.app.vault,
this.settings.password
);
if (this.settings.currLogLevel === "info") { if (this.settings.currLogLevel === "info") {
// pass // pass
@ -285,10 +275,6 @@ export default class RemotelySavePlugin extends Plugin {
} }
this.syncStatus = "getting_local_meta"; this.syncStatus = "getting_local_meta";
const local = this.app.vault.getAllLoadedFiles(); const local = this.app.vault.getAllLoadedFiles();
const localHistory = await loadFileHistoryTableByVault(
this.db,
this.vaultRandomID
);
let localConfigDirContents: ObsConfigDirFileType[] | undefined = let localConfigDirContents: ObsConfigDirFileType[] | undefined =
undefined; undefined;
if (this.settings.syncConfigDir) { if (this.settings.syncConfigDir) {
@ -345,21 +331,12 @@ export default class RemotelySavePlugin extends Plugin {
plan, plan,
sortedKeys, sortedKeys,
metadataFile, metadataFile,
origMetadataOnRemote,
sizesGoWrong, sizesGoWrong,
deletions, deletions,
(key: string) => self.trash(key), (key: string) => self.trash(key),
this.settings.password, this.settings.password,
this.settings.concurrency, this.settings.concurrency,
(ss: FileOrFolderMixedState[]) => {
new SizesConflictModal(
self.app,
self,
this.settings.skipSizeLargerThan ?? -1,
ss,
this.settings.password !== ""
).open();
},
(i: number, totalCount: number, pathName: string, decision: string) => (i: number, totalCount: number, pathName: string, decision: string) =>
self.setCurrSyncMsg(i, totalCount, pathName, decision) self.setCurrSyncMsg(i, totalCount, pathName, decision)
); );
@ -496,52 +473,6 @@ export default class RemotelySavePlugin extends Plugin {
this.syncStatus = "idle"; this.syncStatus = "idle";
this.registerEvent(
this.app.vault.on("delete", async (fileOrFolder) => {
await insertDeleteRecordByVault(
this.db,
fileOrFolder,
this.vaultRandomID
);
})
);
this.registerEvent(
this.app.vault.on("rename", async (fileOrFolder, oldPath) => {
await insertRenameRecordByVault(
this.db,
fileOrFolder,
oldPath,
this.vaultRandomID
);
})
);
function getMethods(obj: any) {
var result = [];
for (var id in obj) {
try {
if (typeof obj[id] == "function") {
result.push(id + ": " + obj[id].toString());
}
} catch (err) {
result.push(id + ": inaccessible");
}
}
return result.join("\n");
}
this.registerEvent(
this.app.vault.on("raw" as any, async (fileOrFolder) => {
// special track on .obsidian folder
const name = `${fileOrFolder}`;
if (name.startsWith(this.app.vault.configDir)) {
if (!(await this.app.vault.adapter.exists(name))) {
await insertDeleteRecordByVault(this.db, name, this.vaultRandomID);
}
}
})
);
this.registerObsidianProtocolHandler(COMMAND_URI, async (inputParams) => { this.registerObsidianProtocolHandler(COMMAND_URI, async (inputParams) => {
const parsed = importQrCodeUri(inputParams, this.app.vault.getName()); const parsed = importQrCodeUri(inputParams, this.app.vault.getName());
if (parsed.status === "error") { if (parsed.status === "error") {
@ -814,9 +745,9 @@ export default class RemotelySavePlugin extends Plugin {
// log.info("click", evt); // log.info("click", evt);
// }); // });
if (!this.settings.agreeToUploadExtraMetadata) { if (!this.settings.agreeToUseSyncV3) {
const syncAlgoV2Modal = new SyncAlgoV2Modal(this.app, this); const syncAlgoV3Modal = new SyncAlgoV3Modal(this.app, this);
syncAlgoV2Modal.open(); syncAlgoV3Modal.open();
} else { } else {
this.enableAutoSyncIfSet(); this.enableAutoSyncIfSet();
this.enableInitSyncIfSet(); this.enableInitSyncIfSet();
@ -829,9 +760,6 @@ export default class RemotelySavePlugin extends Plugin {
this.vaultRandomID, this.vaultRandomID,
this.manifest.version this.manifest.version
); );
if (compareVersion(REMOTELY_SAVE_VERSION_2024PREPARE, oldVersion) >= 0) {
new Notice(t("official_notice_2024_first_party"), 10 * 1000);
}
} }
async onunload() { async onunload() {
@ -918,6 +846,10 @@ export default class RemotelySavePlugin extends Plugin {
this.settings.s3.bypassCorsLocally = true; // deprecated as of 20240113 this.settings.s3.bypassCorsLocally = true; // deprecated as of 20240113
} }
if (this.settings.agreeToUseSyncV3 === undefined) {
this.settings.agreeToUseSyncV3 = false;
}
await this.saveSettings(); await this.saveSettings();
} }

View File

@ -4,7 +4,7 @@ import type { TransItemType } from "./i18n";
import { log } from "./moreOnLog"; import { log } from "./moreOnLog";
export class SyncAlgoV2Modal extends Modal { export class SyncAlgoV3Modal extends Modal {
agree: boolean; agree: boolean;
readonly plugin: RemotelySavePlugin; readonly plugin: RemotelySavePlugin;
constructor(app: App, plugin: RemotelySavePlugin) { constructor(app: App, plugin: RemotelySavePlugin) {
@ -19,11 +19,11 @@ export class SyncAlgoV2Modal extends Modal {
}; };
contentEl.createEl("h2", { contentEl.createEl("h2", {
text: t("syncalgov2_title"), text: t("syncalgov3_title"),
}); });
const ul = contentEl.createEl("ul"); const ul = contentEl.createEl("ul");
t("syncalgov2_texts") t("syncalgov3_texts")
.split("\n") .split("\n")
.forEach((val) => { .forEach((val) => {
ul.createEl("li", { ul.createEl("li", {
@ -33,14 +33,14 @@ export class SyncAlgoV2Modal extends Modal {
new Setting(contentEl) new Setting(contentEl)
.addButton((button) => { .addButton((button) => {
button.setButtonText(t("syncalgov2_button_agree")); button.setButtonText(t("syncalgov3_button_agree"));
button.onClick(async () => { button.onClick(async () => {
this.agree = true; this.agree = true;
this.close(); this.close();
}); });
}) })
.addButton((button) => { .addButton((button) => {
button.setButtonText(t("syncalgov2_button_disagree")); button.setButtonText(t("syncalgov3_button_disagree"));
button.onClick(() => { button.onClick(() => {
this.close(); this.close();
}); });