optimize sync status bar

This commit is contained in:
fyears 2024-06-17 00:15:33 +08:00
parent 57493f57cf
commit 35f5355c8e
7 changed files with 179 additions and 71 deletions

View File

@ -1417,6 +1417,7 @@ export const doActualSync = async (
db: InternalDBs,
profiler: Profiler | undefined,
conflictAction: ConflictActionType,
triggerSource: SyncTriggerSourceType,
callbackSyncProcess?: any
) => {
profiler?.addIndent();
@ -1524,13 +1525,16 @@ export const doActualSync = async (
// );
await callbackSyncProcess?.(
triggerSource,
realCounter,
realTotalCount,
key,
val.decision
);
realCounter += 1;
if (val.change === undefined || val.change) {
realCounter += 1;
}
await dispatchOperationToActualV3(
key,
@ -1743,6 +1747,7 @@ export async function syncer(
db,
profiler,
settings.conflictAction ?? "keep_newer",
triggerSource,
callbackSyncProcess
);
profiler?.insert(`finish step${step} (actual sync)`);

View File

@ -45,20 +45,26 @@
"command_exportlogsindb": "export logs saved in db",
"statusbar_time_years": "Synced {{time}} years ago",
"statusbar_time_months": "Synced {{time}} months ago",
"statusbar_time_weeks": "Synced {{time}} weeks ago",
"statusbar_time_days": "Synced {{time}} days ago",
"statusbar_time_hours": "Synced {{time}} hours ago",
"statusbar_time_minutes": "Synced {{time}} minutes ago",
"statusbar_time_lessminute": "Synced last minute ago",
"statusbar_lastsync": "Synced {{time}} ago",
"statusbar_sync_source_manual": "Manual: ",
"statusbar_sync_source_dry": "Dry: ",
"statusbar_sync_source_auto": "Auto: ",
"statusbar_sync_source_auto_once_init": "Auto (init): ",
"statusbar_sync_source_auto_sync_on_save": "Auto (save): ",
"statusbar_sync_status_prefix_success": "Successfully synced ",
"statusbar_sync_status_prefix_failed": "Failed to sync ",
"statusbar_time_years": "{{time}} years ago",
"statusbar_time_months": "{{time}} months ago",
"statusbar_time_weeks": "{{time}} weeks ago",
"statusbar_time_days": "{{time}} days ago",
"statusbar_time_hours": "{{time}} hours ago",
"statusbar_time_minutes": "{{time}} minutes ago",
"statusbar_time_lessminute": "last minute ago",
"statusbar_time_now": "just now",
"statusbar_syncing": "Syncing...",
"statusbar_failed": "Last sync failed",
"statusbar_now": "Synced just now",
"statusbar_lastsync_label": "Last successful Sync on {{date}}",
"statusbar_lastsync_label": "on {{date}}",
"statusbar_lastsync_never": "Never Synced",
"statusbar_lastsync_never_label": "Never Synced before",
"modal_password_title": "Hold on and PLEASE READ ON...",
"modal_password_shortdesc": "If the field is not empty, files would be encrypted locally before being uploaded.\nIf the field is empty, then files would be uploaded without encryption.",
"modal_password_attn1": "Attention 1/5: The vault name is NOT encrypted. The plugin creates a folder with the vault name on some remote services.",

View File

@ -45,20 +45,26 @@
"command_exportsyncplans_all": "导出同步计划所有export sync plans (all)",
"command_exportlogsindb": "从数据库导出终端日志export logs saved in db",
"statusbar_time_years": "{{time}} 年前同步",
"statusbar_time_months": "{{time}} 月前同步",
"statusbar_time_weeks": "{{time}} 周前同步",
"statusbar_time_days": "{{time}} 天前同步",
"statusbar_time_hours": "{{time}} 小时前同步",
"statusbar_time_minutes": "{{time}} 分钟前同步",
"statusbar_time_lessminute": "一分钟之内同步",
"statusbar_lastsync": "上一次同步于:{{time}}",
"statusbar_sync_source_manual": "手动:",
"statusbar_sync_source_dry": "空跑:",
"statusbar_sync_source_auto": "自动:",
"statusbar_sync_source_auto_once_init": "启动时自动:",
"statusbar_sync_source_auto_sync_on_save": "保存时自动:",
"statusbar_sync_status_prefix_success": "同步成功:",
"statusbar_sync_status_prefix_failed": "同步失败:",
"statusbar_time_years": "{{time}} 年前",
"statusbar_time_months": "{{time}} 月前",
"statusbar_time_weeks": "{{time}} 周前",
"statusbar_time_days": "{{time}} 天前",
"statusbar_time_hours": "{{time}} 小时前",
"statusbar_time_minutes": "{{time}} 分钟前",
"statusbar_time_lessminute": "一分钟之内",
"statusbar_time_now": "刚刚",
"statusbar_syncing": "正在同步",
"statusbar_failed": "上次同步失败了",
"statusbar_now": "刚同步完",
"statusbar_lastsync_label": "上一次同步于:{{date}}",
"statusbar_lastsync_label": "日期:{{date}}",
"statusbar_lastsync_never": "没触发过同步",
"statusbar_lastsync_never_label": "没触发过同步",
"modal_password_title": "稍等一下,请阅读下文:",
"modal_password_shortdesc": "如果密码不是空的,那么文件会在上传之前,在本地先用此密码加密。\n如果密码是空的那么文件会被非加密地上传。",
"modal_password_attn1": "注意 1/5Vault名字是不会加密的本插件会在一些远程存储里创建一个和库名字有着同名的文件夹。",

View File

@ -44,20 +44,26 @@
"command_exportsyncplans_all": "匯出同步計劃所有export sync plans (all)",
"command_exportlogsindb": "從資料庫匯出終端日誌export logs saved in db",
"statusbar_time_years": "{{time}} 年前同步",
"statusbar_time_months": "{{time}} 月前同步",
"statusbar_time_weeks": "{{time}} 周前同步",
"statusbar_time_days": "{{time}} 天前同步",
"statusbar_time_hours": "{{time}} 小時前同步",
"statusbar_time_minutes": "{{time}} 分鐘前同步",
"statusbar_time_lessminute": "一分鐘之內同步",
"statusbar_lastsync": "上一次同步於:{{time}}",
"statusbar_sync_source_manual": "手動:",
"statusbar_sync_source_dry": "空跑:",
"statusbar_sync_source_auto": "自動:",
"statusbar_sync_source_auto_once_init": "啟動時自動:",
"statusbar_sync_source_auto_sync_on_save": "儲存時自動:",
"statusbar_sync_status_prefix_success": "同步成功:",
"statusbar_sync_status_prefix_failed": "同步失敗:",
"statusbar_time_years": "{{time}} 年前",
"statusbar_time_months": "{{time}} 月前",
"statusbar_time_weeks": "{{time}} 周前",
"statusbar_time_days": "{{time}} 天前",
"statusbar_time_hours": "{{time}} 小時前",
"statusbar_time_minutes": "{{time}} 分鐘前",
"statusbar_time_lessminute": "一分鐘之內",
"statusbar_time_now": "剛剛",
"statusbar_syncing": "正在同步",
"statusbar_failed": "上次同步失敗了",
"statusbar_now": "剛同步完",
"statusbar_lastsync_label": "上一次同步於:{{date}}",
"statusbar_lastsync_label": "日期:{{date}}",
"statusbar_lastsync_never": "沒觸發過同步",
"statusbar_lastsync_never_label": "沒觸發過同步",
"modal_password_title": "稍等一下,請閱讀下文:",
"modal_password_shortdesc": "如果密碼不是空的,那麼檔案會在上傳之前,在本地先用此密碼加密。\n如果密碼是空的那麼檔案會被非加密地上傳。",
"modal_password_attn1": "注意 1/5儲存庫Vault名字是不會加密的本外掛會在一些遠端儲存裡建立一個和庫名字有著同名的資料夾。",

View File

@ -519,7 +519,27 @@ export const getLastSuccessSyncTimeByVault = async (
) => {
return (await db.simpleKVForMiscTbl.getItem(
`${vaultRandomID}-lastSuccessSyncMillis`
)) as number;
)) as number | null | undefined;
};
export const upsertLastFailedSyncTimeByVault = async (
db: InternalDBs,
vaultRandomID: string,
millis: number
) => {
await db.simpleKVForMiscTbl.setItem(
`${vaultRandomID}-lastFailedSyncMillis`,
millis
);
};
export const getLastFailedSyncTimeByVault = async (
db: InternalDBs,
vaultRandomID: string
) => {
return (await db.simpleKVForMiscTbl.getItem(
`${vaultRandomID}-lastFailedSyncMillis`
)) as number | null | undefined;
};
export const upsertPluginVersionByVault = async (

View File

@ -92,8 +92,10 @@ import {
type InternalDBs,
clearAllLoggerOutputRecords,
clearExpiredSyncPlanRecords,
getLastFailedSyncTimeByVault,
getLastSuccessSyncTimeByVault,
prepareDBs,
upsertLastFailedSyncTimeByVault,
upsertLastSuccessSyncTimeByVault,
upsertPluginVersionByVault,
} from "./localdb";
@ -176,6 +178,29 @@ const getIconSvg = () => {
return res;
};
const getStatusBarShortMsgFromSyncSource = (
t: (x: TransItemType, vars?: any) => string,
s: SyncTriggerSourceType | undefined
) => {
if (s === undefined) {
return "";
}
switch (s) {
case "manual":
return t("statusbar_sync_source_manual");
case "dry":
return t("statusbar_sync_source_dry");
case "auto":
return t("statusbar_sync_source_auto");
case "auto_once_init":
return t("statusbar_sync_source_auto_once_init");
case "auto_sync_on_save":
return t("statusbar_sync_source_auto_sync_on_save");
default:
throw Error(`no translate for ${s}`);
}
};
export default class RemotelySavePlugin extends Plugin {
settings!: RemotelySavePluginSettings;
db!: InternalDBs;
@ -393,17 +418,15 @@ export default class RemotelySavePlugin extends Plugin {
) => {
if (step === 1) {
// change status to "syncing..." on statusbar
this.updateLastSuccessSyncMsg(-1);
this.updateLastSyncMsg(s, -1, -1);
} else if (step === 8 && everythingOk) {
const lastSuccessSyncMillis = Date.now();
await upsertLastSuccessSyncTimeByVault(
this.db,
this.vaultRandomID,
lastSuccessSyncMillis
);
this.updateLastSuccessSyncMsg(lastSuccessSyncMillis);
const ts = Date.now();
await upsertLastSuccessSyncTimeByVault(this.db, this.vaultRandomID, ts);
this.updateLastSyncMsg(s, ts, null);
} else if (!everythingOk) {
this.updateLastSuccessSyncMsg(-2); // magic number
const ts = Date.now();
await upsertLastFailedSyncTimeByVault(this.db, this.vaultRandomID, ts);
this.updateLastSyncMsg(s, null, ts); // magic number
}
};
@ -412,12 +435,15 @@ export default class RemotelySavePlugin extends Plugin {
};
const callbackSyncProcess = async (
s: SyncTriggerSourceType,
realCounter: number,
realTotalCount: number,
pathName: string,
decision: string
) => {
this.setCurrSyncMsg(
t,
s,
realCounter,
realTotalCount,
pathName,
@ -1060,15 +1086,21 @@ export default class RemotelySavePlugin extends Plugin {
this.statusBarElement = statusBarItem.createEl("span");
this.statusBarElement.setAttribute("data-tooltip-position", "top");
this.updateLastSuccessSyncMsg(
await getLastSuccessSyncTimeByVault(this.db, this.vaultRandomID)
this.updateLastSyncMsg(
undefined,
await getLastSuccessSyncTimeByVault(this.db, this.vaultRandomID),
await getLastFailedSyncTimeByVault(this.db, this.vaultRandomID)
);
// update statusbar text every 30 seconds
this.registerInterval(
window.setInterval(async () => {
this.updateLastSuccessSyncMsg(
await getLastSuccessSyncTimeByVault(this.db, this.vaultRandomID)
);
if (!this.isSyncing) {
this.updateLastSyncMsg(
undefined,
await getLastSuccessSyncTimeByVault(this.db, this.vaultRandomID),
await getLastFailedSyncTimeByVault(this.db, this.vaultRandomID)
);
}
}, 1000 * 30)
);
}
@ -1618,7 +1650,8 @@ export default class RemotelySavePlugin extends Plugin {
if (
caller === "SYNC" ||
(caller === "FILE_CHANGES" && lastModified > lastSuccessSyncMillis)
(caller === "FILE_CHANGES" &&
lastModified > (lastSuccessSyncMillis ?? 1))
) {
console.debug(
`so lastModified > lastSuccessSyncMillis or it's called while syncing before`
@ -1734,17 +1767,34 @@ export default class RemotelySavePlugin extends Plugin {
}
setCurrSyncMsg(
t: (x: TransItemType, vars?: any) => string,
s: SyncTriggerSourceType,
i: number,
totalCount: number,
pathName: string,
decision: string,
triggerSource: SyncTriggerSourceType
) {
const msg = `syncing progress=${i}/${totalCount},decision=${decision},path=${pathName},source=${triggerSource}`;
this.currSyncMsg = msg;
const L = `${totalCount}`.length;
const iStr = `${i}`.padStart(L, "0");
const prefix = getStatusBarShortMsgFromSyncSource(t, s);
const shortMsg = prefix + `Syncing ${iStr}/${totalCount}`;
const longMsg =
prefix +
`Syncing progress=${iStr}/${totalCount},decision=${decision},path=${pathName},source=${triggerSource}`;
this.currSyncMsg = longMsg;
if (this.statusBarElement !== undefined) {
this.statusBarElement.setText(shortMsg);
this.statusBarElement.setAttribute("aria-label", longMsg);
}
}
updateLastSuccessSyncMsg(lastSuccessSyncMillis?: number) {
updateLastSyncMsg(
s: SyncTriggerSourceType | undefined,
lastSuccessSyncMillis: number | null | undefined,
lastFailedSyncMillis: number | null | undefined
) {
if (this.statusBarElement === undefined) return;
const t = (x: TransItemType, vars?: any) => {
@ -1754,18 +1804,27 @@ export default class RemotelySavePlugin extends Plugin {
let lastSyncMsg = t("statusbar_lastsync_never");
let lastSyncLabelMsg = t("statusbar_lastsync_never_label");
if (lastSuccessSyncMillis !== undefined && lastSuccessSyncMillis === -1) {
lastSyncMsg = t("statusbar_syncing");
}
const inputTs = Math.max(
lastSuccessSyncMillis ?? -999,
lastFailedSyncMillis ?? -999
);
const isSuccess =
(lastSuccessSyncMillis ?? -999) >= (lastFailedSyncMillis ?? -999);
if (lastSuccessSyncMillis !== undefined && lastSuccessSyncMillis === -2) {
lastSyncMsg = t("statusbar_failed");
lastSyncLabelMsg = t("statusbar_failed");
}
if (lastSuccessSyncMillis !== undefined && lastSuccessSyncMillis > 0) {
const deltaTime = Date.now() - lastSuccessSyncMillis;
if (lastSuccessSyncMillis === -1) {
// magic number
// otherwise how can we know we are syncing??
lastSyncMsg =
getStatusBarShortMsgFromSyncSource(t, s!) + t("statusbar_syncing");
} else if (inputTs > 0) {
let prefix = "";
if (isSuccess) {
prefix = t("statusbar_sync_status_prefix_success");
} else {
prefix = t("statusbar_sync_status_prefix_failed");
}
const deltaTime = Date.now() - inputTs;
// create human readable time
const years = Math.floor(deltaTime / 31556952000);
const months = Math.floor(deltaTime / 2629746000);
@ -1774,9 +1833,7 @@ export default class RemotelySavePlugin extends Plugin {
const hours = Math.floor(deltaTime / 3600000);
const minutes = Math.floor(deltaTime / 60000);
const seconds = Math.floor(deltaTime / 1000);
let timeText = "";
if (years > 0) {
timeText = t("statusbar_time_years", { time: years });
} else if (months > 0) {
@ -1792,10 +1849,9 @@ export default class RemotelySavePlugin extends Plugin {
} else if (seconds > 30) {
timeText = t("statusbar_time_lessminute");
} else {
timeText = t("statusbar_now");
timeText = t("statusbar_time_now");
}
const dateText = new Date(lastSuccessSyncMillis).toLocaleTimeString(
const dateText = new Date(inputTs).toLocaleTimeString(
navigator.language,
{
weekday: "long",
@ -1805,8 +1861,11 @@ export default class RemotelySavePlugin extends Plugin {
}
);
lastSyncMsg = timeText;
lastSyncLabelMsg = t("statusbar_lastsync_label", { date: dateText });
lastSyncMsg = prefix + timeText;
lastSyncLabelMsg =
prefix + t("statusbar_lastsync_label", { date: dateText });
} else {
// TODO: no idea what happened.
}
this.statusBarElement.setText(lastSyncMsg);

View File

@ -55,6 +55,7 @@ import {
clearAllPrevSyncRecordByVault,
clearAllSyncPlanRecords,
destroyDBs,
upsertLastFailedSyncTimeByVault,
upsertLastSuccessSyncTimeByVault,
} from "./localdb";
import type RemotelySavePlugin from "./main"; // unavoidable
@ -2134,7 +2135,12 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
this.plugin.vaultRandomID,
-1
);
this.plugin.updateLastSuccessSyncMsg(-1);
await upsertLastFailedSyncTimeByVault(
this.plugin.db,
this.plugin.vaultRandomID,
-1
);
this.plugin.updateLastSyncMsg(undefined, null, null);
new Notice(t("settings_resetstatusbar_notice"));
});
});