@vrtmrz/livesync-commonlib 0.1.0-rc.2 → 0.1.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common/configForDoc.js +6 -3
- package/dist/common/messages/combinedMessages.prod.d.ts +9 -0
- package/dist/common/messages/combinedMessages.prod.js +9 -0
- package/dist/common/messages/def.d.ts +3 -0
- package/dist/common/messagesJson/en.json +3 -0
- package/dist/common/models/setting.const.defaults.js +1 -0
- package/dist/common/models/setting.type.d.ts +4 -2
- package/dist/common/settingConstants.js +2 -2
- package/dist/interfaces/Confirm.d.ts +2 -1
- package/dist/replication/LiveSyncAbstractReplicator.d.ts +1 -2
- package/dist/replication/couchdb/LiveSyncReplicator.d.ts +0 -1
- package/dist/replication/couchdb/LiveSyncReplicator.js +0 -3
- package/dist/replication/journal/LiveSyncJournalReplicator.d.ts +0 -1
- package/dist/replication/journal/LiveSyncJournalReplicator.js +0 -3
- package/dist/replication/trystero/LiveSyncTrysteroReplicator.d.ts +1 -2
- package/dist/replication/trystero/LiveSyncTrysteroReplicator.js +1 -4
- package/dist/serviceFeatures/checkRemoteSize.d.ts +5 -3
- package/dist/serviceFeatures/checkRemoteSize.js +51 -11
- package/dist/serviceModules/Rebuilder.d.ts +0 -4
- package/dist/serviceModules/Rebuilder.js +2 -10
- package/dist/services/base/IService.d.ts +1 -5
- package/dist/services/base/ReplicationService.d.ts +1 -1
- package/dist/services/base/ReplicationService.js +5 -15
- package/dist/services/base/SettingService.d.ts +0 -8
- package/dist/services/base/SettingService.js +0 -5
- package/dist/services/implements/headless/HeadlessAPIService.d.ts +2 -2
- package/dist/services/implements/headless/HeadlessAPIService.js +1 -1
- package/dist/worker/bgWorker.js +1 -1
- package/docs/development.md +8 -0
- package/docs/proven-in-use.md +9 -7
- package/docs/releasing.md +3 -1
- package/package.json +1 -1
|
@@ -20,12 +20,12 @@ const DoctorRegulationV0_24_16 = {
|
|
|
20
20
|
rules: {
|
|
21
21
|
sendChunksBulk: {
|
|
22
22
|
value: false,
|
|
23
|
-
reason: "
|
|
23
|
+
reason: "Automatic bulk chunk pre-send is obsolete and must remain disabled",
|
|
24
24
|
level: 0 /* Must */
|
|
25
25
|
},
|
|
26
26
|
sendChunksBulkMaxSize: {
|
|
27
27
|
value: 1,
|
|
28
|
-
reason: "
|
|
28
|
+
reason: "Use a conservative request size for the explicit manual chunk resend tool",
|
|
29
29
|
level: 0 /* Must */
|
|
30
30
|
},
|
|
31
31
|
doNotUseFixedRevisionForChunks: {
|
|
@@ -263,7 +263,10 @@ async function performDoctorConsultation(env, settings, {
|
|
|
263
263
|
}),
|
|
264
264
|
options,
|
|
265
265
|
{
|
|
266
|
-
title: translate("Doctor.Dialogue.TitleFix", {
|
|
266
|
+
title: translate("Doctor.Dialogue.TitleFix", {
|
|
267
|
+
current: `${++idx}`,
|
|
268
|
+
total: `${issueItems.length}`
|
|
269
|
+
}),
|
|
267
270
|
defaultAction: OPT_FIX
|
|
268
271
|
}
|
|
269
272
|
);
|
|
@@ -2597,6 +2597,12 @@ export declare const allMessages: {
|
|
|
2597
2597
|
readonly ru: "Можно установить предупреждение о максимальной ёмкости базы данных.";
|
|
2598
2598
|
readonly zh: "我们可以设置一个最大数据库容量警告,**以便在远程存储空间耗尽前采取行动**。\n您想启用这个功能吗?\n\n> [!MORE]-\n> - 0: 不警告存储大小。\n> 如果您在远程存储(尤其是自托管)上有足够的空间,则推荐此选项。您可以手动检查存储大小并重建。\n> - 800: 如果远程存储大小超过 800MB 则发出警告。\n> 如果您使用的是 fly.io(1GB 限制) 或 IBM Cloudant,则推荐此选项。\n> - 2000: 如果远程存储大小超过 2GB 则发出警告。\n\n如果达到限制,系统会要求我们逐步增大限制\n";
|
|
2599
2599
|
};
|
|
2600
|
+
readonly "moduleCheckRemoteSize.noticeExceeded": {
|
|
2601
|
+
readonly def: "Remote storage size is ${measuredSize}, above the configured ${notifySize} notification threshold. {HERE}";
|
|
2602
|
+
};
|
|
2603
|
+
readonly "moduleCheckRemoteSize.noticeNotConfigured": {
|
|
2604
|
+
readonly def: "Remote storage size notifications are not configured. {HERE}";
|
|
2605
|
+
};
|
|
2600
2606
|
readonly "moduleCheckRemoteSize.option2GB": {
|
|
2601
2607
|
readonly def: "2GB (Standard)";
|
|
2602
2608
|
readonly es: "2GB (Estándar)";
|
|
@@ -2667,6 +2673,9 @@ export declare const allMessages: {
|
|
|
2667
2673
|
readonly ru: "Перестроить всё сейчас";
|
|
2668
2674
|
readonly zh: "立即重建所有内容";
|
|
2669
2675
|
};
|
|
2676
|
+
readonly "moduleCheckRemoteSize.optionReview": {
|
|
2677
|
+
readonly def: "Review options";
|
|
2678
|
+
};
|
|
2670
2679
|
readonly "moduleCheckRemoteSize.titleDatabaseSizeLimitExceeded": {
|
|
2671
2680
|
readonly def: "Remote storage size exceeded the limit";
|
|
2672
2681
|
readonly es: "El tamaño del almacenamiento remoto superó el límite";
|
|
@@ -2597,6 +2597,12 @@ const allMessages = {
|
|
|
2597
2597
|
ru: "\u041C\u043E\u0436\u043D\u043E \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u043F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0435 \u043E \u043C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u043E\u0439 \u0451\u043C\u043A\u043E\u0441\u0442\u0438 \u0431\u0430\u0437\u044B \u0434\u0430\u043D\u043D\u044B\u0445.",
|
|
2598
2598
|
zh: "\u6211\u4EEC\u53EF\u4EE5\u8BBE\u7F6E\u4E00\u4E2A\u6700\u5927\u6570\u636E\u5E93\u5BB9\u91CF\u8B66\u544A,**\u4EE5\u4FBF\u5728\u8FDC\u7A0B\u5B58\u50A8\u7A7A\u95F4\u8017\u5C3D\u524D\u91C7\u53D6\u884C\u52A8**\u3002\n\u60A8\u60F3\u542F\u7528\u8FD9\u4E2A\u529F\u80FD\u5417?\n\n> [!MORE]-\n> - 0: \u4E0D\u8B66\u544A\u5B58\u50A8\u5927\u5C0F\u3002\n> \u5982\u679C\u60A8\u5728\u8FDC\u7A0B\u5B58\u50A8(\u5C24\u5176\u662F\u81EA\u6258\u7BA1)\u4E0A\u6709\u8DB3\u591F\u7684\u7A7A\u95F4,\u5219\u63A8\u8350\u6B64\u9009\u9879\u3002\u60A8\u53EF\u4EE5\u624B\u52A8\u68C0\u67E5\u5B58\u50A8\u5927\u5C0F\u5E76\u91CD\u5EFA\u3002\n> - 800: \u5982\u679C\u8FDC\u7A0B\u5B58\u50A8\u5927\u5C0F\u8D85\u8FC7 800MB \u5219\u53D1\u51FA\u8B66\u544A\u3002\n> \u5982\u679C\u60A8\u4F7F\u7528\u7684\u662F fly.io(1GB \u9650\u5236) \u6216 IBM Cloudant,\u5219\u63A8\u8350\u6B64\u9009\u9879\u3002\n> - 2000: \u5982\u679C\u8FDC\u7A0B\u5B58\u50A8\u5927\u5C0F\u8D85\u8FC7 2GB \u5219\u53D1\u51FA\u8B66\u544A\u3002\n\n\u5982\u679C\u8FBE\u5230\u9650\u5236,\u7CFB\u7EDF\u4F1A\u8981\u6C42\u6211\u4EEC\u9010\u6B65\u589E\u5927\u9650\u5236\n"
|
|
2599
2599
|
},
|
|
2600
|
+
"moduleCheckRemoteSize.noticeExceeded": {
|
|
2601
|
+
def: "Remote storage size is ${measuredSize}, above the configured ${notifySize} notification threshold. {HERE}"
|
|
2602
|
+
},
|
|
2603
|
+
"moduleCheckRemoteSize.noticeNotConfigured": {
|
|
2604
|
+
def: "Remote storage size notifications are not configured. {HERE}"
|
|
2605
|
+
},
|
|
2600
2606
|
"moduleCheckRemoteSize.option2GB": {
|
|
2601
2607
|
def: "2GB (Standard)",
|
|
2602
2608
|
es: "2GB (Est\xE1ndar)",
|
|
@@ -2667,6 +2673,9 @@ const allMessages = {
|
|
|
2667
2673
|
ru: "\u041F\u0435\u0440\u0435\u0441\u0442\u0440\u043E\u0438\u0442\u044C \u0432\u0441\u0451 \u0441\u0435\u0439\u0447\u0430\u0441",
|
|
2668
2674
|
zh: "\u7ACB\u5373\u91CD\u5EFA\u6240\u6709\u5185\u5BB9"
|
|
2669
2675
|
},
|
|
2676
|
+
"moduleCheckRemoteSize.optionReview": {
|
|
2677
|
+
def: "Review options"
|
|
2678
|
+
},
|
|
2670
2679
|
"moduleCheckRemoteSize.titleDatabaseSizeLimitExceeded": {
|
|
2671
2680
|
def: "Remote storage size exceeded the limit",
|
|
2672
2681
|
es: "El tama\xF1o del almacenamiento remoto super\xF3 el l\xEDmite",
|
|
@@ -278,6 +278,8 @@ export declare const PartialMessages: {
|
|
|
278
278
|
"moduleCheckRemoteSize.msgConfirmRebuild": string;
|
|
279
279
|
"moduleCheckRemoteSize.msgDatabaseGrowing": string;
|
|
280
280
|
"moduleCheckRemoteSize.msgSetDBCapacity": string;
|
|
281
|
+
"moduleCheckRemoteSize.noticeExceeded": string;
|
|
282
|
+
"moduleCheckRemoteSize.noticeNotConfigured": string;
|
|
281
283
|
"moduleCheckRemoteSize.option2GB": string;
|
|
282
284
|
"moduleCheckRemoteSize.option800MB": string;
|
|
283
285
|
"moduleCheckRemoteSize.optionAskMeLater": string;
|
|
@@ -285,6 +287,7 @@ export declare const PartialMessages: {
|
|
|
285
287
|
"moduleCheckRemoteSize.optionIncreaseLimit": string;
|
|
286
288
|
"moduleCheckRemoteSize.optionNoWarn": string;
|
|
287
289
|
"moduleCheckRemoteSize.optionRebuildAll": string;
|
|
290
|
+
"moduleCheckRemoteSize.optionReview": string;
|
|
288
291
|
"moduleCheckRemoteSize.titleDatabaseSizeLimitExceeded": string;
|
|
289
292
|
"moduleCheckRemoteSize.titleDatabaseSizeNotify": string;
|
|
290
293
|
"moduleInputUIObsidian.defaultTitleConfirmation": string;
|
|
@@ -277,6 +277,8 @@
|
|
|
277
277
|
"moduleCheckRemoteSize.msgConfirmRebuild": "This may take a bit of a long time. Do you really want to rebuild everything now?",
|
|
278
278
|
"moduleCheckRemoteSize.msgDatabaseGrowing": "**Your database is getting larger!** But do not worry, we can address it now. The time before running out of space on the remote storage.\n\n| Measured size | Configured size |\n| --- | --- |\n| ${estimatedSize} | ${maxSize} |\n\n> [!MORE]-\n> If you have been using it for many years, there may be unreferenced chunks - that is, garbage - accumulating in the database. Therefore, we recommend rebuilding everything. It will probably become much smaller.\n>\n> If the volume of your vault is simply increasing, it is better to rebuild everything after organizing the files. Self-hosted LiveSync does not delete the actual data even if you delete it to speed up the process. It is roughly [documented](https://github.com/vrtmrz/obsidian-livesync/blob/main/docs/tech_info.md).\n>\n> If you don't mind the increase, you can increase the notification limit by 100MB. This is the case if you are running it on your own server. However, it is better to rebuild everything from time to time.\n>\n\n> [!WARNING]\n> If you perform rebuild everything, make sure all devices are synchronised. The plug-in will merge as much as possible, though.\n",
|
|
279
279
|
"moduleCheckRemoteSize.msgSetDBCapacity": "We can set a maximum database capacity warning, **to take action before running out of space on the remote storage**.\nDo you want to enable this?\n\n> [!MORE]-\n> - 0: Do not warn about storage size.\n> This is recommended if you have enough space on the remote storage especially you have self-hosted. And you can check the storage size and rebuild manually.\n> - 800: Warn if the remote storage size exceeds 800MB.\n> This is recommended if you are using fly.io with 1GB limit or IBM Cloudant.\n> - 2000: Warn if the remote storage size exceeds 2GB.\n\nIf we have reached the limit, we will be asked to enlarge the limit step by step.\n",
|
|
280
|
+
"moduleCheckRemoteSize.noticeExceeded": "Remote storage size is ${measuredSize}, above the configured ${notifySize} notification threshold. {HERE}",
|
|
281
|
+
"moduleCheckRemoteSize.noticeNotConfigured": "Remote storage size notifications are not configured. {HERE}",
|
|
280
282
|
"moduleCheckRemoteSize.option2GB": "2GB (Standard)",
|
|
281
283
|
"moduleCheckRemoteSize.option800MB": "800MB (Cloudant, fly.io)",
|
|
282
284
|
"moduleCheckRemoteSize.optionAskMeLater": "Ask me later",
|
|
@@ -284,6 +286,7 @@
|
|
|
284
286
|
"moduleCheckRemoteSize.optionIncreaseLimit": "increase to ${newMax}MB",
|
|
285
287
|
"moduleCheckRemoteSize.optionNoWarn": "No, never warn please",
|
|
286
288
|
"moduleCheckRemoteSize.optionRebuildAll": "Rebuild Everything Now",
|
|
289
|
+
"moduleCheckRemoteSize.optionReview": "Review options",
|
|
287
290
|
"moduleCheckRemoteSize.titleDatabaseSizeLimitExceeded": "Remote storage size exceeded the limit",
|
|
288
291
|
"moduleCheckRemoteSize.titleDatabaseSizeNotify": "Setting up database size notification",
|
|
289
292
|
"moduleInputUIObsidian.defaultTitleConfirmation": "Confirmation",
|
|
@@ -146,6 +146,7 @@ const SETTINGS_SCHEMA_DEFAULTS = {
|
|
|
146
146
|
handleFilenameCaseSensitive: void 0,
|
|
147
147
|
doNotUseFixedRevisionForChunks: true,
|
|
148
148
|
showLongerLogInsideEditor: false,
|
|
149
|
+
/** @deprecated Retained for settings and Setup URI compatibility. */
|
|
149
150
|
sendChunksBulk: false,
|
|
150
151
|
sendChunksBulkMaxSize: 1,
|
|
151
152
|
/**
|
|
@@ -668,11 +668,13 @@ interface ObsoleteRemoteDBSettings {
|
|
|
668
668
|
*/
|
|
669
669
|
disableRequestURI: boolean;
|
|
670
670
|
/**
|
|
671
|
-
*
|
|
671
|
+
* Retained for settings and Setup URI compatibility.
|
|
672
|
+
* Automatic bulk chunk pre-send is no longer supported.
|
|
673
|
+
* @deprecated
|
|
672
674
|
*/
|
|
673
675
|
sendChunksBulk: boolean;
|
|
674
676
|
/**
|
|
675
|
-
* The maximum size
|
|
677
|
+
* The maximum request size used by the explicit manual chunk resend tool, in MB.
|
|
676
678
|
*/
|
|
677
679
|
sendChunksBulkMaxSize: number;
|
|
678
680
|
/**
|
|
@@ -328,8 +328,8 @@ const SettingInformation = {
|
|
|
328
328
|
desc: "If this enabled, all chunks will be stored with the revision made from its content."
|
|
329
329
|
},
|
|
330
330
|
sendChunksBulkMaxSize: {
|
|
331
|
-
name: "Maximum size
|
|
332
|
-
desc: "MB"
|
|
331
|
+
name: "Maximum request size for manually resending chunks",
|
|
332
|
+
desc: "MB per request"
|
|
333
333
|
},
|
|
334
334
|
useAdvancedMode: {
|
|
335
335
|
name: "Enable advanced features"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export type ConfirmActionLayout = "auto" | "vertical";
|
|
1
2
|
export interface Confirm {
|
|
2
3
|
askYesNo(message: string): Promise<"yes" | "no">;
|
|
3
4
|
askString(title: string, key: string, placeholder: string, isPassword?: boolean): Promise<string | false>;
|
|
@@ -20,5 +21,5 @@ export interface Confirm {
|
|
|
20
21
|
* interactive action.
|
|
21
22
|
*/
|
|
22
23
|
askInPopup(key: string, dialogText: string, anchorCallback: (anchor: HTMLAnchorElement) => void, durationMs?: number): void;
|
|
23
|
-
confirmWithMessage(title: string, contentMd: string, buttons: string[], defaultAction: (typeof buttons)[number], timeout?: number): Promise<(typeof buttons)[number] | false>;
|
|
24
|
+
confirmWithMessage(title: string, contentMd: string, buttons: string[], defaultAction: (typeof buttons)[number], timeout?: number, actionLayout?: ConfirmActionLayout): Promise<(typeof buttons)[number] | false>;
|
|
24
25
|
}
|
|
@@ -34,7 +34,6 @@ export declare abstract class LiveSyncAbstractReplicator {
|
|
|
34
34
|
remoteLockedAndDeviceNotAccepted: boolean;
|
|
35
35
|
tweakSettingsMismatched: boolean;
|
|
36
36
|
preferredTweakValue?: TweakValues;
|
|
37
|
-
abstract get isChunkSendingSupported(): boolean;
|
|
38
37
|
get database(): import("../pouchdb/LiveSyncLocalDB.js").LiveSyncLocalDB;
|
|
39
38
|
get rawDatabase(): PouchDB.Database<EntryDoc>;
|
|
40
39
|
get currentSettings(): import("../common/types.js").ObsidianLiveSyncSettings;
|
|
@@ -49,7 +48,7 @@ export declare abstract class LiveSyncAbstractReplicator {
|
|
|
49
48
|
abstract openReplication(setting: RemoteDBSettings, keepAlive: boolean, showResult: boolean, ignoreCleanLock: boolean): Promise<void | boolean>;
|
|
50
49
|
updateInfo: () => void;
|
|
51
50
|
abstract tryConnectRemote(setting: RemoteDBSettings, showResult?: boolean): Promise<boolean>;
|
|
52
|
-
abstract replicateAllToServer(setting: RemoteDBSettings, showingNotice?: boolean
|
|
51
|
+
abstract replicateAllToServer(setting: RemoteDBSettings, showingNotice?: boolean): Promise<boolean>;
|
|
53
52
|
abstract replicateAllFromServer(setting: RemoteDBSettings, showingNotice?: boolean): Promise<boolean>;
|
|
54
53
|
abstract closeReplication(): void;
|
|
55
54
|
abstract tryResetRemoteDatabase(setting: RemoteDBSettings): Promise<void>;
|
|
@@ -5,7 +5,6 @@ export interface LiveSyncCouchDBReplicatorEnv extends LiveSyncReplicatorEnv {
|
|
|
5
5
|
services: ServiceHub;
|
|
6
6
|
}
|
|
7
7
|
export declare class LiveSyncCouchDBReplicator extends LiveSyncAbstractReplicator {
|
|
8
|
-
get isChunkSendingSupported(): boolean;
|
|
9
8
|
isMobile(): boolean;
|
|
10
9
|
constructor(env: LiveSyncCouchDBReplicatorEnv);
|
|
11
10
|
getInitialSyncParameters(setting: RemoteDBSettings): Promise<SyncParameters>;
|
|
@@ -7,7 +7,6 @@ import { type SimpleStore } from "../../common/utils.js";
|
|
|
7
7
|
import type { LiveSyncJournalReplicatorEnv } from "./LiveSyncJournalReplicatorEnv.js";
|
|
8
8
|
export declare class LiveSyncJournalReplicator extends LiveSyncAbstractReplicator {
|
|
9
9
|
env: LiveSyncJournalReplicatorEnv;
|
|
10
|
-
get isChunkSendingSupported(): boolean;
|
|
11
10
|
get client(): JournalSyncCore;
|
|
12
11
|
get simpleStore(): SimpleStore<CheckPointInfo>;
|
|
13
12
|
_client: JournalSyncCore;
|
|
@@ -23,7 +23,6 @@ export declare class LiveSyncTrysteroReplicator extends LiveSyncAbstractReplicat
|
|
|
23
23
|
get openReplicationUI(): (showResult: boolean) => Promise<boolean | void>;
|
|
24
24
|
get rawReplicator(): TrysteroReplicator;
|
|
25
25
|
get rawHost(): P2PHost;
|
|
26
|
-
get isChunkSendingSupported(): boolean;
|
|
27
26
|
getReplicationPBKDF2Salt(_setting: RemoteDBSettings, _refresh?: boolean): Promise<Uint8Array<ArrayBuffer>>;
|
|
28
27
|
terminateSync(): void;
|
|
29
28
|
private _buildEnv;
|
|
@@ -70,7 +69,7 @@ export declare class LiveSyncTrysteroReplicator extends LiveSyncAbstractReplicat
|
|
|
70
69
|
makeSureOpened(): Promise<void>;
|
|
71
70
|
openReplication(_setting: RemoteDBSettings, _keepAlive: boolean, showResult: boolean, _ignoreCleanLock: boolean): Promise<void | boolean>;
|
|
72
71
|
tryConnectRemote(_setting: RemoteDBSettings, _showResult?: boolean): Promise<boolean>;
|
|
73
|
-
replicateAllToServer(_setting: RemoteDBSettings, _showingNotice?: boolean
|
|
72
|
+
replicateAllToServer(_setting: RemoteDBSettings, _showingNotice?: boolean): Promise<boolean>;
|
|
74
73
|
selectPeer(settingPeerName: string, r: TrysteroReplicator, logLevel: LOG_LEVEL): Promise<string | false>;
|
|
75
74
|
tryUntilSuccess<T>(func: () => Promise<T | false>, repeat: number, logLevel: LOG_LEVEL): Promise<T | false>;
|
|
76
75
|
replicateAllFromServer(setting: RemoteDBSettings, showingNotice?: boolean): Promise<boolean>;
|
|
@@ -29,9 +29,6 @@ class LiveSyncTrysteroReplicator extends LiveSyncAbstractReplicator {
|
|
|
29
29
|
get rawHost() {
|
|
30
30
|
return this._p2pHost;
|
|
31
31
|
}
|
|
32
|
-
get isChunkSendingSupported() {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
32
|
getReplicationPBKDF2Salt(_setting, _refresh) {
|
|
36
33
|
return Promise.resolve(new Uint8Array(32));
|
|
37
34
|
}
|
|
@@ -215,7 +212,7 @@ class LiveSyncTrysteroReplicator extends LiveSyncAbstractReplicator {
|
|
|
215
212
|
tryConnectRemote(_setting, _showResult) {
|
|
216
213
|
return Promise.resolve(false);
|
|
217
214
|
}
|
|
218
|
-
replicateAllToServer(_setting, _showingNotice
|
|
215
|
+
replicateAllToServer(_setting, _showingNotice) {
|
|
219
216
|
return Promise.resolve(false);
|
|
220
217
|
}
|
|
221
218
|
async selectPeer(settingPeerName, r, logLevel) {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { createInstanceLogFunction, type LogFunction } from "../services/lib/logUtils.js";
|
|
2
2
|
import type { NecessaryServices } from "../interfaces/ServiceModule.js";
|
|
3
|
+
type RemoteSizeReviewMode = "notice" | "dialogue";
|
|
3
4
|
/**
|
|
4
5
|
* Notify when checking remote storage size is not configured.
|
|
5
6
|
* @returns true if the check is passed or user has configured the notification, false to block subsequent processes. (always true).
|
|
6
7
|
*/
|
|
7
|
-
export declare function onNotifyRemoteSizeNotConfiguredFactory(host: NecessaryServices<"appLifecycle" | "API" | "setting", never>, log: ReturnType<typeof createInstanceLogFunction
|
|
8
|
+
export declare function onNotifyRemoteSizeNotConfiguredFactory(host: NecessaryServices<"appLifecycle" | "API" | "setting", never>, log: ReturnType<typeof createInstanceLogFunction>, mode?: RemoteSizeReviewMode): () => Promise<boolean>;
|
|
8
9
|
/**
|
|
9
10
|
* Notify when the remote storage size exceed the threshold.
|
|
10
11
|
* @returns true if the check is passed or user has chosen to ignore the warning, false to block subsequent processes.
|
|
@@ -12,7 +13,7 @@ export declare function onNotifyRemoteSizeNotConfiguredFactory(host: NecessarySe
|
|
|
12
13
|
* @param log
|
|
13
14
|
* @returns
|
|
14
15
|
*/
|
|
15
|
-
export declare function onNotifyRemoteSizeExceedFactory(host: NecessaryServices<"API" | "setting" | "replicator", "rebuilder">, log: ReturnType<typeof createInstanceLogFunction
|
|
16
|
+
export declare function onNotifyRemoteSizeExceedFactory(host: NecessaryServices<"API" | "setting" | "replicator", "rebuilder">, log: ReturnType<typeof createInstanceLogFunction>, mode?: RemoteSizeReviewMode): () => Promise<boolean>;
|
|
16
17
|
/**
|
|
17
18
|
* Scan the remote storage size and notify if it is not configured or exceed the threshold.
|
|
18
19
|
* @param host The necessary services required for the operation.
|
|
@@ -20,9 +21,10 @@ export declare function onNotifyRemoteSizeExceedFactory(host: NecessaryServices<
|
|
|
20
21
|
* @param resetThreshold Whether to reset the notification threshold before scanning. This is useful when you want to force the notification to show up again.
|
|
21
22
|
* @returns A promise that resolves to true if all checks pass or user has configured the notification.
|
|
22
23
|
*/
|
|
23
|
-
export declare function scanAllStat(host: NecessaryServices<"API" | "setting" | "replicator" | "appLifecycle", "rebuilder">, log: LogFunction, resetThreshold?: boolean): Promise<boolean>;
|
|
24
|
+
export declare function scanAllStat(host: NecessaryServices<"API" | "setting" | "replicator" | "appLifecycle", "rebuilder">, log: LogFunction, resetThreshold?: boolean, mode?: RemoteSizeReviewMode): Promise<boolean>;
|
|
24
25
|
/**
|
|
25
26
|
* Associate the remote storage size check feature with the app lifecycle events.
|
|
26
27
|
* @param host
|
|
27
28
|
*/
|
|
28
29
|
export declare function useCheckRemoteSize(host: NecessaryServices<"API" | "setting" | "replicator" | "appLifecycle", "rebuilder">): void;
|
|
30
|
+
export {};
|
|
@@ -2,7 +2,17 @@ import { sizeToHumanReadable } from "octagonal-wheels/number";
|
|
|
2
2
|
import { LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE } from "../common/types.js";
|
|
3
3
|
import { createInstanceLogFunction } from "../services/lib/logUtils.js";
|
|
4
4
|
import { EVENT_REQUEST_CHECK_REMOTE_SIZE } from "../events/coreEvents.js";
|
|
5
|
-
|
|
5
|
+
import { fireAndForget } from "../common/utils.js";
|
|
6
|
+
const REMOTE_SIZE_NOTICE_DURATION_MS = 5 * 60 * 1e3;
|
|
7
|
+
function configureReviewAnchor(anchor, label, review) {
|
|
8
|
+
anchor.href = "#";
|
|
9
|
+
anchor.textContent = label;
|
|
10
|
+
anchor.addEventListener("click", (event) => {
|
|
11
|
+
event.preventDefault();
|
|
12
|
+
fireAndForget(review);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function onNotifyRemoteSizeNotConfiguredFactory(host, log, mode = "notice") {
|
|
6
16
|
return async () => {
|
|
7
17
|
const translate = host.services.context.translate;
|
|
8
18
|
log(translate("moduleCheckRemoteSize.logCheckingStorageSizes"), LOG_LEVEL_VERBOSE);
|
|
@@ -15,13 +25,25 @@ function onNotifyRemoteSizeNotConfiguredFactory(host, log) {
|
|
|
15
25
|
const ANSWER_800 = translate("moduleCheckRemoteSize.option800MB");
|
|
16
26
|
const ANSWER_2000 = translate("moduleCheckRemoteSize.option2GB");
|
|
17
27
|
const ASK_ME_NEXT_TIME = translate("moduleCheckRemoteSize.optionAskMeLater");
|
|
28
|
+
if (mode === "notice") {
|
|
29
|
+
host.services.API.confirm.askInPopup(
|
|
30
|
+
"remote-size-not-configured",
|
|
31
|
+
translate("moduleCheckRemoteSize.noticeNotConfigured"),
|
|
32
|
+
(anchor) => configureReviewAnchor(
|
|
33
|
+
anchor,
|
|
34
|
+
translate("moduleCheckRemoteSize.optionReview"),
|
|
35
|
+
() => onNotifyRemoteSizeNotConfiguredFactory(host, log, "dialogue")()
|
|
36
|
+
),
|
|
37
|
+
REMOTE_SIZE_NOTICE_DURATION_MS
|
|
38
|
+
);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
18
41
|
const ret = await host.services.API.confirm.askSelectStringDialogue(
|
|
19
42
|
message,
|
|
20
43
|
[ANSWER_0, ANSWER_800, ANSWER_2000, ASK_ME_NEXT_TIME],
|
|
21
44
|
{
|
|
22
45
|
defaultAction: ASK_ME_NEXT_TIME,
|
|
23
|
-
title: translate("moduleCheckRemoteSize.titleDatabaseSizeNotify")
|
|
24
|
-
timeout: 40
|
|
46
|
+
title: translate("moduleCheckRemoteSize.titleDatabaseSizeNotify")
|
|
25
47
|
}
|
|
26
48
|
);
|
|
27
49
|
if (ret == ANSWER_0) {
|
|
@@ -49,7 +71,7 @@ function onNotifyRemoteSizeNotConfiguredFactory(host, log) {
|
|
|
49
71
|
return true;
|
|
50
72
|
};
|
|
51
73
|
}
|
|
52
|
-
function onNotifyRemoteSizeExceedFactory(host, log) {
|
|
74
|
+
function onNotifyRemoteSizeExceedFactory(host, log, mode = "notice") {
|
|
53
75
|
return async () => {
|
|
54
76
|
const translate = host.services.context.translate;
|
|
55
77
|
const settings = host.services.setting.currentSettings();
|
|
@@ -89,13 +111,28 @@ function onNotifyRemoteSizeExceedFactory(host, log) {
|
|
|
89
111
|
});
|
|
90
112
|
const ANSWER_REBUILD = translate("moduleCheckRemoteSize.optionRebuildAll");
|
|
91
113
|
const ANSWER_IGNORE = translate("moduleCheckRemoteSize.optionDismiss");
|
|
114
|
+
if (mode === "notice") {
|
|
115
|
+
host.services.API.confirm.askInPopup(
|
|
116
|
+
"remote-size-exceeded",
|
|
117
|
+
translate("moduleCheckRemoteSize.noticeExceeded", {
|
|
118
|
+
measuredSize: sizeToHumanReadable(estimatedSize),
|
|
119
|
+
notifySize: sizeToHumanReadable(maxSize)
|
|
120
|
+
}),
|
|
121
|
+
(anchor) => configureReviewAnchor(
|
|
122
|
+
anchor,
|
|
123
|
+
translate("moduleCheckRemoteSize.optionReview"),
|
|
124
|
+
() => onNotifyRemoteSizeExceedFactory(host, log, "dialogue")()
|
|
125
|
+
),
|
|
126
|
+
REMOTE_SIZE_NOTICE_DURATION_MS
|
|
127
|
+
);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
92
130
|
const ret = await host.services.API.confirm.askSelectStringDialogue(
|
|
93
131
|
message,
|
|
94
132
|
[ANSWER_ENLARGE_LIMIT, ANSWER_REBUILD, ANSWER_IGNORE],
|
|
95
133
|
{
|
|
96
134
|
defaultAction: ANSWER_IGNORE,
|
|
97
|
-
title: translate("moduleCheckRemoteSize.titleDatabaseSizeLimitExceeded")
|
|
98
|
-
timeout: 60
|
|
135
|
+
title: translate("moduleCheckRemoteSize.titleDatabaseSizeLimitExceeded")
|
|
99
136
|
}
|
|
100
137
|
);
|
|
101
138
|
if (ret == ANSWER_REBUILD) {
|
|
@@ -142,7 +179,7 @@ function onNotifyRemoteSizeExceedFactory(host, log) {
|
|
|
142
179
|
return true;
|
|
143
180
|
};
|
|
144
181
|
}
|
|
145
|
-
async function scanAllStat(host, log, resetThreshold = false) {
|
|
182
|
+
async function scanAllStat(host, log, resetThreshold = false, mode = "notice") {
|
|
146
183
|
if (resetThreshold) {
|
|
147
184
|
await host.services.setting.applyPartial(
|
|
148
185
|
{
|
|
@@ -151,8 +188,8 @@ async function scanAllStat(host, log, resetThreshold = false) {
|
|
|
151
188
|
true
|
|
152
189
|
);
|
|
153
190
|
}
|
|
154
|
-
const onNotifyNotConfigured = onNotifyRemoteSizeNotConfiguredFactory(host, log);
|
|
155
|
-
const onNotifyExceed = onNotifyRemoteSizeExceedFactory(host, log);
|
|
191
|
+
const onNotifyNotConfigured = onNotifyRemoteSizeNotConfiguredFactory(host, log, mode);
|
|
192
|
+
const onNotifyExceed = onNotifyRemoteSizeExceedFactory(host, log, mode);
|
|
156
193
|
return await onNotifyNotConfigured() && await onNotifyExceed();
|
|
157
194
|
}
|
|
158
195
|
function useCheckRemoteSize(host) {
|
|
@@ -163,10 +200,13 @@ function useCheckRemoteSize(host) {
|
|
|
163
200
|
id: "livesync-reset-remote-size-threshold-and-check",
|
|
164
201
|
name: "Reset notification threshold and check the remote database usage",
|
|
165
202
|
callback: async () => {
|
|
166
|
-
await scanAllStat(host, log, true);
|
|
203
|
+
await scanAllStat(host, log, true, "dialogue");
|
|
167
204
|
}
|
|
168
205
|
});
|
|
169
|
-
host.services.context.events.onEvent(
|
|
206
|
+
host.services.context.events.onEvent(
|
|
207
|
+
EVENT_REQUEST_CHECK_REMOTE_SIZE,
|
|
208
|
+
() => scanAllStat(host, log, true, "dialogue")
|
|
209
|
+
);
|
|
170
210
|
return Promise.resolve(true);
|
|
171
211
|
});
|
|
172
212
|
}
|
|
@@ -48,10 +48,6 @@ export declare class ServiceRebuilder extends ServiceModuleBase<ServiceRebuilder
|
|
|
48
48
|
constructor(services: ServiceRebuilderDependencies);
|
|
49
49
|
$performRebuildDB(method: "localOnly" | "remoteOnly" | "rebuildBothByThisDevice" | "localOnlyWithChunks"): Promise<void>;
|
|
50
50
|
informOptionalFeatures(): Promise<void>;
|
|
51
|
-
askUsingOptionalFeature(opt: {
|
|
52
|
-
enableFetch?: boolean;
|
|
53
|
-
enableOverwrite?: boolean;
|
|
54
|
-
}): Promise<void>;
|
|
55
51
|
rebuildRemote(): Promise<void>;
|
|
56
52
|
private performRemoteRebuild;
|
|
57
53
|
$rebuildRemote(): Promise<void>;
|
|
@@ -67,14 +67,6 @@ Please enable them from the settings screen after setup is complete.`,
|
|
|
67
67
|
["OK"]
|
|
68
68
|
);
|
|
69
69
|
}
|
|
70
|
-
async askUsingOptionalFeature(opt) {
|
|
71
|
-
if (await this.UI.confirm.askYesNoDialog(
|
|
72
|
-
"Do you want to enable extra features? If you are new to Self-hosted LiveSync, try the core feature first!",
|
|
73
|
-
{ title: "Enable extra features", defaultOption: "No", timeout: 15 }
|
|
74
|
-
) == "yes") {
|
|
75
|
-
await this.setting.suggestOptionalFeatures(opt);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
70
|
async rebuildRemote() {
|
|
79
71
|
await this.replicator.runBoundedRemoteActivity(() => this.performRemoteRebuild(), {
|
|
80
72
|
label: "rebuild-remote"
|
|
@@ -95,7 +87,7 @@ Please enable them from the settings screen after setup is complete.`,
|
|
|
95
87
|
await delay(1e3);
|
|
96
88
|
await this.replication.replicateAllToRemote(true);
|
|
97
89
|
await delay(1e3);
|
|
98
|
-
await this.replication.replicateAllToRemote(true
|
|
90
|
+
await this.replication.replicateAllToRemote(true);
|
|
99
91
|
}
|
|
100
92
|
$rebuildRemote() {
|
|
101
93
|
return this.rebuildRemote();
|
|
@@ -123,7 +115,7 @@ Please enable them from the settings screen after setup is complete.`,
|
|
|
123
115
|
await delay(1e3);
|
|
124
116
|
await this.replication.replicateAllToRemote(true);
|
|
125
117
|
await delay(1e3);
|
|
126
|
-
await this.replication.replicateAllToRemote(true
|
|
118
|
+
await this.replication.replicateAllToRemote(true);
|
|
127
119
|
}
|
|
128
120
|
$rebuildEverything() {
|
|
129
121
|
return this.rebuildEverything();
|
|
@@ -128,7 +128,7 @@ export interface IReplicationService {
|
|
|
128
128
|
databaseQueueCount: ReactiveSource<number>;
|
|
129
129
|
storageApplyingCount: ReactiveSource<number>;
|
|
130
130
|
replicationResultCount: ReactiveSource<number>;
|
|
131
|
-
replicateAllToRemote(showingNotice?: boolean
|
|
131
|
+
replicateAllToRemote(showingNotice?: boolean): Promise<boolean>;
|
|
132
132
|
replicateAllFromRemote(showingNotice?: boolean): Promise<boolean>;
|
|
133
133
|
markLocked(lockByClean?: boolean): Promise<void>;
|
|
134
134
|
markUnlocked(): Promise<void>;
|
|
@@ -189,10 +189,6 @@ export interface ISettingService {
|
|
|
189
189
|
onRealiseSetting(): Promise<boolean>;
|
|
190
190
|
suspendAllSync(): Promise<boolean>;
|
|
191
191
|
suspendExtraSync(): Promise<boolean>;
|
|
192
|
-
suggestOptionalFeatures(opt: {
|
|
193
|
-
enableFetch?: boolean;
|
|
194
|
-
enableOverwrite?: boolean;
|
|
195
|
-
}): Promise<boolean>;
|
|
196
192
|
enableOptionalFeature(mode: keyof OPTIONAL_SYNC_FEATURES): Promise<boolean>;
|
|
197
193
|
clearUsedPassphrase(): void;
|
|
198
194
|
decryptSettings(settings: ObsidianLiveSyncSettings): Promise<ObsidianLiveSyncSettings>;
|
|
@@ -85,7 +85,7 @@ export declare abstract class ReplicationService<T extends ServiceContext = Serv
|
|
|
85
85
|
storageApplyingCount: import("octagonal-wheels/dataobject/reactive_v2").ReactiveSource<number>;
|
|
86
86
|
replicationResultCount: import("octagonal-wheels/dataobject/reactive_v2").ReactiveSource<number>;
|
|
87
87
|
getActiveReplicatorFor(usage: string): false | LiveSyncAbstractReplicator;
|
|
88
|
-
replicateAllToRemote(showingNotice?: boolean
|
|
88
|
+
replicateAllToRemote(showingNotice?: boolean): Promise<boolean>;
|
|
89
89
|
replicateAllFromRemote(showingNotice?: boolean): Promise<boolean>;
|
|
90
90
|
private _getReplicatorAndPerform;
|
|
91
91
|
markLocked(lockByClean?: boolean): Promise<void>;
|
|
@@ -34,7 +34,10 @@ class ReplicationService extends ServiceBase {
|
|
|
34
34
|
this.fileProcessing = dependencies.fileProcessingService;
|
|
35
35
|
this.databaseService = dependencies.databaseService;
|
|
36
36
|
this._log = createInstanceLogFunction("ReplicationService", dependencies.APIService);
|
|
37
|
-
this._unresolvedErrorManager = new UnresolvedErrorManager(
|
|
37
|
+
this._unresolvedErrorManager = new UnresolvedErrorManager(
|
|
38
|
+
dependencies.appLifecycleService,
|
|
39
|
+
this.context.events
|
|
40
|
+
);
|
|
38
41
|
}
|
|
39
42
|
/**
|
|
40
43
|
* Process a synchronisation result document.
|
|
@@ -183,7 +186,7 @@ class ReplicationService extends ServiceBase {
|
|
|
183
186
|
}
|
|
184
187
|
return activeReplicator;
|
|
185
188
|
}
|
|
186
|
-
async replicateAllToRemote(showingNotice = false
|
|
189
|
+
async replicateAllToRemote(showingNotice = false) {
|
|
187
190
|
if (!this.appLifecycleService.isReady()) return false;
|
|
188
191
|
if (!await this.onBeforeReplicate(showingNotice)) {
|
|
189
192
|
this._log(this.context.translate("Replicator.Message.SomeModuleFailed"), LOG_LEVEL_NOTICE);
|
|
@@ -194,19 +197,6 @@ class ReplicationService extends ServiceBase {
|
|
|
194
197
|
if (!activeReplicator) {
|
|
195
198
|
return false;
|
|
196
199
|
}
|
|
197
|
-
if (!sendChunksInBulkDisabled) {
|
|
198
|
-
if (activeReplicator?.isChunkSendingSupported) {
|
|
199
|
-
if (await this.APIService.confirm.askYesNoDialog(
|
|
200
|
-
"Do you want to send all chunks before replication?",
|
|
201
|
-
{
|
|
202
|
-
defaultOption: "No",
|
|
203
|
-
timeout: 20
|
|
204
|
-
}
|
|
205
|
-
) == "yes") {
|
|
206
|
-
await activeReplicator.sendChunks(currentSettings, void 0, true, 0);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
200
|
const ret = await activeReplicator.replicateAllToServer(currentSettings, showingNotice);
|
|
211
201
|
if (ret) return true;
|
|
212
202
|
const checkResult = await this.checkConnectionFailure();
|
|
@@ -82,16 +82,8 @@ export declare abstract class SettingService<T extends ServiceContext = ServiceC
|
|
|
82
82
|
* Suspend extra synchronisation activities, e.g., hidden files sync.
|
|
83
83
|
*/
|
|
84
84
|
readonly suspendExtraSync: import("../lib/HandlerUtils.js").BooleanMultipleHandlerFunction<() => Promise<boolean>>;
|
|
85
|
-
/**
|
|
86
|
-
* Suggest enabling optional features to the user.
|
|
87
|
-
*/
|
|
88
|
-
readonly suggestOptionalFeatures: import("../lib/HandlerUtils.js").BooleanMultipleHandlerFunction<(opt: {
|
|
89
|
-
enableFetch?: boolean;
|
|
90
|
-
enableOverwrite?: boolean;
|
|
91
|
-
}) => Promise<boolean>>;
|
|
92
85
|
/**
|
|
93
86
|
* Enable an optional feature and save to the settings.
|
|
94
|
-
* It may also raised from `handleSuggestOptionalFeatures` if the user agrees.
|
|
95
87
|
* @param mode The optional feature to enable.
|
|
96
88
|
*/
|
|
97
89
|
readonly enableOptionalFeature: import("../lib/HandlerUtils.js").BooleanMultipleHandlerFunction<(mode: keyof OPTIONAL_SYNC_FEATURES) => Promise<boolean>>;
|
|
@@ -287,13 +287,8 @@ class SettingService extends ServiceBase {
|
|
|
287
287
|
* Suspend extra synchronisation activities, e.g., hidden files sync.
|
|
288
288
|
*/
|
|
289
289
|
suspendExtraSync = handlers().all("suspendExtraSync");
|
|
290
|
-
/**
|
|
291
|
-
* Suggest enabling optional features to the user.
|
|
292
|
-
*/
|
|
293
|
-
suggestOptionalFeatures = handlers().all("suggestOptionalFeatures");
|
|
294
290
|
/**
|
|
295
291
|
* Enable an optional feature and save to the settings.
|
|
296
|
-
* It may also raised from `handleSuggestOptionalFeatures` if the user agrees.
|
|
297
292
|
* @param mode The optional feature to enable.
|
|
298
293
|
*/
|
|
299
294
|
enableOptionalFeature = handlers().all("enableOptionalFeature");
|
|
@@ -2,7 +2,7 @@ import type { ServiceContext } from "../../base/ServiceBase.js";
|
|
|
2
2
|
import { InjectableAPIService } from "../injectable/InjectableAPIService.js";
|
|
3
3
|
import type { FetchHttpHandler } from "@smithy/fetch-http-handler";
|
|
4
4
|
import type { ICommandCompat } from "../../base/IService.js";
|
|
5
|
-
import type { Confirm } from "../../../interfaces/Confirm.js";
|
|
5
|
+
import type { Confirm, ConfirmActionLayout } from "../../../interfaces/Confirm.js";
|
|
6
6
|
/**
|
|
7
7
|
* Headless implementation of Confirm that returns sensible defaults instead
|
|
8
8
|
* of throwing. Dialogs are logged to stderr so the prompts are visible in
|
|
@@ -23,7 +23,7 @@ export declare class HeadlessConfirm implements Confirm {
|
|
|
23
23
|
timeout?: number;
|
|
24
24
|
}): Promise<T[number] | false>;
|
|
25
25
|
askInPopup(key: string, dialogText: string, anchorCallback: (anchor: HTMLAnchorElement) => void, durationMs?: number): void;
|
|
26
|
-
confirmWithMessage(title: string, contentMd: string, buttons: string[], defaultAction: (typeof buttons)[number], timeout?: number): Promise<(typeof buttons)[number] | false>;
|
|
26
|
+
confirmWithMessage(title: string, contentMd: string, buttons: string[], defaultAction: (typeof buttons)[number], timeout?: number, _actionLayout?: ConfirmActionLayout): Promise<(typeof buttons)[number] | false>;
|
|
27
27
|
}
|
|
28
28
|
export declare class HeadlessAPIService<T extends ServiceContext> extends InjectableAPIService<T> {
|
|
29
29
|
private _confirmInstance;
|
|
@@ -26,7 +26,7 @@ class HeadlessConfirm {
|
|
|
26
26
|
askInPopup(key, dialogText, anchorCallback, durationMs) {
|
|
27
27
|
console.error(`[Headless] Popup (${key}): ${dialogText}`);
|
|
28
28
|
}
|
|
29
|
-
confirmWithMessage(title, contentMd, buttons, defaultAction, timeout) {
|
|
29
|
+
confirmWithMessage(title, contentMd, buttons, defaultAction, timeout, _actionLayout) {
|
|
30
30
|
console.error(`[Headless] ${title}: ${contentMd} \u2192 ${defaultAction}`);
|
|
31
31
|
return Promise.resolve(defaultAction);
|
|
32
32
|
}
|