Align host integrations with current API recommendations

This commit is contained in:
vorotamoroz
2026-08-24 16:39:32 +00:00
parent 47759f6205
commit dd11a753d5
19 changed files with 146 additions and 129 deletions
@@ -4,7 +4,6 @@ vi.mock("@/deps.ts", () => ({
addIcon: vi.fn(),
diff_match_patch: class DiffMatchPatch {},
normalizePath: vi.fn((path: string) => path),
Notice: class Notice {},
parseYaml: vi.fn(),
Platform: {},
}));
@@ -30,13 +29,10 @@ vi.mock("@/common/types.ts", () => ({
PERIODIC_PLUGIN_SWEEP: 60,
}));
vi.mock("@/common/utils.ts", () => ({
cancelTask: vi.fn(),
EVEN: Symbol("even"),
disposeMemoObject: vi.fn(),
isCustomisationSyncMetadata: vi.fn(),
isPluginMetadata: vi.fn(),
memoIfNotExist: vi.fn(),
memoObject: vi.fn(),
retrieveMemoObject: vi.fn(),
scheduleTask: vi.fn(),
}));
vi.mock("@/common/PeriodicProcessor.ts", () => ({
@@ -55,6 +51,7 @@ vi.mock("@/common/obsidianCommunityPlugins.ts", () => ({
getObsidianCommunityPluginManager: vi.fn(),
}));
import { cancelTask } from "@/common/utils.ts";
import { ConfigSync } from "./CmdConfigSync";
describe("ConfigSync commands", () => {
@@ -93,4 +90,24 @@ describe("ConfigSync commands", () => {
expect(command?.checkCallback?.(false)).toBe(true);
expect(showPluginSyncModal).toHaveBeenCalledOnce();
});
it("cancels the pending configuration Notice before releasing its owned UI", () => {
const notices = { hide: vi.fn() };
const periodicPluginSweepProcessor = { disable: vi.fn() };
const configSync = Object.create(ConfigSync.prototype) as ConfigSync;
Object.assign(configSync, {
core: {
services: {
context: { notices },
},
},
periodicPluginSweepProcessor,
});
configSync.onunload();
expect(cancelTask).toHaveBeenCalledWith("config-sync:updated-configuration");
expect(notices.hide).toHaveBeenCalledWith("config-sync:updated-configuration");
expect(periodicPluginSweepProcessor.disable).toHaveBeenCalledOnce();
});
});
+10 -36
View File
@@ -1,7 +1,6 @@
import { writable } from "svelte/store";
import type PouchDB from "pouchdb-core";
import {
Notice,
type PluginManifest,
parseYaml,
normalizePath,
@@ -53,21 +52,11 @@ import {
import { serialized, shareRunningResult } from "octagonal-wheels/concurrency/lock";
import { LiveSyncCommands } from "@/features/LiveSyncCommands.ts";
import { stripAllPrefixes } from "@vrtmrz/livesync-commonlib/compat/string_and_binary/path";
import {
EVEN,
disposeMemoObject,
isCustomisationSyncMetadata,
isPluginMetadata,
memoIfNotExist,
memoObject,
retrieveMemoObject,
scheduleTask,
} from "@/common/utils.ts";
import { cancelTask, EVEN, isCustomisationSyncMetadata, isPluginMetadata, scheduleTask } from "@/common/utils.ts";
import { PeriodicProcessor } from "@/common/PeriodicProcessor.ts";
import { JsonResolveModal } from "@/features/HiddenFileCommon/JsonResolveModal.ts";
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
import { pluginScanningCount } from "@vrtmrz/livesync-commonlib/compat/mock_and_interop/stores";
import type ObsidianLiveSyncPlugin from "@/main.ts";
import { base64ToArrayBuffer, base64ToString } from "octagonal-wheels/binary/base64";
import { ConflictResolveModal } from "@/modules/features/InteractiveConflictResolving/ConflictResolveModal.ts";
import { Semaphore } from "octagonal-wheels/concurrency/semaphore";
@@ -82,6 +71,7 @@ import { getObsidianCommunityPluginManager } from "@/common/obsidianCommunityPlu
const d = "\u200b";
const d2 = "\n";
const UPDATED_CONFIGURATION_NOTICE_KEY = "config-sync:updated-configuration";
function serialize(data: PluginDataEx): string {
// For higher performance, create custom plug-in data strings.
@@ -393,8 +383,8 @@ export type PluginDataEx = {
};
export class ConfigSync extends LiveSyncCommands {
constructor(plugin: ObsidianLiveSyncPlugin, core: LiveSyncCore) {
super(plugin, core);
constructor(core: LiveSyncCore) {
super(core);
pluginScanningCount.onChanged((e) => {
const total = e.value;
pluginIsEnumerating.set(total != 0);
@@ -428,7 +418,7 @@ export class ConfigSync extends LiveSyncCommands {
if (this.pluginDialog) {
this.pluginDialog.open();
} else {
this.pluginDialog = new PluginDialogModal(this.app, this.plugin);
this.pluginDialog = new PluginDialogModal(this.app, this.services.context.liveSyncPlugin);
this.pluginDialog.open();
}
}
@@ -440,8 +430,10 @@ export class ConfigSync extends LiveSyncCommands {
}
}
onunload() {
cancelTask(UPDATED_CONFIGURATION_NOTICE_KEY);
this.hidePluginSyncModal();
this.periodicPluginSweepProcessor?.disable();
this.services.context.notices.hide(UPDATED_CONFIGURATION_NOTICE_KEY);
}
addRibbonIcon = this.services.API.addRibbonIcon.bind(this.services.API);
onload() {
@@ -1196,22 +1188,9 @@ export class ConfigSync extends LiveSyncCommands {
});
});
const updatedPluginKey = "popupUpdated-plugins";
scheduleTask(updatedPluginKey, 1000, async () => {
const popup = await memoIfNotExist(updatedPluginKey, () => new Notice(fragment, 0));
//@ts-ignore -- retained for compatibility with Obsidian versions before Notice.messageEl.
const isShown = popup?.noticeEl?.isShown();
if (!isShown) {
memoObject(updatedPluginKey, new Notice(fragment, 0));
}
scheduleTask(updatedPluginKey + "-close", 20000, () => {
const popup = retrieveMemoObject<Notice>(updatedPluginKey);
if (!popup) return;
//@ts-ignore -- retained for compatibility with Obsidian versions before Notice.messageEl.
if (popup?.noticeEl?.isShown()) {
popup.hide();
}
disposeMemoObject(updatedPluginKey);
scheduleTask(UPDATED_CONFIGURATION_NOTICE_KEY, 1000, () => {
this.services.context.notices.show(UPDATED_CONFIGURATION_NOTICE_KEY, fragment, {
durationMs: 20_000,
});
});
}
@@ -1716,8 +1695,6 @@ export class ConfigSync extends LiveSyncCommands {
}
async configureHiddenFileSync(mode: OptionalSyncFeatureMode) {
if (mode == "DISABLE") {
// this.plugin.settings.usePluginSync = false;
// await this.plugin.saveSettings();
await this.core.services.setting.applyPartial(
{
usePluginSync: false,
@@ -1758,9 +1735,6 @@ export class ConfigSync extends LiveSyncCommands {
}
this.services.setting.setDeviceAndVaultName(name);
}
// this.core.settings.usePluginSync = true;
// this.core.settings.useAdvancedMode = true;
// await this.core.saveSettings();
await this.core.services.setting.applyPartial(
{
usePluginSync: true,
+2 -11
View File
@@ -8,7 +8,6 @@ import {
type FilePathWithPrefix,
type LOG_LEVEL,
} from "@vrtmrz/livesync-commonlib/compat/common/types";
import type ObsidianLiveSyncPlugin from "@/main.ts";
import { MARK_DONE } from "@/modules/features/ModuleLog.ts";
import type { LiveSyncCore } from "@/main.ts";
// import { __$checkInstanceBinding } from "@vrtmrz/livesync-commonlib/compat/dev/checks";
@@ -16,13 +15,9 @@ import { createInstanceLogFunction } from "@vrtmrz/livesync-commonlib/compat/ser
let noticeIndex = 0;
export abstract class LiveSyncCommands {
/**
* @deprecated This class is deprecated. Please use core
*/
plugin: ObsidianLiveSyncPlugin;
core: LiveSyncCore;
get app() {
return this.plugin.app;
return this.services.context.app;
}
get settings() {
return this.core.settings;
@@ -34,9 +29,6 @@ export abstract class LiveSyncCommands {
return this.core.services;
}
// id2path(id: DocumentID, entry?: EntryHasPath, stripPrefix?: boolean): FilePathWithPrefix {
// return this.plugin.$$id2path(id, entry, stripPrefix);
// }
async path2id(filename: FilePathWithPrefix | FilePath, prefix?: string): Promise<DocumentID> {
return await this.services.path.path2id(filename, prefix);
}
@@ -45,8 +37,7 @@ export abstract class LiveSyncCommands {
return this.services.path.getPath(entry);
}
constructor(plugin: ObsidianLiveSyncPlugin, core: LiveSyncCore) {
this.plugin = plugin;
constructor(core: LiveSyncCore) {
this.core = core;
this.onBindFunction(this.core, this.core.services);
this._log = createInstanceLogFunction(this.constructor.name, this.services.API);
@@ -35,7 +35,7 @@ export class LocalDatabaseMaintenance extends LiveSyncCommands {
}
onload(): void | Promise<void> {
// NO OP.
this.plugin.addCommand({
this.services.API.addCommand({
id: "analyse-database",
name: "Analyse Database Usage (advanced)",
icon: "database-search",
@@ -47,7 +47,7 @@ export class LocalDatabaseMaintenance extends LiveSyncCommands {
return true;
},
});
this.plugin.addCommand({
this.services.API.addCommand({
id: "gc-v3",
name: "Garbage Collection V3 (advanced, beta)",
icon: "trash-2",
@@ -18,10 +18,13 @@ vi.mock("@vrtmrz/livesync-commonlib/compat/common/utils", async (importOriginal)
});
vi.mock("@/features/LiveSyncCommands", () => ({
LiveSyncCommands: class LiveSyncCommands {
core!: { settings: unknown };
core!: { settings: unknown; services: unknown };
get settings() {
return this.core.settings;
}
get services() {
return this.core.services;
}
},
}));
vi.mock("@/common/events", () => ({
@@ -76,11 +79,13 @@ describe("LocalDatabaseMaintenance prerequisites", () => {
};
const maintenance = Object.create(LocalDatabaseMaintenance.prototype) as LocalDatabaseMaintenance;
Object.assign(maintenance, {
plugin: {
addCommand: vi.fn((command) => commands.push(command)),
},
core: {
settings,
services: {
API: {
addCommand: vi.fn((command) => commands.push(command)),
},
},
},
_isDatabaseReady: vi.fn(() => true),
});