mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-11-06 00:08:23 +00:00
Refactor conflict resolution into service features
This commit is contained in:
1 parent
3b2d5aa5af
commit
6ea906b575
19 files changed
+2322
-1240
No files matched your search
@@ -0,0 +1,91 @@
|
||||
import type { NecessaryServices } from "@vrtmrz/livesync-commonlib/compat/interfaces/ServiceModule";
|
||||
import { createInstanceLogFunction } from "@vrtmrz/livesync-commonlib/compat/services/lib/logUtils";
|
||||
import { fireAndForget } from "octagonal-wheels/promises";
|
||||
import type { Editor, MarkdownFileInfo, MarkdownView } from "@/deps.ts";
|
||||
import type { FilePathWithPrefix } from "@vrtmrz/livesync-commonlib/compat/common/types";
|
||||
import { EVENT_CONFLICT_CANCELLED, EVENT_PLUGIN_UNLOADED } from "@/common/events.ts";
|
||||
import { createInteractiveConflictResolutionOperations } from "./operations";
|
||||
import type { ConflictResolveDialogueFactory } from "./types";
|
||||
|
||||
export type InteractiveConflictResolutionHost = NecessaryServices<
|
||||
"API" | "UI" | "appLifecycle" | "conflict" | "replication" | "vault" | "database" | "setting" | "path",
|
||||
"databaseFileAccess"
|
||||
>;
|
||||
|
||||
export function useInteractiveConflictResolutionFeature(
|
||||
host: InteractiveConflictResolutionHost,
|
||||
createDialogue: ConflictResolveDialogueFactory
|
||||
): void {
|
||||
const services = host.services;
|
||||
const operations = createInteractiveConflictResolutionOperations({
|
||||
events: services.context.events,
|
||||
databaseFileAccess: host.serviceModules.databaseFileAccess,
|
||||
localDatabase: () => services.database.localDatabase,
|
||||
confirm: services.UI.confirm,
|
||||
path: services.path,
|
||||
vault: services.vault,
|
||||
appLifecycle: services.appLifecycle,
|
||||
conflict: services.conflict,
|
||||
replication: services.replication,
|
||||
currentSettings: () => services.setting.currentSettings(),
|
||||
createDialogue,
|
||||
log: createInstanceLogFunction("SF:InteractiveConflictResolution", services.API),
|
||||
});
|
||||
|
||||
services.appLifecycle.onScanningStartupIssues.addHandler(operations.scanStartupIssues);
|
||||
services.appLifecycle.onInitialise.addHandler(() => {
|
||||
services.API.addCommand({
|
||||
id: "livesync-checkdoc-conflicted",
|
||||
name: "Resolve if conflicted.",
|
||||
editorCallback: (editor: Editor, view: MarkdownView | MarkdownFileInfo) => {
|
||||
const file = view.file;
|
||||
if (!file) return;
|
||||
void operations.requestConflictResolution(file.path as FilePathWithPrefix);
|
||||
},
|
||||
});
|
||||
services.API.addCommand({
|
||||
id: "livesync-conflictcheck",
|
||||
name: "Pick a file to resolve conflict",
|
||||
callback: async () => {
|
||||
await operations.pickFileForResolve();
|
||||
},
|
||||
});
|
||||
services.API.addCommand({
|
||||
id: "livesync-all-conflictcheck",
|
||||
name: "Resolve all conflicted files",
|
||||
callback: async () => {
|
||||
await operations.allConflictCheck();
|
||||
},
|
||||
});
|
||||
return Promise.resolve(true);
|
||||
});
|
||||
services.appLifecycle.getUnresolvedMessages.addHandler(operations.getActiveConflictMessages);
|
||||
services.conflict.resolveByUserInteraction.addHandler(operations.resolveByUserInteraction);
|
||||
const offConflictCancelled = services.context.events.onEvent(EVENT_CONFLICT_CANCELLED, (filename) => {
|
||||
operations.invalidateWaitingResolution(filename);
|
||||
fireAndForget(() => operations.refreshConflictState(filename));
|
||||
});
|
||||
let featureDisposed = false;
|
||||
const dispose = () => {
|
||||
if (featureDisposed) return;
|
||||
featureDisposed = true;
|
||||
// Stop the refresh listener before cancellation so that unloading does
|
||||
// not start a database read which can race with database disposal.
|
||||
offConflictCancelled();
|
||||
operations.dispose();
|
||||
};
|
||||
const offPluginUnloaded = services.context.events.onceEvent(EVENT_PLUGIN_UNLOADED, dispose);
|
||||
services.appLifecycle.onUnload.addHandler(() => {
|
||||
offPluginUnloaded();
|
||||
dispose();
|
||||
return Promise.resolve(true);
|
||||
});
|
||||
}
|
||||
|
||||
export { createInteractiveConflictResolutionOperations } from "./operations";
|
||||
export type {
|
||||
InteractiveConflictResolutionOperations,
|
||||
InteractiveConflictResolutionOperationsDependencies,
|
||||
} from "./operations";
|
||||
export { POSTPONED } from "./types";
|
||||
export type { ConflictResolveDialogue, ConflictResolveDialogueFactory, MergeDialogResult } from "./types";
|
||||
Reference in new issue
Block a user