mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-07-31 08:51:23 +00:00
Group Obsidian startup notices by operation
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import { KeyedNoticeGroupManager } from "@vrtmrz/obsidian-plugin-kit/notice";
|
||||
|
||||
export interface ObsidianNoticeGroupItem {
|
||||
message: string;
|
||||
action?: {
|
||||
label: string;
|
||||
onSelect: () => void;
|
||||
};
|
||||
}
|
||||
|
||||
interface KeyedNoticeGroupDriver {
|
||||
setItem(groupKey: string, itemKey: string, item: ObsidianNoticeGroupItem): unknown;
|
||||
finish(groupKey: string, options?: { durationMs?: number | false }): boolean;
|
||||
removeItem(groupKey: string, itemKey: string): boolean;
|
||||
hide(groupKey: string): boolean;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
/** Obsidian-owned interactive Notice capability exposed through the application Context. */
|
||||
export interface ObsidianNoticeGroups {
|
||||
setItem(groupKey: string, itemKey: string, item: ObsidianNoticeGroupItem): void;
|
||||
finish(groupKey: string, options?: { durationMs?: number | false }): boolean;
|
||||
removeItem(groupKey: string, itemKey: string): boolean;
|
||||
hide(groupKey: string): boolean;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
/** Adapts Fancy Kit grouped Notices without exposing Obsidian Notice instances to features. */
|
||||
export class ObsidianNoticeGroupManager implements ObsidianNoticeGroups {
|
||||
constructor(private readonly manager: KeyedNoticeGroupDriver = new KeyedNoticeGroupManager()) {}
|
||||
|
||||
setItem(groupKey: string, itemKey: string, item: ObsidianNoticeGroupItem): void {
|
||||
this.manager.setItem(groupKey, itemKey, item);
|
||||
}
|
||||
|
||||
finish(groupKey: string, options?: { durationMs?: number | false }): boolean {
|
||||
return this.manager.finish(groupKey, options);
|
||||
}
|
||||
|
||||
removeItem(groupKey: string, itemKey: string): boolean {
|
||||
return this.manager.removeItem(groupKey, itemKey);
|
||||
}
|
||||
|
||||
hide(groupKey: string): boolean {
|
||||
return this.manager.hide(groupKey);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.manager.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
vi.mock("@vrtmrz/obsidian-plugin-kit/notice", () => ({
|
||||
KeyedNoticeGroupManager: class KeyedNoticeGroupManager {},
|
||||
}));
|
||||
|
||||
import { ObsidianNoticeGroupManager } from "./ObsidianNoticeGroups";
|
||||
|
||||
describe("ObsidianNoticeGroupManager", () => {
|
||||
it("keeps Fancy Kit rendering behind the Context-owned capability", () => {
|
||||
const driver = {
|
||||
setItem: vi.fn(),
|
||||
finish: vi.fn(() => true),
|
||||
removeItem: vi.fn(() => true),
|
||||
hide: vi.fn(() => true),
|
||||
dispose: vi.fn(),
|
||||
};
|
||||
const groups = new ObsidianNoticeGroupManager(driver);
|
||||
const item = {
|
||||
message: "Complete",
|
||||
action: { label: "Review", onSelect: vi.fn() },
|
||||
};
|
||||
|
||||
groups.setItem("integrity", "result", item);
|
||||
expect(driver.setItem).toHaveBeenCalledWith("integrity", "result", item);
|
||||
expect(groups.finish("integrity", { durationMs: 1_000 })).toBe(true);
|
||||
expect(groups.removeItem("integrity", "result")).toBe(true);
|
||||
expect(groups.hide("integrity")).toBe(true);
|
||||
groups.dispose();
|
||||
expect(driver.dispose).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
@@ -3,17 +3,20 @@ import type { App, Plugin } from "@/deps";
|
||||
import { ServiceContext } from "@vrtmrz/livesync-commonlib/context";
|
||||
import { eventHub } from "@/common/events";
|
||||
import { translateLiveSyncMessage } from "@/common/translation";
|
||||
import type { ObsidianNoticeGroups } from "./ObsidianNoticeGroups";
|
||||
|
||||
/** Host capabilities owned by one Self-hosted LiveSync plug-in instance. */
|
||||
export class ObsidianServiceContext extends ServiceContext {
|
||||
app: App;
|
||||
plugin: Plugin;
|
||||
liveSyncPlugin: ObsidianLiveSyncPlugin;
|
||||
readonly noticeGroups: ObsidianNoticeGroups;
|
||||
|
||||
constructor(app: App, plugin: Plugin, liveSyncPlugin: ObsidianLiveSyncPlugin) {
|
||||
constructor(app: App, plugin: Plugin, liveSyncPlugin: ObsidianLiveSyncPlugin, noticeGroups: ObsidianNoticeGroups) {
|
||||
super({ events: eventHub, translate: translateLiveSyncMessage });
|
||||
this.app = app;
|
||||
this.plugin = plugin;
|
||||
this.liveSyncPlugin = liveSyncPlugin;
|
||||
this.noticeGroups = noticeGroups;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ describe("ObsidianServiceContext contract", () => {
|
||||
const app = {} as Parameters[0];
|
||||
const plugin = {} as Parameters[1];
|
||||
const liveSyncPlugin = {} as Parameters[2];
|
||||
const context = new ObsidianServiceContext(app, plugin, liveSyncPlugin);
|
||||
const noticeGroups = {} as Parameters[3];
|
||||
const context = new ObsidianServiceContext(app, plugin, liveSyncPlugin, noticeGroups);
|
||||
|
||||
expect(observeServiceContext(context, TRANSLATION_KEY)).toEqual({
|
||||
translation: translateLiveSyncMessage(TRANSLATION_KEY),
|
||||
@@ -23,5 +24,6 @@ describe("ObsidianServiceContext contract", () => {
|
||||
expect(context.app).toBe(app);
|
||||
expect(context.plugin).toBe(plugin);
|
||||
expect(context.liveSyncPlugin).toBe(liveSyncPlugin);
|
||||
expect(context.noticeGroups).toBe(noticeGroups);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,12 +25,14 @@ import { ObsidianUIService } from "./ObsidianUIService";
|
||||
import { createScreenWakeLockManager } from "octagonal-wheels/browser/wakeLock";
|
||||
import { PouchDB } from "@vrtmrz/livesync-commonlib/compat/pouchdb/pouchdb-browser";
|
||||
import { OpenKeyValueDatabase } from "@/common/KeyValueDB";
|
||||
import { ObsidianNoticeGroupManager } from "./ObsidianNoticeGroups";
|
||||
|
||||
// InjectableServiceHub
|
||||
|
||||
export class ObsidianServiceHub extends InjectableServiceHub<ObsidianServiceContext> {
|
||||
constructor(plugin: ObsidianLiveSyncPlugin) {
|
||||
const context = new ObsidianServiceContext(plugin.app, plugin, plugin);
|
||||
const noticeGroups = new ObsidianNoticeGroupManager();
|
||||
const context = new ObsidianServiceContext(plugin.app, plugin, plugin, noticeGroups);
|
||||
|
||||
const API = new ObsidianAPIService(context);
|
||||
const conflict = new ObsidianConflictService(context);
|
||||
@@ -62,6 +64,7 @@ export class ObsidianServiceHub extends InjectableServiceHub<ObsidianServiceCont
|
||||
const screenWakeLock = createScreenWakeLockManager();
|
||||
appLifecycle.onUnload.addHandler(async () => {
|
||||
await screenWakeLock.dispose();
|
||||
noticeGroups.dispose();
|
||||
return true;
|
||||
});
|
||||
const database = new ObsidianDatabaseService(context, {
|
||||
|
||||
Reference in New Issue
Block a user