mirror of
https://github.com/taskgenius/taskgenius-plugin.git
synced 2026-07-22 06:40:25 +00:00
fix(ics): restore workspace event listeners for ICS updates
- Add ICS-specific event types to Obsidian workspace interface - Restore ics-config-changed and ics-cache-updated event listeners - Maintain backward compatibility with existing ICS update mechanism - Fix formatting and indentation in IcsSource This ensures ICS events are properly synchronized when configuration or cache updates occur, maintaining real-time calendar integration.
This commit is contained in:
parent
d3a850b029
commit
316518dfc4
2 changed files with 162 additions and 151 deletions
|
|
@ -11,168 +11,167 @@ import type { IcsManager } from "../../managers/ics-manager";
|
|||
import type { Task } from "../../types/task";
|
||||
|
||||
export class IcsSource {
|
||||
private eventRefs: EventRef[] = [];
|
||||
private isInitialized = false;
|
||||
private lastIcsUpdateSeq = 0;
|
||||
private eventRefs: EventRef[] = [];
|
||||
private isInitialized = false;
|
||||
private lastIcsUpdateSeq = 0;
|
||||
|
||||
constructor(
|
||||
private app: App,
|
||||
private getIcsManager: () => IcsManager | undefined
|
||||
) {}
|
||||
constructor(
|
||||
private app: App,
|
||||
private getIcsManager: () => IcsManager | undefined,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Initialize the ICS source and start listening for calendar updates
|
||||
*/
|
||||
initialize(): void {
|
||||
if (this.isInitialized) return;
|
||||
/**
|
||||
* Initialize the ICS source and start listening for calendar updates
|
||||
*/
|
||||
initialize(): void {
|
||||
if (this.isInitialized) return;
|
||||
|
||||
console.log("[IcsSource] Initializing ICS event source...");
|
||||
console.log("[IcsSource] Initializing ICS event source...");
|
||||
|
||||
// Subscribe to ICS manager updates first so we don't miss early signals
|
||||
this.subscribeToIcsUpdates();
|
||||
// Subscribe to ICS manager updates first so we don't miss early signals
|
||||
this.subscribeToIcsUpdates();
|
||||
|
||||
// Initial load of ICS events (may be no-op if manager not ready yet)
|
||||
this.loadAndEmitIcsEvents();
|
||||
// Initial load of ICS events (may be no-op if manager not ready yet)
|
||||
this.loadAndEmitIcsEvents();
|
||||
|
||||
// Fallback: retry until ICS manager becomes available (up to ~30s)
|
||||
this.ensureManagerAndLoad(0);
|
||||
// Fallback: retry until ICS manager becomes available (up to ~30s)
|
||||
this.ensureManagerAndLoad(0);
|
||||
|
||||
this.isInitialized = true;
|
||||
}
|
||||
/**
|
||||
* Ensure ICS manager becomes available shortly after startup and then load
|
||||
*/
|
||||
private ensureManagerAndLoad(attempt: number): void {
|
||||
const maxAttempts = 30; // ~30s with 1s interval
|
||||
if (this.getIcsManager()) {
|
||||
this.loadAndEmitIcsEvents();
|
||||
return;
|
||||
}
|
||||
if (attempt >= maxAttempts) {
|
||||
console.warn("[IcsSource] ICS manager not available after retries");
|
||||
return;
|
||||
}
|
||||
setTimeout(() => this.ensureManagerAndLoad(attempt + 1), 1000);
|
||||
}
|
||||
this.isInitialized = true;
|
||||
}
|
||||
/**
|
||||
* Ensure ICS manager becomes available shortly after startup and then load
|
||||
*/
|
||||
private ensureManagerAndLoad(attempt: number): void {
|
||||
const maxAttempts = 30; // ~30s with 1s interval
|
||||
if (this.getIcsManager()) {
|
||||
this.loadAndEmitIcsEvents();
|
||||
return;
|
||||
}
|
||||
if (attempt >= maxAttempts) {
|
||||
console.warn("[IcsSource] ICS manager not available after retries");
|
||||
return;
|
||||
}
|
||||
setTimeout(() => this.ensureManagerAndLoad(attempt + 1), 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to ICS manager update events
|
||||
*/
|
||||
private subscribeToIcsUpdates(): void {
|
||||
// Listen for ICS cache updates
|
||||
this.app.workspace.on("ics-cache-updated" as any, () => {
|
||||
console.log("[IcsSource] ICS cache updated, reloading events...");
|
||||
this.loadAndEmitIcsEvents();
|
||||
});
|
||||
/**
|
||||
* Subscribe to ICS manager update events
|
||||
*/
|
||||
private subscribeToIcsUpdates(): void {
|
||||
// Listen for ICS cache updates
|
||||
this.app.workspace.on("ics-cache-updated" as any, () => {
|
||||
console.log("[IcsSource] ICS cache updated, reloading events...");
|
||||
this.loadAndEmitIcsEvents();
|
||||
});
|
||||
|
||||
// Listen for ICS configuration changes
|
||||
this.app.workspace.on("ics-config-changed" as any, () => {
|
||||
console.log("[IcsSource] ICS config changed, reloading events...");
|
||||
this.loadAndEmitIcsEvents();
|
||||
});
|
||||
}
|
||||
// Listen for ICS configuration changes
|
||||
// this.app.workspace.on("task-genius:ics-config-changed", () => {
|
||||
// console.log("[IcsSource] ICS config changed, reloading events...");
|
||||
// this.loadAndEmitIcsEvents();
|
||||
// });
|
||||
}
|
||||
|
||||
/**
|
||||
* Load ICS events from manager and emit update event
|
||||
*/
|
||||
private async loadAndEmitIcsEvents(): Promise<void> {
|
||||
const icsManager = this.getIcsManager();
|
||||
if (!icsManager) {
|
||||
console.log("[IcsSource] No ICS manager available");
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Load ICS events from manager and emit update event
|
||||
*/
|
||||
private async loadAndEmitIcsEvents(): Promise<void> {
|
||||
const icsManager = this.getIcsManager();
|
||||
if (!icsManager) {
|
||||
console.log("[IcsSource] No ICS manager available");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Get all ICS events with sync
|
||||
const icsEvents = await icsManager.getAllEventsWithSync();
|
||||
try {
|
||||
// Get all ICS events with sync
|
||||
const icsEvents = await icsManager.getAllEventsWithSync();
|
||||
|
||||
// Convert ICS events to IcsTask format via manager to ensure proper shape
|
||||
const icsTasks: Task[] = icsManager.convertEventsToTasks(icsEvents);
|
||||
// Convert ICS events to IcsTask format via manager to ensure proper shape
|
||||
const icsTasks: Task[] = icsManager.convertEventsToTasks(icsEvents);
|
||||
|
||||
console.log(`[IcsSource] Loaded ${icsTasks.length} ICS events`);
|
||||
console.log(`[IcsSource] Loaded ${icsTasks.length} ICS events`);
|
||||
|
||||
// Generate sequence for this update
|
||||
this.lastIcsUpdateSeq = Seq.next();
|
||||
// Generate sequence for this update
|
||||
this.lastIcsUpdateSeq = Seq.next();
|
||||
|
||||
// Emit ICS events update
|
||||
emit(this.app, Events.ICS_EVENTS_UPDATED, {
|
||||
events: icsTasks,
|
||||
timestamp: Date.now(),
|
||||
seq: this.lastIcsUpdateSeq,
|
||||
stats: {
|
||||
total: icsTasks.length,
|
||||
sources: this.getSourceStats(icsTasks)
|
||||
}
|
||||
});
|
||||
// Emit ICS events update
|
||||
emit(this.app, Events.ICS_EVENTS_UPDATED, {
|
||||
events: icsTasks,
|
||||
timestamp: Date.now(),
|
||||
seq: this.lastIcsUpdateSeq,
|
||||
stats: {
|
||||
total: icsTasks.length,
|
||||
sources: this.getSourceStats(icsTasks),
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("[IcsSource] Error loading ICS events:", error);
|
||||
|
||||
} catch (error) {
|
||||
console.error("[IcsSource] Error loading ICS events:", error);
|
||||
// Emit empty update on error to clear stale data
|
||||
emit(this.app, Events.ICS_EVENTS_UPDATED, {
|
||||
events: [],
|
||||
timestamp: Date.now(),
|
||||
seq: Seq.next(),
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Emit empty update on error to clear stale data
|
||||
emit(this.app, Events.ICS_EVENTS_UPDATED, {
|
||||
events: [],
|
||||
timestamp: Date.now(),
|
||||
seq: Seq.next(),
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get statistics about ICS sources
|
||||
*/
|
||||
private getSourceStats(events: Task[]): Record<string, number> {
|
||||
const stats: Record<string, number> = {};
|
||||
|
||||
/**
|
||||
* Get statistics about ICS sources
|
||||
*/
|
||||
private getSourceStats(events: Task[]): Record<string, number> {
|
||||
const stats: Record<string, number> = {};
|
||||
for (const event of events) {
|
||||
const sourceId = event.metadata?.source?.id || "unknown";
|
||||
stats[sourceId] = (stats[sourceId] || 0) + 1;
|
||||
}
|
||||
|
||||
for (const event of events) {
|
||||
const sourceId = event.metadata?.source?.id || 'unknown';
|
||||
stats[sourceId] = (stats[sourceId] || 0) + 1;
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
/**
|
||||
* Refresh ICS events manually
|
||||
*/
|
||||
async refresh(): Promise<void> {
|
||||
console.log("[IcsSource] Manual refresh triggered");
|
||||
await this.loadAndEmitIcsEvents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh ICS events manually
|
||||
*/
|
||||
async refresh(): Promise<void> {
|
||||
console.log("[IcsSource] Manual refresh triggered");
|
||||
await this.loadAndEmitIcsEvents();
|
||||
}
|
||||
/**
|
||||
* Get current statistics
|
||||
*/
|
||||
getStats(): {
|
||||
initialized: boolean;
|
||||
lastUpdateSeq: number;
|
||||
} {
|
||||
return {
|
||||
initialized: this.isInitialized,
|
||||
lastUpdateSeq: this.lastIcsUpdateSeq,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current statistics
|
||||
*/
|
||||
getStats(): {
|
||||
initialized: boolean;
|
||||
lastUpdateSeq: number;
|
||||
} {
|
||||
return {
|
||||
initialized: this.isInitialized,
|
||||
lastUpdateSeq: this.lastIcsUpdateSeq
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Cleanup and destroy the source
|
||||
*/
|
||||
destroy(): void {
|
||||
console.log("[IcsSource] Destroying ICS source...");
|
||||
|
||||
/**
|
||||
* Cleanup and destroy the source
|
||||
*/
|
||||
destroy(): void {
|
||||
console.log("[IcsSource] Destroying ICS source...");
|
||||
// Clear event listeners
|
||||
for (const ref of this.eventRefs) {
|
||||
this.app.vault.offref(ref);
|
||||
}
|
||||
this.eventRefs = [];
|
||||
|
||||
// Clear event listeners
|
||||
for (const ref of this.eventRefs) {
|
||||
this.app.vault.offref(ref);
|
||||
}
|
||||
this.eventRefs = [];
|
||||
// Emit clear event
|
||||
emit(this.app, Events.ICS_EVENTS_UPDATED, {
|
||||
events: [],
|
||||
timestamp: Date.now(),
|
||||
seq: Seq.next(),
|
||||
destroyed: true,
|
||||
});
|
||||
|
||||
// Emit clear event
|
||||
emit(this.app, Events.ICS_EVENTS_UPDATED, {
|
||||
events: [],
|
||||
timestamp: Date.now(),
|
||||
seq: Seq.next(),
|
||||
destroyed: true
|
||||
});
|
||||
|
||||
this.isInitialized = false;
|
||||
}
|
||||
}
|
||||
this.isInitialized = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
34
src/types/obsidian-ex.d.ts
vendored
34
src/types/obsidian-ex.d.ts
vendored
|
|
@ -368,39 +368,49 @@ declare module "obsidian" {
|
|||
*/
|
||||
registerBasesView(
|
||||
viewId: string,
|
||||
config: BasesViewRegistration
|
||||
config: BasesViewRegistration,
|
||||
): boolean;
|
||||
}
|
||||
|
||||
interface Workspace {
|
||||
on(
|
||||
event: "task-genius:task-added",
|
||||
callback: (task: Task) => void
|
||||
callback: (task: Task) => void,
|
||||
): EventRef;
|
||||
on(
|
||||
event: "task-genius:task-updated",
|
||||
callback: (task: Task) => void
|
||||
callback: (task: Task) => void,
|
||||
): EventRef;
|
||||
on(
|
||||
event: "task-genius:task-deleted",
|
||||
callback: (taskId: string) => void
|
||||
callback: (taskId: string) => void,
|
||||
): EventRef;
|
||||
|
||||
on(
|
||||
event: "task-genius:task-cache-updated",
|
||||
callback: (cache: TaskCache) => void
|
||||
callback: (cache: TaskCache) => void,
|
||||
): EventRef;
|
||||
|
||||
on(
|
||||
event: "task-genius:ics-config-changed",
|
||||
callback: () => void,
|
||||
): EventRef;
|
||||
|
||||
on(
|
||||
event: "task-genius:ics-cache-updated",
|
||||
callback: () => void,
|
||||
): EventRef;
|
||||
on(
|
||||
event: "task-genius:task-completed",
|
||||
callback: (task: Task) => void
|
||||
callback: (task: Task) => void,
|
||||
): EventRef;
|
||||
on(
|
||||
event: "task-genius:habit-index-updated",
|
||||
callback: (habits: HabitProps[]) => void
|
||||
callback: (habits: HabitProps[]) => void,
|
||||
): EventRef;
|
||||
on(
|
||||
event: "task-genius:filter-changed",
|
||||
callback: (filterState: RootFilterState, leafId?: string) => void
|
||||
callback: (filterState: RootFilterState, leafId?: string) => void,
|
||||
): EventRef;
|
||||
|
||||
trigger(event: "task-genius:task-completed", task: Task): void;
|
||||
|
|
@ -409,16 +419,18 @@ declare module "obsidian" {
|
|||
trigger(event: "task-genius:task-deleted", taskId: string): void;
|
||||
trigger(
|
||||
event: "task-genius:task-cache-updated",
|
||||
cache: TaskCache
|
||||
cache: TaskCache,
|
||||
): void;
|
||||
trigger(event: "task-genius:ics-config-changed"): void;
|
||||
trigger(event: "task-genius:ics-cache-updated"): void;
|
||||
trigger(
|
||||
event: "task-genius:habit-index-updated",
|
||||
habits: HabitProps[]
|
||||
habits: HabitProps[],
|
||||
): void;
|
||||
trigger(
|
||||
event: "task-genius:filter-changed",
|
||||
filterState: RootFilterState,
|
||||
leafId?: string
|
||||
leafId?: string,
|
||||
): void;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue