Refactor optional file synchronisation ownership

This commit is contained in:
vorotamoroz committed 2026-09-03 15:43:21 +00:00
1 parent 3b2d5aa5af
commit 826413bf84
67 files changed
+6294 -1856

No files matched your search

@@ -2,14 +2,33 @@ import { ObsidianLiveSyncSettingTab } from "./SettingDialogue/ObsidianLiveSyncSe
import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts";
// import { PouchDB } from "../../lib/src/pouchdb/pouchdb-browser";
import { EVENT_REQUEST_OPEN_SETTINGS, eventHub } from "@/common/events.ts";
import type ObsidianLiveSyncPlugin from "@/main.ts";
import type { LiveSyncCore } from "@/main.ts";
import { openObsidianSettings } from "@/common/obsidianSettings.ts";
import type { HiddenFileSyncRepairView } from "@/features/HiddenFileSync/hiddenFileSyncViews.ts";
export type ModuleObsidianSettingDialogueDependencies = {
getHiddenFileSyncRepair(): HiddenFileSyncRepairView | undefined;
};
export class ModuleObsidianSettingDialogue extends AbstractObsidianModule {
private readonly dependencies: ModuleObsidianSettingDialogueDependencies;
settingTab!: ObsidianLiveSyncSettingTab;
constructor(
plugin: ObsidianLiveSyncPlugin,
core: LiveSyncCore,
dependencies: Partial<ModuleObsidianSettingDialogueDependencies> = {}
) {
super(plugin, core);
this.dependencies = {
getHiddenFileSyncRepair: dependencies.getHiddenFileSyncRepair ?? (() => undefined),
};
}
_everyOnloadAfterLoadSettings(): Promise<boolean> {
this.settingTab = new ObsidianLiveSyncSettingTab(this.app, this.plugin);
const hiddenFileSyncRepair = this.dependencies.getHiddenFileSyncRepair();
this.settingTab = new ObsidianLiveSyncSettingTab(this.app, this.plugin, { hiddenFileSyncRepair });
this.settingTab.reloadAllSettings(true);
this.plugin.addSettingTab(this.settingTab);
eventHub.onEvent(EVENT_REQUEST_OPEN_SETTINGS, () => this.openSetting());
@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
const settingTabState = vi.hoisted(() => ({
callOrder: [] as string[],
featureViews: undefined as unknown,
reloadAllSettings: vi.fn<(skipUpdate?: boolean) => void>(),
}));
@@ -11,6 +12,10 @@ const eventHubState = vi.hoisted(() => ({
vi.mock("./SettingDialogue/ObsidianLiveSyncSettingTab.ts", () => ({
ObsidianLiveSyncSettingTab: class ObsidianLiveSyncSettingTab {
constructor(_app: unknown, _plugin: unknown, featureViews: unknown) {
settingTabState.featureViews = featureViews;
}
reloadAllSettings(skipUpdate?: boolean) {
settingTabState.callOrder.push(`reload:${String(skipUpdate)}`);
settingTabState.reloadAllSettings(skipUpdate);
@@ -46,15 +51,20 @@ function createModuleHarness() {
},
},
};
const hiddenFileSyncRepair = { scanInternalFiles: vi.fn() };
const getHiddenFileSyncRepair = vi.fn(() => hiddenFileSyncRepair);
const module = Object.assign(Object.create(ModuleObsidianSettingDialogue.prototype), {
plugin,
core: { services },
dependencies: { getHiddenFileSyncRepair },
}) as ModuleObsidianSettingDialogue;
module.onBindFunction(module.core as never, services as never);
return {
initialisationHandler: () => initialisationHandler,
getHiddenFileSyncRepair,
hiddenFileSyncRepair,
module,
plugin,
services,
@@ -65,6 +75,7 @@ function createModuleHarness() {
describe("ModuleObsidianSettingDialogue startup lifecycle", () => {
beforeEach(() => {
settingTabState.callOrder.length = 0;
settingTabState.featureViews = undefined;
settingTabState.reloadAllSettings.mockClear();
eventHubState.onEvent.mockClear();
});
@@ -79,7 +90,8 @@ describe("ModuleObsidianSettingDialogue startup lifecycle", () => {
});
it("seeds the setting editor without requesting a render before registration", async () => {
const { initialisationHandler, settingsLoadedHandler } = createModuleHarness();
const { getHiddenFileSyncRepair, hiddenFileSyncRepair, initialisationHandler, settingsLoadedHandler } =
createModuleHarness();
const handler = settingsLoadedHandler() ?? initialisationHandler();
expect(handler).toBeTypeOf("function");
@@ -87,5 +99,7 @@ describe("ModuleObsidianSettingDialogue startup lifecycle", () => {
expect(settingTabState.reloadAllSettings).toHaveBeenCalledWith(true);
expect(settingTabState.callOrder).toEqual(["reload:true", "add-setting-tab"]);
expect(getHiddenFileSyncRepair).toHaveBeenCalledOnce();
expect(settingTabState.featureViews).toEqual({ hiddenFileSyncRepair });
});
});
@@ -14,7 +14,7 @@ import {
import { delay, isObjectDifferent, sizeToHumanReadable } from "@vrtmrz/livesync-commonlib/compat/common/utils";
import { Logger } from "@vrtmrz/livesync-commonlib/compat/common/logger";
import { testCrypt } from "octagonal-wheels/encryption/encryption";
import ObsidianLiveSyncPlugin from "@/main.ts";
import type ObsidianLiveSyncPlugin from "@/main.ts";
import { scheduleTask } from "@/common/utils.ts";
import { REMOTE_RESOURCE_KINDS } from "@vrtmrz/livesync-commonlib/replication";
import {
@@ -78,12 +78,18 @@ import { createExtraMenuSettingSpecGroup, createGeneralSettingSpecGroups } from
import { SetupManager } from "@/modules/features/SetupManager.ts";
import { isP2PMainRemote } from "@/common/remoteConfiguration.ts";
import { withOwnedRemoteResource } from "@/common/ownedRemoteResource.ts";
import type { HiddenFileSyncRepairView } from "@/features/HiddenFileSync/hiddenFileSyncViews.ts";
// For creating a document
// const toc = new Set<string>();
export type SettingTabFeatureViews = {
hiddenFileSyncRepair?: HiddenFileSyncRepairView;
};
export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
plugin: ObsidianLiveSyncPlugin;
readonly featureViews: SettingTabFeatureViews;
private _lifetimeComponent?: Component;
private activePageRefresh?: () => void;
get lifetimeComponent(): Component {
@@ -323,9 +329,10 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
controlledElementFunc = [] as UpdateFunction[];
onSavedHandlers = [] as OnSavedHandler<AllSettingItemKey>[];
constructor(app: App, plugin: ObsidianLiveSyncPlugin) {
constructor(app: App, plugin: ObsidianLiveSyncPlugin, featureViews: SettingTabFeatureViews = {}) {
super(app, plugin);
this.plugin = plugin;
this.featureViews = featureViews;
Setting.env = this;
eventHub.onEvent(EVENT_REQUEST_RELOAD_SETTING_TAB, () => {
this.requestReload();
@@ -67,8 +67,6 @@ export function paneCustomisationSync(
.setButtonText("Open")
.setDisabled(false)
.onClick(() => {
// this.plugin.getAddOn<ConfigSync>(ConfigSync.name)?.showPluginSyncModal();
// this.plugin.addOnConfigSync.showPluginSyncModal();
eventHub.emitEvent(EVENT_REQUEST_OPEN_PLUGIN_SYNC_DIALOG);
});
})
@@ -21,7 +21,6 @@ import {
EVENT_REQUEST_RUN_FIX_INCOMPLETE,
eventHub,
} from "@/common/events.ts";
import { HiddenFileSync } from "@/features/HiddenFileSync/CmdHiddenFileSync.ts";
import { EVENT_REQUEST_SHOW_HISTORY } from "@/common/obsidianEvents.ts";
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
import type { PageFunctions } from "./SettingPane.ts";
@@ -339,22 +338,22 @@ export function paneHatch(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement,
]);
};
const findHiddenFile = async (path: string) => {
const addOn = this.core.getAddOn<HiddenFileSync>(HiddenFileSync.name);
if (!addOn) {
const repair = this.featureViews.hiddenFileSyncRepair;
if (!repair) {
return false;
}
const file = (await addOn.scanInternalFiles()).find((entry) => entry.path === path);
const file = (await repair.scanInternalFiles()).find((entry) => entry.path === path);
if (!file) {
Logger(`Failed to find the file in the internal files: ${path}`, LOG_LEVEL_NOTICE);
return false;
}
return { addOn, file };
return { repair, file };
};
const storeStorageInDatabase = async (path: string): Promise<boolean> => {
if (path.startsWith(".")) {
const hidden = await findHiddenFile(path);
return hidden
? Boolean(await hidden.addOn.storeInternalFileToDatabase(hidden.file, true))
? Boolean(await hidden.repair.storeInternalFileToDatabase(hidden.file, true))
: false;
}
return Boolean(await this.core.fileHandler.storeFileToDB(path as FilePath, true));
@@ -368,7 +367,7 @@ export function paneHatch(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement,
const hidden = await findHiddenFile(path);
return hidden
? Boolean(
await hidden.addOn.storeInternalFileToDatabaseWithBaseRevision(
await hidden.repair.storeInternalFileToDatabaseWithBaseRevision(
hidden.file,
revision,
createIfDifferent
@@ -390,10 +389,10 @@ export function paneHatch(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement,
force: boolean
): Promise<boolean> => {
if (path.startsWith(".")) {
const addOn = this.core.getAddOn<HiddenFileSync>(HiddenFileSync.name);
return addOn
const repair = this.featureViews.hiddenFileSyncRepair;
return repair
? Boolean(
await addOn.extractInternalFileRevisionFromDatabase(
await repair.extractInternalFileRevisionFromDatabase(
path as FilePath,
revision,
force