## 0.24.31

### Fixed

- The description of `Enable Developers' Debug Tools.` has been refined.
- Automatic conflict checking and resolution has been improved.
- Resolving conflicts dialogue will not be shown for the multiple files at once.
This commit is contained in:
vorotamoroz committed 2025-07-10 11:12:44 +01:00
1 parent 7535999388
commit 52b02f3888
3 files changed
+16 -13

No files matched your search

@@ -37,13 +37,17 @@ export class ModuleConflictChecker extends AbstractModule implements ICoreModule
// TODO-> Move to ModuleConflictResolver? // TODO-> Move to ModuleConflictResolver?
conflictResolveQueue = new QueueProcessor( conflictResolveQueue = new QueueProcessor(
async (filenames: FilePathWithPrefix[]) => { async (filenames: FilePathWithPrefix[]) => {
await this.core.$$resolveConflict(filenames[0]); const filename = filenames[0];
return await this.core.$$resolveConflict(filename);
}, },
{ {
suspended: false, suspended: false,
batchSize: 1, batchSize: 1,
concurrentLimit: 1, // No need to limit concurrency to `1` here, subsequent process will handle it,
delay: 10, // And, some cases, we do not need to synchronised. (e.g., auto-merge available).
// Therefore, limiting global concurrency is performed on resolver with the UI.
concurrentLimit: 10,
delay: 0,
keepResultUntilDownstreamConnected: false, keepResultUntilDownstreamConnected: false,
} }
).replaceEnqueueProcessor((queue, newEntity) => { ).replaceEnqueueProcessor((queue, newEntity) => {
@@ -57,19 +61,13 @@ export class ModuleConflictChecker extends AbstractModule implements ICoreModule
new QueueProcessor( new QueueProcessor(
(files: FilePathWithPrefix[]) => { (files: FilePathWithPrefix[]) => {
const filename = files[0]; const filename = files[0];
// const file = await this.core.storageAccess.isExists(filename);
// if (!file) return [];
// if (!(file instanceof TFile)) return;
// if ((file instanceof TFolder)) return [];
// Check again?
return Promise.resolve([filename]); return Promise.resolve([filename]);
// this.conflictResolveQueue.enqueueWithKey(filename, { filename, file });
}, },
{ {
suspended: false, suspended: false,
batchSize: 1, batchSize: 1,
concurrentLimit: 5, concurrentLimit: 10,
delay: 10, delay: 0,
keepResultUntilDownstreamConnected: true, keepResultUntilDownstreamConnected: true,
pipeTo: this.conflictResolveQueue, pipeTo: this.conflictResolveQueue,
totalRemainingReactiveSource: this.core.conflictProcessQueueCount, totalRemainingReactiveSource: this.core.conflictProcessQueueCount,
@@ -13,6 +13,7 @@ import { ConflictResolveModal } from "./InteractiveConflictResolving/ConflictRes
import { AbstractObsidianModule, type IObsidianModule } from "../AbstractObsidianModule.ts"; import { AbstractObsidianModule, type IObsidianModule } from "../AbstractObsidianModule.ts";
import { displayRev, getPath, getPathWithoutPrefix } from "../../common/utils.ts"; import { displayRev, getPath, getPathWithoutPrefix } from "../../common/utils.ts";
import { fireAndForget } from "octagonal-wheels/promises"; import { fireAndForget } from "octagonal-wheels/promises";
import { serialized } from "../../lib/src/concurrency/lock.ts";
export class ModuleInteractiveConflictResolver extends AbstractObsidianModule implements IObsidianModule { export class ModuleInteractiveConflictResolver extends AbstractObsidianModule implements IObsidianModule {
$everyOnloadStart(): Promise<boolean> { $everyOnloadStart(): Promise<boolean> {
@@ -34,6 +35,8 @@ export class ModuleInteractiveConflictResolver extends AbstractObsidianModule im
} }
async $anyResolveConflictByUI(filename: FilePathWithPrefix, conflictCheckResult: diff_result): Promise<boolean> { async $anyResolveConflictByUI(filename: FilePathWithPrefix, conflictCheckResult: diff_result): Promise<boolean> {
// UI for resolving conflicts should one-by-one.
return await serialized(`conflict-resolve-ui`, async () => {
this._log("Merge:open conflict dialog", LOG_LEVEL_VERBOSE); this._log("Merge:open conflict dialog", LOG_LEVEL_VERBOSE);
const dialog = new ConflictResolveModal(this.app, filename, conflictCheckResult); const dialog = new ConflictResolveModal(this.app, filename, conflictCheckResult);
dialog.open(); dialog.open();
@@ -77,7 +80,8 @@ export class ModuleInteractiveConflictResolver extends AbstractObsidianModule im
} else if (typeof toDelete === "string") { } else if (typeof toDelete === "string") {
// Select one of the conflicted revision to delete. // Select one of the conflicted revision to delete.
if ( if (
(await this.core.$$resolveConflictByDeletingRev(filename, toDelete, "UI Selected")) == MISSING_OR_ERROR (await this.core.$$resolveConflictByDeletingRev(filename, toDelete, "UI Selected")) ==
MISSING_OR_ERROR
) { ) {
this._log(`Merge: Something went wrong: ${filename}, (${toDelete})`, LOG_LEVEL_NOTICE); this._log(`Merge: Something went wrong: ${filename}, (${toDelete})`, LOG_LEVEL_NOTICE);
return false; return false;
@@ -95,6 +99,7 @@ export class ModuleInteractiveConflictResolver extends AbstractObsidianModule im
// And, check it again. // And, check it again.
await this.core.$$queueConflictCheck(filename); await this.core.$$queueConflictCheck(filename);
return false; return false;
});
} }
async allConflictCheck() { async allConflictCheck() {
while (await this.pickFileForResolve()); while (await this.pickFileForResolve());
@@ -367,7 +367,7 @@ export const SettingInformation: Partial<Record<keyof AllSettings, Configuration
}, },
enableDebugTools: { enableDebugTools: {
name: "Enable Developers' Debug Tools.", name: "Enable Developers' Debug Tools.",
desc: "Requires restart of Obsidian", desc: "While enabled, it causes very performance impact but debugging replication testing and other features will be enabled. Please disable this if you have not read the source code. Requires restart of Obsidian.",
}, },
suppressNotifyHiddenFilesChange: { suppressNotifyHiddenFilesChange: {
name: "Suppress notification of hidden files change", name: "Suppress notification of hidden files change",