mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-09-03 17:27:06 +00:00
92 lines
4.1 KiB
TypeScript
92 lines
4.1 KiB
TypeScript
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";
|