mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2025-12-20 13:11:29 +00:00
## 0.24.16
### Improved #### Peer-to-Peer - Now peer-to-peer synchronisation checks the settings are compatible with each other. - Peer-to-peer synchronisation now handles the platform and detects pseudo-clients. #### General - New migration method has been implemented, that called `Doctor`. - The minimum interval for replication to be caused when an event occurs can now be configurable. - Some detail note has been added and change nuance about the `Report` in the setting dialogue, which had less informative. ### Behaviour and default changed - `Compute revisions for chunks` are backed into enabled again. it is necessary for garbage collection of chunks. ### Refactored - Platform specific codes are more separated. No longer `node` modules were used in the browser and Obsidian.
This commit is contained in:
@@ -18,6 +18,8 @@ export const EVENT_REQUEST_OPEN_PLUGIN_SYNC_DIALOG = "request-open-plugin-sync-d
|
|||||||
export const EVENT_REQUEST_OPEN_P2P = "request-open-p2p";
|
export const EVENT_REQUEST_OPEN_P2P = "request-open-p2p";
|
||||||
export const EVENT_REQUEST_CLOSE_P2P = "request-close-p2p";
|
export const EVENT_REQUEST_CLOSE_P2P = "request-close-p2p";
|
||||||
|
|
||||||
|
export const EVENT_REQUEST_RUN_DOCTOR = "request-run-doctor";
|
||||||
|
|
||||||
// export const EVENT_FILE_CHANGED = "file-changed";
|
// export const EVENT_FILE_CHANGED = "file-changed";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@@ -33,6 +35,7 @@ declare global {
|
|||||||
[EVENT_REQUEST_OPEN_P2P]: undefined;
|
[EVENT_REQUEST_OPEN_P2P]: undefined;
|
||||||
[EVENT_REQUEST_OPEN_SETUP_URI]: undefined;
|
[EVENT_REQUEST_OPEN_SETUP_URI]: undefined;
|
||||||
[EVENT_REQUEST_COPY_SETUP_URI]: undefined;
|
[EVENT_REQUEST_COPY_SETUP_URI]: undefined;
|
||||||
|
[EVENT_REQUEST_RUN_DOCTOR]: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import { sameChangePairs } from "./stores.ts";
|
|||||||
import type { KeyValueDatabase } from "./KeyValueDB.ts";
|
import type { KeyValueDatabase } from "./KeyValueDB.ts";
|
||||||
import { scheduleTask } from "octagonal-wheels/concurrency/task";
|
import { scheduleTask } from "octagonal-wheels/concurrency/task";
|
||||||
import { EVENT_PLUGIN_UNLOADED, eventHub } from "./events.ts";
|
import { EVENT_PLUGIN_UNLOADED, eventHub } from "./events.ts";
|
||||||
|
import { promiseWithResolver, type PromiseWithResolvers } from "octagonal-wheels/promises";
|
||||||
|
|
||||||
export { scheduleTask, cancelTask, cancelAllTasks } from "../lib/src/concurrency/task.ts";
|
export { scheduleTask, cancelTask, cancelAllTasks } from "../lib/src/concurrency/task.ts";
|
||||||
|
|
||||||
@@ -493,3 +494,47 @@ export function onlyInNTimes(n: number, proc: (progress: number) => any) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const waitingTasks = {} as Record<string, { task?: PromiseWithResolvers<any>; previous: number; leastNext: number }>;
|
||||||
|
|
||||||
|
export function rateLimitedSharedExecution<T>(key: string, interval: number, proc: () => Promise<T>): Promise<T> {
|
||||||
|
if (!(key in waitingTasks)) {
|
||||||
|
waitingTasks[key] = { task: undefined, previous: 0, leastNext: 0 };
|
||||||
|
}
|
||||||
|
if (waitingTasks[key].task) {
|
||||||
|
// Extend the previous execution time.
|
||||||
|
waitingTasks[key].leastNext = Date.now() + interval;
|
||||||
|
return waitingTasks[key].task.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
const previous = waitingTasks[key].previous;
|
||||||
|
|
||||||
|
const delay = previous == 0 ? 0 : Math.max(interval - (Date.now() - previous), 0);
|
||||||
|
|
||||||
|
const task = promiseWithResolver<T>();
|
||||||
|
void task.promise.finally(() => {
|
||||||
|
if (waitingTasks[key].task === task) {
|
||||||
|
waitingTasks[key].task = undefined;
|
||||||
|
waitingTasks[key].previous = Math.max(Date.now(), waitingTasks[key].leastNext);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
waitingTasks[key] = {
|
||||||
|
task,
|
||||||
|
previous: Date.now(),
|
||||||
|
leastNext: Date.now() + interval,
|
||||||
|
};
|
||||||
|
void scheduleTask("thin-out-" + key, delay, async () => {
|
||||||
|
try {
|
||||||
|
task.resolve(await proc());
|
||||||
|
} catch (ex) {
|
||||||
|
task.reject(ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return task.promise;
|
||||||
|
}
|
||||||
|
export function updatePreviousExecutionTime(key: string, timeDelta: number = 0) {
|
||||||
|
if (!(key in waitingTasks)) {
|
||||||
|
waitingTasks[key] = { task: undefined, previous: 0, leastNext: 0 };
|
||||||
|
}
|
||||||
|
waitingTasks[key].leastNext = Math.max(Date.now() + timeDelta, waitingTasks[key].leastNext);
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import { reactiveSource } from "octagonal-wheels/dataobject/reactive_v2";
|
|||||||
import type { Confirm } from "../../lib/src/interfaces/Confirm.ts";
|
import type { Confirm } from "../../lib/src/interfaces/Confirm.ts";
|
||||||
import type ObsidianLiveSyncPlugin from "../../main.ts";
|
import type ObsidianLiveSyncPlugin from "../../main.ts";
|
||||||
import type { SimpleStore } from "octagonal-wheels/databases/SimpleStoreBase";
|
import type { SimpleStore } from "octagonal-wheels/databases/SimpleStoreBase";
|
||||||
|
import { getPlatformName } from "../../lib/src/PlatformAPIs/obsidian/Environment.ts";
|
||||||
|
|
||||||
class P2PReplicatorCommandBase extends LiveSyncCommands implements P2PReplicatorBase {
|
class P2PReplicatorCommandBase extends LiveSyncCommands implements P2PReplicatorBase {
|
||||||
storeP2PStatusLine = reactiveSource("");
|
storeP2PStatusLine = reactiveSource("");
|
||||||
@@ -79,6 +80,9 @@ export class P2PReplicator
|
|||||||
}
|
}
|
||||||
return undefined!;
|
return undefined!;
|
||||||
}
|
}
|
||||||
|
override getPlatform(): string {
|
||||||
|
return getPlatformName();
|
||||||
|
}
|
||||||
|
|
||||||
override onunload(): void {
|
override onunload(): void {
|
||||||
removeP2PReplicatorInstance();
|
removeP2PReplicatorInstance();
|
||||||
|
|||||||
@@ -299,6 +299,8 @@
|
|||||||
placeholder="anything-you-like"
|
placeholder="anything-you-like"
|
||||||
bind:value={eRoomId}
|
bind:value={eRoomId}
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
|
spellcheck="false"
|
||||||
|
autocorrect="off"
|
||||||
/>
|
/>
|
||||||
<button onclick={() => chooseRandom()}> Use Random Number </button>
|
<button onclick={() => chooseRandom()}> Use Random Number </button>
|
||||||
</label>
|
</label>
|
||||||
@@ -327,6 +329,12 @@
|
|||||||
<label class={{ "is-dirty": isDeviceNameModified }}>
|
<label class={{ "is-dirty": isDeviceNameModified }}>
|
||||||
<input type="text" placeholder="iphone-16" bind:value={eDeviceName} autocomplete="off" />
|
<input type="text" placeholder="iphone-16" bind:value={eDeviceName} autocomplete="off" />
|
||||||
</label>
|
</label>
|
||||||
|
<span>
|
||||||
|
<small>
|
||||||
|
Device name to identify the device. Please use shorter one for the stable peer
|
||||||
|
detection, i.e., "iphone-16" or "macbook-2021".
|
||||||
|
</small>
|
||||||
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
2
src/lib
2
src/lib
Submodule src/lib updated: 2a0dd3c3ac...9cf9bb6f1f
@@ -570,6 +570,9 @@ export default class ObsidianLiveSyncPlugin
|
|||||||
$$replicate(showMessage: boolean = false): Promise<boolean | void> {
|
$$replicate(showMessage: boolean = false): Promise<boolean | void> {
|
||||||
throwShouldBeOverridden();
|
throwShouldBeOverridden();
|
||||||
}
|
}
|
||||||
|
$$replicateByEvent(showMessage: boolean = false): Promise<boolean | void> {
|
||||||
|
throwShouldBeOverridden();
|
||||||
|
}
|
||||||
|
|
||||||
$everyOnDatabaseInitialized(showingNotice: boolean): Promise<boolean> {
|
$everyOnDatabaseInitialized(showingNotice: boolean): Promise<boolean> {
|
||||||
throwShouldBeOverridden();
|
throwShouldBeOverridden();
|
||||||
@@ -636,10 +639,6 @@ export default class ObsidianLiveSyncPlugin
|
|||||||
throwShouldBeOverridden();
|
throwShouldBeOverridden();
|
||||||
}
|
}
|
||||||
|
|
||||||
$$waitForReplicationOnce(): Promise<boolean | void> {
|
|
||||||
throwShouldBeOverridden();
|
|
||||||
}
|
|
||||||
|
|
||||||
$$resetLocalDatabase(): Promise<void> {
|
$$resetLocalDatabase(): Promise<void> {
|
||||||
throwShouldBeOverridden();
|
throwShouldBeOverridden();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,17 +18,26 @@ import {
|
|||||||
type MetaEntry,
|
type MetaEntry,
|
||||||
} from "../../lib/src/common/types";
|
} from "../../lib/src/common/types";
|
||||||
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
|
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
|
||||||
import { getPath, isChunk, isValidPath, scheduleTask } from "../../common/utils";
|
import {
|
||||||
|
getPath,
|
||||||
|
isChunk,
|
||||||
|
isValidPath,
|
||||||
|
rateLimitedSharedExecution,
|
||||||
|
scheduleTask,
|
||||||
|
updatePreviousExecutionTime,
|
||||||
|
} from "../../common/utils";
|
||||||
import { isAnyNote } from "../../lib/src/common/utils";
|
import { isAnyNote } from "../../lib/src/common/utils";
|
||||||
import { EVENT_FILE_SAVED, eventHub } from "../../common/events";
|
import { EVENT_FILE_SAVED, eventHub } from "../../common/events";
|
||||||
import type { LiveSyncAbstractReplicator } from "../../lib/src/replication/LiveSyncAbstractReplicator";
|
import type { LiveSyncAbstractReplicator } from "../../lib/src/replication/LiveSyncAbstractReplicator";
|
||||||
import { globalSlipBoard } from "../../lib/src/bureau/bureau";
|
import { globalSlipBoard } from "../../lib/src/bureau/bureau";
|
||||||
|
|
||||||
|
const KEY_REPLICATION_ON_EVENT = "replicationOnEvent";
|
||||||
|
const REPLICATION_ON_EVENT_FORECASTED_TIME = 5000;
|
||||||
export class ModuleReplicator extends AbstractModule implements ICoreModule {
|
export class ModuleReplicator extends AbstractModule implements ICoreModule {
|
||||||
$everyOnloadAfterLoadSettings(): Promise<boolean> {
|
$everyOnloadAfterLoadSettings(): Promise<boolean> {
|
||||||
eventHub.onEvent(EVENT_FILE_SAVED, () => {
|
eventHub.onEvent(EVENT_FILE_SAVED, () => {
|
||||||
if (this.settings.syncOnSave && !this.core.$$isSuspended()) {
|
if (this.settings.syncOnSave && !this.core.$$isSuspended()) {
|
||||||
scheduleTask("perform-replicate-after-save", 250, () => this.core.$$waitForReplicationOnce());
|
scheduleTask("perform-replicate-after-save", 250, () => this.core.$$replicateByEvent());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
@@ -61,7 +70,16 @@ export class ModuleReplicator extends AbstractModule implements ICoreModule {
|
|||||||
await this.loadQueuedFiles();
|
await this.loadQueuedFiles();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async $$replicate(showMessage: boolean = false): Promise<boolean | void> {
|
async $$replicate(showMessage: boolean = false): Promise<boolean | void> {
|
||||||
|
try {
|
||||||
|
updatePreviousExecutionTime(KEY_REPLICATION_ON_EVENT, REPLICATION_ON_EVENT_FORECASTED_TIME);
|
||||||
|
return await this.$$_replicate(showMessage);
|
||||||
|
} finally {
|
||||||
|
updatePreviousExecutionTime(KEY_REPLICATION_ON_EVENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async $$_replicate(showMessage: boolean = false): Promise<boolean | void> {
|
||||||
//--?
|
//--?
|
||||||
if (!this.core.$$isReady()) return;
|
if (!this.core.$$isReady()) return;
|
||||||
if (isLockAcquired("cleanup")) {
|
if (isLockAcquired("cleanup")) {
|
||||||
@@ -192,6 +210,15 @@ Or if you are sure know what had been happened, we can unlock the database from
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async $$replicateByEvent(): Promise<boolean | void> {
|
||||||
|
const least = this.settings.syncMinimumInterval;
|
||||||
|
if (least > 0) {
|
||||||
|
return rateLimitedSharedExecution(KEY_REPLICATION_ON_EVENT, least, async () => {
|
||||||
|
return await this.$$replicate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return await shareRunningResult(`replication`, () => this.core.$$replicate());
|
||||||
|
}
|
||||||
$$parseReplicationResult(docs: Array<PouchDB.Core.ExistingDocument<EntryDoc>>): void {
|
$$parseReplicationResult(docs: Array<PouchDB.Core.ExistingDocument<EntryDoc>>): void {
|
||||||
if (this.settings.suspendParseReplicationResult && !this.replicationResultProcessor.isSuspended) {
|
if (this.settings.suspendParseReplicationResult && !this.replicationResultProcessor.isSuspended) {
|
||||||
this.replicationResultProcessor.suspend();
|
this.replicationResultProcessor.suspend();
|
||||||
@@ -416,8 +443,4 @@ Or if you are sure know what had been happened, we can unlock the database from
|
|||||||
if (checkResult == "CHECKAGAIN") return await this.core.$$replicateAllFromServer(showingNotice);
|
if (checkResult == "CHECKAGAIN") return await this.core.$$replicateAllFromServer(showingNotice);
|
||||||
return !checkResult;
|
return !checkResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
async $$waitForReplicationOnce(): Promise<boolean | void> {
|
|
||||||
return await shareRunningResult(`replication`, () => this.core.$$replicate());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ export class ModuleConflictResolver extends AbstractModule implements ICoreModul
|
|||||||
//auto resolved, but need check again;
|
//auto resolved, but need check again;
|
||||||
if (this.settings.syncAfterMerge && !this.core.$$isSuspended()) {
|
if (this.settings.syncAfterMerge && !this.core.$$isSuspended()) {
|
||||||
//Wait for the running replication, if not running replication, run it once.
|
//Wait for the running replication, if not running replication, run it once.
|
||||||
await this.core.$$waitForReplicationOnce();
|
await this.core.$$replicateByEvent();
|
||||||
}
|
}
|
||||||
this._log("[conflict] Automatically merged, but we have to check it again");
|
this._log("[conflict] Automatically merged, but we have to check it again");
|
||||||
await this.core.$$queueConflictCheck(filename);
|
await this.core.$$queueConflictCheck(filename);
|
||||||
|
|||||||
@@ -1,17 +1,141 @@
|
|||||||
import { LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE } from "octagonal-wheels/common/logger.js";
|
import { LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE } from "octagonal-wheels/common/logger.js";
|
||||||
import { SETTING_VERSION_SUPPORT_CASE_INSENSITIVE } from "../../lib/src/common/types.js";
|
import { type ObsidianLiveSyncSettings } from "../../lib/src/common/types.js";
|
||||||
import {
|
import {
|
||||||
EVENT_REQUEST_OPEN_P2P,
|
EVENT_REQUEST_OPEN_P2P,
|
||||||
EVENT_REQUEST_OPEN_SETTING_WIZARD,
|
EVENT_REQUEST_OPEN_SETTING_WIZARD,
|
||||||
EVENT_REQUEST_OPEN_SETTINGS,
|
EVENT_REQUEST_OPEN_SETTINGS,
|
||||||
EVENT_REQUEST_OPEN_SETUP_URI,
|
EVENT_REQUEST_OPEN_SETUP_URI,
|
||||||
|
EVENT_REQUEST_RUN_DOCTOR,
|
||||||
eventHub,
|
eventHub,
|
||||||
} from "../../common/events.ts";
|
} from "../../common/events.ts";
|
||||||
import { AbstractModule } from "../AbstractModule.ts";
|
import { AbstractModule } from "../AbstractModule.ts";
|
||||||
import type { ICoreModule } from "../ModuleTypes.ts";
|
import type { ICoreModule } from "../ModuleTypes.ts";
|
||||||
import { $msg } from "src/lib/src/common/i18n.ts";
|
import { $msg } from "src/lib/src/common/i18n.ts";
|
||||||
|
import { checkUnsuitableValues, RuleLevel, type RuleForType } from "../../lib/src/common/configForDoc.ts";
|
||||||
|
import { getConfName, type AllSettingItemKey } from "../features/SettingDialogue/settingConstants.ts";
|
||||||
|
|
||||||
export class ModuleMigration extends AbstractModule implements ICoreModule {
|
export class ModuleMigration extends AbstractModule implements ICoreModule {
|
||||||
|
async migrateUsingDoctor(skipRebuild: boolean = false, activateReason = "updated", forceRescan = false) {
|
||||||
|
const r = checkUnsuitableValues(this.core.settings);
|
||||||
|
if (!forceRescan && r.version == this.settings.doctorProcessedVersion) {
|
||||||
|
const isIssueFound = Object.keys(r.rules).length > 0;
|
||||||
|
const msg = isIssueFound ? "Issues found" : "No issues found";
|
||||||
|
this._log(`${msg} but marked as to be silent`, LOG_LEVEL_VERBOSE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const issues = Object.entries(r.rules);
|
||||||
|
if (issues.length == 0) {
|
||||||
|
this._log($msg("Doctor.Message.NoIssues"), LOG_LEVEL_NOTICE);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const OPT_YES = `${$msg("Doctor.Button.Yes")}` as const;
|
||||||
|
const OPT_NO = `${$msg("Doctor.Button.No")}` as const;
|
||||||
|
const OPT_DISMISS = `${$msg("Doctor.Button.DismissThisVersion")}` as const;
|
||||||
|
// this._log(`Issues found in ${key}`, LOG_LEVEL_VERBOSE);
|
||||||
|
const issues = Object.keys(r.rules)
|
||||||
|
.map((key) => `- ${getConfName(key as AllSettingItemKey)}`)
|
||||||
|
.join("\n");
|
||||||
|
const msg = await this.core.confirm.askSelectStringDialogue(
|
||||||
|
$msg("Doctor.Dialogue.Main", { activateReason, issues }),
|
||||||
|
[OPT_YES, OPT_NO, OPT_DISMISS],
|
||||||
|
{
|
||||||
|
title: $msg("Doctor.Dialogue.Title"),
|
||||||
|
defaultAction: OPT_YES,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (msg == OPT_DISMISS) {
|
||||||
|
this.settings.doctorProcessedVersion = r.version;
|
||||||
|
await this.core.saveSettings();
|
||||||
|
this._log("Marked as to be silent", LOG_LEVEL_VERBOSE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (msg != OPT_YES) return;
|
||||||
|
let shouldRebuild = false;
|
||||||
|
let shouldRebuildLocal = false;
|
||||||
|
const issueItems = Object.entries(r.rules) as [keyof ObsidianLiveSyncSettings, RuleForType<any>][];
|
||||||
|
this._log(`${issueItems.length} Issue(s) found `, LOG_LEVEL_VERBOSE);
|
||||||
|
let idx = 0;
|
||||||
|
const applySettings = {} as Partial<ObsidianLiveSyncSettings>;
|
||||||
|
const OPT_FIX = `${$msg("Doctor.Button.Fix")}` as const;
|
||||||
|
const OPT_SKIP = `${$msg("Doctor.Button.Skip")}` as const;
|
||||||
|
const OPT_FIXBUTNOREBUILD = `${$msg("Doctor.Button.FixButNoRebuild")}` as const;
|
||||||
|
let skipped = 0;
|
||||||
|
for (const [key, value] of issueItems) {
|
||||||
|
const levelMap = {
|
||||||
|
[RuleLevel.Necessary]: $msg("Doctor.Level.Necessary"),
|
||||||
|
[RuleLevel.Recommended]: $msg("Doctor.Level.Recommended"),
|
||||||
|
[RuleLevel.Optional]: $msg("Doctor.Level.Optional"),
|
||||||
|
[RuleLevel.Must]: $msg("Doctor.Level.Must"),
|
||||||
|
};
|
||||||
|
const level = value.level ? levelMap[value.level] : "Unknown";
|
||||||
|
const options = [OPT_FIX];
|
||||||
|
if ((!skipRebuild && value.requireRebuild) || value.requireRebuildLocal) {
|
||||||
|
options.push(OPT_FIXBUTNOREBUILD);
|
||||||
|
}
|
||||||
|
options.push(OPT_SKIP);
|
||||||
|
const note = skipRebuild
|
||||||
|
? ""
|
||||||
|
: `${value.requireRebuild ? $msg("Doctor.Message.RebuildRequired") : ""}${value.requireRebuildLocal ? $msg("Doctor.Message.RebuildLocalRequired") : ""}`;
|
||||||
|
|
||||||
|
const ret = await this.core.confirm.askSelectStringDialogue(
|
||||||
|
$msg("Doctor.Dialogue.MainFix", {
|
||||||
|
name: getConfName(key as AllSettingItemKey),
|
||||||
|
current: `${this.settings[key]}`,
|
||||||
|
reason: value.reason ?? " N/A ",
|
||||||
|
ideal: `${value.value}`,
|
||||||
|
level: `${level}`,
|
||||||
|
note: note,
|
||||||
|
}),
|
||||||
|
options,
|
||||||
|
{
|
||||||
|
title: $msg("Doctor.Dialogue.TitleFix", { current: `${++idx}`, total: `${issueItems.length}` }),
|
||||||
|
defaultAction: OPT_FIX,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ret == OPT_FIX || ret == OPT_FIXBUTNOREBUILD) {
|
||||||
|
//@ts-ignore
|
||||||
|
applySettings[key] = value.value;
|
||||||
|
if (ret == OPT_FIX) {
|
||||||
|
shouldRebuild = shouldRebuild || value.requireRebuild || false;
|
||||||
|
shouldRebuildLocal = shouldRebuildLocal || value.requireRebuildLocal || false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
skipped++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Object.keys(applySettings).length > 0) {
|
||||||
|
this.settings = {
|
||||||
|
...this.settings,
|
||||||
|
...applySettings,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (skipped == 0) {
|
||||||
|
this.settings.doctorProcessedVersion = r.version;
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
(await this.core.confirm.askYesNoDialog($msg("Doctor.Message.SomeSkipped"), {
|
||||||
|
title: $msg("Doctor.Dialogue.TitleAlmostDone"),
|
||||||
|
defaultOption: "No",
|
||||||
|
})) == "no"
|
||||||
|
) {
|
||||||
|
// Some skipped, and user wants
|
||||||
|
this.settings.doctorProcessedVersion = r.version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.core.saveSettings();
|
||||||
|
if (!skipRebuild) {
|
||||||
|
if (shouldRebuild) {
|
||||||
|
await this.core.rebuilder.scheduleRebuild();
|
||||||
|
await this.core.$$performRestart();
|
||||||
|
} else if (shouldRebuildLocal) {
|
||||||
|
await this.core.rebuilder.scheduleFetch();
|
||||||
|
await this.core.$$performRestart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async migrateDisableBulkSend() {
|
async migrateDisableBulkSend() {
|
||||||
if (this.settings.sendChunksBulk) {
|
if (this.settings.sendChunksBulk) {
|
||||||
this._log($msg("moduleMigration.logBulkSendCorrupted"), LOG_LEVEL_NOTICE);
|
this._log($msg("moduleMigration.logBulkSendCorrupted"), LOG_LEVEL_NOTICE);
|
||||||
@@ -20,157 +144,157 @@ export class ModuleMigration extends AbstractModule implements ICoreModule {
|
|||||||
await this.saveSettings();
|
await this.saveSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async migrationCheck() {
|
// async migrationCheck() {
|
||||||
const old = this.settings.settingVersion;
|
// const old = this.settings.settingVersion;
|
||||||
const current = SETTING_VERSION_SUPPORT_CASE_INSENSITIVE;
|
// const current = SETTING_VERSION_SUPPORT_CASE_INSENSITIVE;
|
||||||
// Check each migrations(old -> current)
|
// // Check each migrations(old -> current)
|
||||||
if (!(await this.migrateToCaseInsensitive(old, current))) {
|
// if (!(await this.migrateToCaseInsensitive(old, current))) {
|
||||||
this._log(
|
// this._log(
|
||||||
$msg("moduleMigration.logMigrationFailed", {
|
// $msg("moduleMigration.logMigrationFailed", {
|
||||||
old: old.toString(),
|
// old: old.toString(),
|
||||||
current: current.toString(),
|
// current: current.toString(),
|
||||||
}),
|
// }),
|
||||||
LOG_LEVEL_NOTICE
|
// LOG_LEVEL_NOTICE
|
||||||
);
|
// );
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
async migrateToCaseInsensitive(old: number, current: number) {
|
// async migrateToCaseInsensitive(old: number, current: number) {
|
||||||
if (
|
// if (
|
||||||
this.settings.handleFilenameCaseSensitive !== undefined &&
|
// this.settings.handleFilenameCaseSensitive !== undefined &&
|
||||||
this.settings.doNotUseFixedRevisionForChunks !== undefined
|
// this.settings.doNotUseFixedRevisionForChunks !== undefined
|
||||||
) {
|
// ) {
|
||||||
if (current < SETTING_VERSION_SUPPORT_CASE_INSENSITIVE) {
|
// if (current < SETTING_VERSION_SUPPORT_CASE_INSENSITIVE) {
|
||||||
this.settings.settingVersion = SETTING_VERSION_SUPPORT_CASE_INSENSITIVE;
|
// this.settings.settingVersion = SETTING_VERSION_SUPPORT_CASE_INSENSITIVE;
|
||||||
await this.saveSettings();
|
// await this.saveSettings();
|
||||||
}
|
// }
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
if (
|
// if (
|
||||||
old >= SETTING_VERSION_SUPPORT_CASE_INSENSITIVE &&
|
// old >= SETTING_VERSION_SUPPORT_CASE_INSENSITIVE &&
|
||||||
this.settings.handleFilenameCaseSensitive !== undefined &&
|
// this.settings.handleFilenameCaseSensitive !== undefined &&
|
||||||
this.settings.doNotUseFixedRevisionForChunks !== undefined
|
// this.settings.doNotUseFixedRevisionForChunks !== undefined
|
||||||
) {
|
// ) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
let remoteHandleFilenameCaseSensitive: undefined | boolean = undefined;
|
// let remoteHandleFilenameCaseSensitive: undefined | boolean = undefined;
|
||||||
let remoteDoNotUseFixedRevisionForChunks: undefined | boolean = undefined;
|
// let remoteDoNotUseFixedRevisionForChunks: undefined | boolean = undefined;
|
||||||
let remoteChecked = false;
|
// let remoteChecked = false;
|
||||||
try {
|
// try {
|
||||||
const remoteInfo = await this.core.replicator.getRemotePreferredTweakValues(this.settings);
|
// const remoteInfo = await this.core.replicator.getRemotePreferredTweakValues(this.settings);
|
||||||
if (remoteInfo) {
|
// if (remoteInfo) {
|
||||||
remoteHandleFilenameCaseSensitive =
|
// remoteHandleFilenameCaseSensitive =
|
||||||
"handleFilenameCaseSensitive" in remoteInfo ? remoteInfo.handleFilenameCaseSensitive : false;
|
// "handleFilenameCaseSensitive" in remoteInfo ? remoteInfo.handleFilenameCaseSensitive : false;
|
||||||
remoteDoNotUseFixedRevisionForChunks =
|
// remoteDoNotUseFixedRevisionForChunks =
|
||||||
"doNotUseFixedRevisionForChunks" in remoteInfo ? remoteInfo.doNotUseFixedRevisionForChunks : false;
|
// "doNotUseFixedRevisionForChunks" in remoteInfo ? remoteInfo.doNotUseFixedRevisionForChunks : false;
|
||||||
if (
|
// if (
|
||||||
remoteHandleFilenameCaseSensitive !== undefined ||
|
// remoteHandleFilenameCaseSensitive !== undefined ||
|
||||||
remoteDoNotUseFixedRevisionForChunks !== undefined
|
// remoteDoNotUseFixedRevisionForChunks !== undefined
|
||||||
) {
|
// ) {
|
||||||
remoteChecked = true;
|
// remoteChecked = true;
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
this._log($msg("moduleMigration.logFetchRemoteTweakFailed"), LOG_LEVEL_INFO);
|
// this._log($msg("moduleMigration.logFetchRemoteTweakFailed"), LOG_LEVEL_INFO);
|
||||||
}
|
// }
|
||||||
} catch (ex) {
|
// } catch (ex) {
|
||||||
this._log($msg("moduleMigration.logRemoteTweakUnavailable"), LOG_LEVEL_INFO);
|
// this._log($msg("moduleMigration.logRemoteTweakUnavailable"), LOG_LEVEL_INFO);
|
||||||
this._log(ex, LOG_LEVEL_VERBOSE);
|
// this._log(ex, LOG_LEVEL_VERBOSE);
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (remoteChecked) {
|
// if (remoteChecked) {
|
||||||
// The case that the remote could be checked.
|
// // The case that the remote could be checked.
|
||||||
if (remoteHandleFilenameCaseSensitive && remoteDoNotUseFixedRevisionForChunks) {
|
// if (remoteHandleFilenameCaseSensitive && remoteDoNotUseFixedRevisionForChunks) {
|
||||||
// Migrated, but configured as same as old behaviour.
|
// // Migrated, but configured as same as old behaviour.
|
||||||
this.settings.handleFilenameCaseSensitive = true;
|
// this.settings.handleFilenameCaseSensitive = true;
|
||||||
this.settings.doNotUseFixedRevisionForChunks = true;
|
// this.settings.doNotUseFixedRevisionForChunks = true;
|
||||||
this.settings.settingVersion = SETTING_VERSION_SUPPORT_CASE_INSENSITIVE;
|
// this.settings.settingVersion = SETTING_VERSION_SUPPORT_CASE_INSENSITIVE;
|
||||||
this._log(
|
// this._log(
|
||||||
$msg("moduleMigration.logMigratedSameBehaviour", {
|
// $msg("moduleMigration.logMigratedSameBehaviour", {
|
||||||
current: current.toString(),
|
// current: current.toString(),
|
||||||
}),
|
// }),
|
||||||
LOG_LEVEL_INFO
|
// LOG_LEVEL_INFO
|
||||||
);
|
// );
|
||||||
await this.saveSettings();
|
// await this.saveSettings();
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
const message = $msg("moduleMigration.msgFetchRemoteAgain");
|
// const message = $msg("moduleMigration.msgFetchRemoteAgain");
|
||||||
const OPTION_FETCH = $msg("moduleMigration.optionYesFetchAgain");
|
// const OPTION_FETCH = $msg("moduleMigration.optionYesFetchAgain");
|
||||||
const DISMISS = $msg("moduleMigration.optionNoAskAgain");
|
// const DISMISS = $msg("moduleMigration.optionNoAskAgain");
|
||||||
const options = [OPTION_FETCH, DISMISS];
|
// const options = [OPTION_FETCH, DISMISS];
|
||||||
const ret = await this.core.confirm.confirmWithMessage(
|
// const ret = await this.core.confirm.confirmWithMessage(
|
||||||
$msg("moduleMigration.titleCaseSensitivity"),
|
// $msg("moduleMigration.titleCaseSensitivity"),
|
||||||
message,
|
// message,
|
||||||
options,
|
// options,
|
||||||
DISMISS,
|
// DISMISS,
|
||||||
40
|
// 40
|
||||||
);
|
// );
|
||||||
if (ret == OPTION_FETCH) {
|
// if (ret == OPTION_FETCH) {
|
||||||
this.settings.handleFilenameCaseSensitive = remoteHandleFilenameCaseSensitive || false;
|
// this.settings.handleFilenameCaseSensitive = remoteHandleFilenameCaseSensitive || false;
|
||||||
this.settings.doNotUseFixedRevisionForChunks = remoteDoNotUseFixedRevisionForChunks || false;
|
// this.settings.doNotUseFixedRevisionForChunks = remoteDoNotUseFixedRevisionForChunks || false;
|
||||||
this.settings.settingVersion = SETTING_VERSION_SUPPORT_CASE_INSENSITIVE;
|
// this.settings.settingVersion = SETTING_VERSION_SUPPORT_CASE_INSENSITIVE;
|
||||||
await this.saveSettings();
|
// await this.saveSettings();
|
||||||
try {
|
// try {
|
||||||
await this.core.rebuilder.scheduleFetch();
|
// await this.core.rebuilder.scheduleFetch();
|
||||||
return;
|
// return;
|
||||||
} catch (ex) {
|
// } catch (ex) {
|
||||||
this._log($msg("moduleMigration.logRedflag2CreationFail"), LOG_LEVEL_VERBOSE);
|
// this._log($msg("moduleMigration.logRedflag2CreationFail"), LOG_LEVEL_VERBOSE);
|
||||||
this._log(ex, LOG_LEVEL_VERBOSE);
|
// this._log(ex, LOG_LEVEL_VERBOSE);
|
||||||
}
|
// }
|
||||||
return false;
|
// return false;
|
||||||
} else {
|
// } else {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const ENABLE_BOTH = $msg("moduleMigration.optionEnableBoth");
|
// const ENABLE_BOTH = $msg("moduleMigration.optionEnableBoth");
|
||||||
const ENABLE_FILENAME_CASE_INSENSITIVE = $msg("moduleMigration.optionEnableFilenameCaseInsensitive");
|
// const ENABLE_FILENAME_CASE_INSENSITIVE = $msg("moduleMigration.optionEnableFilenameCaseInsensitive");
|
||||||
const ENABLE_FIXED_REVISION_FOR_CHUNKS = $msg("moduleMigration.optionEnableFixedRevisionForChunks");
|
// const ENABLE_FIXED_REVISION_FOR_CHUNKS = $msg("moduleMigration.optionEnableFixedRevisionForChunks");
|
||||||
const ADJUST_TO_REMOTE = $msg("moduleMigration.optionAdjustRemote");
|
// const ADJUST_TO_REMOTE = $msg("moduleMigration.optionAdjustRemote");
|
||||||
const KEEP = $msg("moduleMigration.optionKeepPreviousBehaviour");
|
// const KEEP = $msg("moduleMigration.optionKeepPreviousBehaviour");
|
||||||
const DISMISS = $msg("moduleMigration.optionDecideLater");
|
// const DISMISS = $msg("moduleMigration.optionDecideLater");
|
||||||
const message = $msg("moduleMigration.msgSinceV02321");
|
// const message = $msg("moduleMigration.msgSinceV02321");
|
||||||
const options = [ENABLE_BOTH, ENABLE_FILENAME_CASE_INSENSITIVE, ENABLE_FIXED_REVISION_FOR_CHUNKS];
|
// const options = [ENABLE_BOTH, ENABLE_FILENAME_CASE_INSENSITIVE, ENABLE_FIXED_REVISION_FOR_CHUNKS];
|
||||||
if (remoteChecked) {
|
// if (remoteChecked) {
|
||||||
options.push(ADJUST_TO_REMOTE);
|
// options.push(ADJUST_TO_REMOTE);
|
||||||
}
|
// }
|
||||||
options.push(KEEP, DISMISS);
|
// options.push(KEEP, DISMISS);
|
||||||
const ret = await this.core.confirm.confirmWithMessage(
|
// const ret = await this.core.confirm.confirmWithMessage(
|
||||||
$msg("moduleMigration.titleCaseSensitivity"),
|
// $msg("moduleMigration.titleCaseSensitivity"),
|
||||||
message,
|
// message,
|
||||||
options,
|
// options,
|
||||||
DISMISS,
|
// DISMISS,
|
||||||
40
|
// 40
|
||||||
);
|
// );
|
||||||
console.dir(ret);
|
// console.dir(ret);
|
||||||
switch (ret) {
|
// switch (ret) {
|
||||||
case ENABLE_BOTH:
|
// case ENABLE_BOTH:
|
||||||
this.settings.handleFilenameCaseSensitive = false;
|
// this.settings.handleFilenameCaseSensitive = false;
|
||||||
this.settings.doNotUseFixedRevisionForChunks = false;
|
// this.settings.doNotUseFixedRevisionForChunks = false;
|
||||||
break;
|
// break;
|
||||||
case ENABLE_FILENAME_CASE_INSENSITIVE:
|
// case ENABLE_FILENAME_CASE_INSENSITIVE:
|
||||||
this.settings.handleFilenameCaseSensitive = false;
|
// this.settings.handleFilenameCaseSensitive = false;
|
||||||
this.settings.doNotUseFixedRevisionForChunks = true;
|
// this.settings.doNotUseFixedRevisionForChunks = true;
|
||||||
break;
|
// break;
|
||||||
case ENABLE_FIXED_REVISION_FOR_CHUNKS:
|
// case ENABLE_FIXED_REVISION_FOR_CHUNKS:
|
||||||
this.settings.doNotUseFixedRevisionForChunks = false;
|
// this.settings.doNotUseFixedRevisionForChunks = false;
|
||||||
this.settings.handleFilenameCaseSensitive = true;
|
// this.settings.handleFilenameCaseSensitive = true;
|
||||||
break;
|
// break;
|
||||||
case KEEP:
|
// case KEEP:
|
||||||
this.settings.handleFilenameCaseSensitive = true;
|
// this.settings.handleFilenameCaseSensitive = true;
|
||||||
this.settings.doNotUseFixedRevisionForChunks = true;
|
// this.settings.doNotUseFixedRevisionForChunks = true;
|
||||||
this.settings.settingVersion = SETTING_VERSION_SUPPORT_CASE_INSENSITIVE;
|
// this.settings.settingVersion = SETTING_VERSION_SUPPORT_CASE_INSENSITIVE;
|
||||||
await this.saveSettings();
|
// await this.saveSettings();
|
||||||
return true;
|
// return true;
|
||||||
case DISMISS:
|
// case DISMISS:
|
||||||
default:
|
// default:
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
this.settings.settingVersion = SETTING_VERSION_SUPPORT_CASE_INSENSITIVE;
|
// this.settings.settingVersion = SETTING_VERSION_SUPPORT_CASE_INSENSITIVE;
|
||||||
await this.saveSettings();
|
// await this.saveSettings();
|
||||||
await this.core.rebuilder.scheduleRebuild();
|
// await this.core.rebuilder.scheduleRebuild();
|
||||||
await this.core.$$performRestart();
|
// await this.core.$$performRestart();
|
||||||
}
|
// }
|
||||||
|
|
||||||
async initialMessage() {
|
async initialMessage() {
|
||||||
const message = $msg("moduleMigration.msgInitialSetup", {
|
const message = $msg("moduleMigration.msgInitialSetup", {
|
||||||
@@ -226,7 +350,8 @@ export class ModuleMigration extends AbstractModule implements ICoreModule {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this.settings.isConfigured) {
|
if (this.settings.isConfigured) {
|
||||||
await this.migrationCheck();
|
await this.migrateUsingDoctor(false);
|
||||||
|
// await this.migrationCheck();
|
||||||
await this.migrateDisableBulkSend();
|
await this.migrateDisableBulkSend();
|
||||||
}
|
}
|
||||||
if (!this.settings.isConfigured) {
|
if (!this.settings.isConfigured) {
|
||||||
@@ -235,7 +360,14 @@ export class ModuleMigration extends AbstractModule implements ICoreModule {
|
|||||||
this._log($msg("moduleMigration.logSetupCancelled"), LOG_LEVEL_NOTICE);
|
this._log($msg("moduleMigration.logSetupCancelled"), LOG_LEVEL_NOTICE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
await this.migrateUsingDoctor(true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
$everyOnLayoutReady(): Promise<boolean> {
|
||||||
|
eventHub.onEvent(EVENT_REQUEST_RUN_DOCTOR, async (reason) => {
|
||||||
|
await this.migrateUsingDoctor(false, reason, true);
|
||||||
|
});
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export class ModuleObsidianEvents extends AbstractObsidianModule implements IObs
|
|||||||
} else {
|
} else {
|
||||||
if (this.settings.syncOnEditorSave) {
|
if (this.settings.syncOnEditorSave) {
|
||||||
this._log("Sync on Editor Save.", LOG_LEVEL_VERBOSE);
|
this._log("Sync on Editor Save.", LOG_LEVEL_VERBOSE);
|
||||||
fireAndForget(() => this.core.$$replicate());
|
fireAndForget(() => this.core.$$replicateByEvent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -155,7 +155,7 @@ export class ModuleObsidianEvents extends AbstractObsidianModule implements IObs
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.settings.syncOnFileOpen && !this.core.$$isSuspended()) {
|
if (this.settings.syncOnFileOpen && !this.core.$$isSuspended()) {
|
||||||
await this.core.$$replicate();
|
await this.core.$$replicateByEvent();
|
||||||
}
|
}
|
||||||
await this.core.$$queueConflictCheckIfOpen(file.path as FilePathWithPrefix);
|
await this.core.$$queueConflictCheckIfOpen(file.path as FilePathWithPrefix);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export class ModuleInteractiveConflictResolver extends AbstractObsidianModule im
|
|||||||
// So we have to run replication if configured.
|
// So we have to run replication if configured.
|
||||||
// TODO: Make this is as a event request
|
// TODO: Make this is as a event request
|
||||||
if (this.settings.syncAfterMerge && !this.core.$$isSuspended()) {
|
if (this.settings.syncAfterMerge && !this.core.$$isSuspended()) {
|
||||||
await this.core.$$waitForReplicationOnce();
|
await this.core.$$replicateByEvent();
|
||||||
}
|
}
|
||||||
// And, check it again.
|
// And, check it again.
|
||||||
await this.core.$$queueConflictCheck(filename);
|
await this.core.$$queueConflictCheck(filename);
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ import {
|
|||||||
EVENT_REQUEST_OPEN_PLUGIN_SYNC_DIALOG,
|
EVENT_REQUEST_OPEN_PLUGIN_SYNC_DIALOG,
|
||||||
EVENT_REQUEST_OPEN_SETUP_URI,
|
EVENT_REQUEST_OPEN_SETUP_URI,
|
||||||
EVENT_REQUEST_RELOAD_SETTING_TAB,
|
EVENT_REQUEST_RELOAD_SETTING_TAB,
|
||||||
|
EVENT_REQUEST_RUN_DOCTOR,
|
||||||
eventHub,
|
eventHub,
|
||||||
} from "../../../common/events.ts";
|
} from "../../../common/events.ts";
|
||||||
import { skipIfDuplicated } from "octagonal-wheels/concurrency/lock";
|
import { skipIfDuplicated } from "octagonal-wheels/concurrency/lock";
|
||||||
@@ -1890,6 +1891,9 @@ The pane also can be launched by \`P2P Replicator\` command from the Command Pal
|
|||||||
})
|
})
|
||||||
.setClass("wizardHidden");
|
.setClass("wizardHidden");
|
||||||
|
|
||||||
|
new Setting(paneEl).autoWireNumeric("syncMinimumInterval", {
|
||||||
|
onUpdate: onlyOnNonLiveSync,
|
||||||
|
});
|
||||||
new Setting(paneEl)
|
new Setting(paneEl)
|
||||||
.setClass("wizardHidden")
|
.setClass("wizardHidden")
|
||||||
.autoWireToggle("syncOnSave", { onUpdate: onlyOnNonLiveSync });
|
.autoWireToggle("syncOnSave", { onUpdate: onlyOnNonLiveSync });
|
||||||
@@ -2226,10 +2230,23 @@ The pane also can be launched by \`P2P Replicator\` command from the Command Pal
|
|||||||
void addPane(containerEl, "Hatch", "🧰", 50, true).then((paneEl) => {
|
void addPane(containerEl, "Hatch", "🧰", 50, true).then((paneEl) => {
|
||||||
// const hatchWarn = this.createEl(paneEl, "div", { text: `To stop the boot up sequence for fixing problems on databases, you can put redflag.md on top of your vault (Rebooting obsidian is required).` });
|
// const hatchWarn = this.createEl(paneEl, "div", { text: `To stop the boot up sequence for fixing problems on databases, you can put redflag.md on top of your vault (Rebooting obsidian is required).` });
|
||||||
// hatchWarn.addClass("op-warn-info");
|
// hatchWarn.addClass("op-warn-info");
|
||||||
void addPanel(paneEl, "Reporting Issue").then((paneEl) => {
|
void addPanel(paneEl, $msg("Setting.TroubleShooting")).then((paneEl) => {
|
||||||
new Setting(paneEl).setName("Make report to inform the issue").addButton((button) =>
|
new Setting(paneEl)
|
||||||
|
.setName($msg("Setting.TroubleShooting.Doctor"))
|
||||||
|
.setDesc($msg("Setting.TroubleShooting.Doctor.Desc"))
|
||||||
|
.addButton((button) =>
|
||||||
button
|
button
|
||||||
.setButtonText("Make report")
|
.setButtonText("Run Doctor")
|
||||||
|
.setCta()
|
||||||
|
.setDisabled(false)
|
||||||
|
.onClick(() => {
|
||||||
|
this.closeSetting();
|
||||||
|
eventHub.emitEvent(EVENT_REQUEST_RUN_DOCTOR, "you wanted(Thank you)!");
|
||||||
|
})
|
||||||
|
);
|
||||||
|
new Setting(paneEl).setName("Prepare the 'report' to create an issue").addButton((button) =>
|
||||||
|
button
|
||||||
|
.setButtonText("Copy Report to clipboard")
|
||||||
.setCta()
|
.setCta()
|
||||||
.setDisabled(false)
|
.setDisabled(false)
|
||||||
.onClick(async () => {
|
.onClick(async () => {
|
||||||
@@ -2310,7 +2327,10 @@ version:${manifestVersion}
|
|||||||
${stringifyYaml(pluginConfig)}`;
|
${stringifyYaml(pluginConfig)}`;
|
||||||
console.log(msgConfig);
|
console.log(msgConfig);
|
||||||
await navigator.clipboard.writeText(msgConfig);
|
await navigator.clipboard.writeText(msgConfig);
|
||||||
Logger(`Information has been copied to clipboard`, LOG_LEVEL_NOTICE);
|
Logger(
|
||||||
|
`Generated report has been copied to clipboard. Please report the issue with this! Thank you for your cooperation!`,
|
||||||
|
LOG_LEVEL_NOTICE
|
||||||
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
new Setting(paneEl).autoWireToggle("writeLogToTheFile");
|
new Setting(paneEl).autoWireToggle("writeLogToTheFile");
|
||||||
|
|||||||
@@ -346,8 +346,8 @@ export const SettingInformation: Partial<Record<keyof AllSettings, Configuration
|
|||||||
desc: "If this enabled, All files are handled as case-Sensitive (Previous behaviour).",
|
desc: "If this enabled, All files are handled as case-Sensitive (Previous behaviour).",
|
||||||
},
|
},
|
||||||
doNotUseFixedRevisionForChunks: {
|
doNotUseFixedRevisionForChunks: {
|
||||||
name: "Compute revisions for chunks (Previous behaviour)",
|
name: "Compute revisions for chunks",
|
||||||
desc: "If this enabled, all chunks will be stored with the revision made from its content. (Previous behaviour)",
|
desc: "If this enabled, all chunks will be stored with the revision made from its content.",
|
||||||
},
|
},
|
||||||
sendChunksBulkMaxSize: {
|
sendChunksBulkMaxSize: {
|
||||||
name: "Maximum size of chunks to send in one request",
|
name: "Maximum size of chunks to send in one request",
|
||||||
@@ -373,6 +373,10 @@ export const SettingInformation: Partial<Record<keyof AllSettings, Configuration
|
|||||||
name: "Suppress notification of hidden files change",
|
name: "Suppress notification of hidden files change",
|
||||||
desc: "If enabled, the notification of hidden files change will be suppressed.",
|
desc: "If enabled, the notification of hidden files change will be suppressed.",
|
||||||
},
|
},
|
||||||
|
syncMinimumInterval: {
|
||||||
|
name: "Minimum interval for syncing",
|
||||||
|
desc: "The minimum interval for automatic synchronisation on event.",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
function translateInfo(infoSrc: ConfigurationItem | undefined | false) {
|
function translateInfo(infoSrc: ConfigurationItem | undefined | false) {
|
||||||
if (!infoSrc) return false;
|
if (!infoSrc) return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user