Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions src/ui/ICSCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,30 @@ function renderRelatedNoteIndicator(
});
}

function getEventSourceName(icsEvent: ICSEvent, plugin: TaskNotesPlugin): string {
const subscription = plugin.icsSubscriptionService
?.getSubscriptions()
.find((candidate) => candidate.id === icsEvent.subscriptionId);
if (subscription?.name) {
return subscription.name;
}

const provider = plugin.calendarProviderRegistry?.findProviderForEvent(icsEvent);
if (provider) {
const { calendarId } = provider.extractEventIds(icsEvent);
const calendar = provider
.getAvailableCalendars()
.find(
(candidate) =>
candidate.id === calendarId ||
(calendarId === "primary" && candidate.primary === true)
);
return calendar?.summary || provider.providerName;
}

return plugin.i18n.translate("ui.icsCard.calendarFallback");
}

function formatTimeRange(icsEvent: ICSEvent, plugin: TaskNotesPlugin): string {
try {
if (!icsEvent.start) return "";
Expand Down Expand Up @@ -85,12 +109,12 @@ export function createICSEventCard(
card.dataset.relatedNoteCount = String(opts.relatedNoteCount);
}

// Determine subscription color and name
// Determine subscription color and source name
const subscription = plugin.icsSubscriptionService
?.getSubscriptions()
.find((s) => s.id === icsEvent.subscriptionId);
const color = icsEvent.color || subscription?.color || "var(--color-accent)";
const sourceName = subscription?.name || plugin.i18n.translate("ui.icsCard.calendarFallback");
const sourceName = getEventSourceName(icsEvent, plugin);

// Main row
const mainRow = card.createEl("div", { cls: "task-card__main-row" });
Expand Down Expand Up @@ -228,7 +252,7 @@ export function updateICSEventCard(
?.getSubscriptions()
.find((s) => s.id === icsEvent.subscriptionId);
const color = icsEvent.color || subscription?.color || "var(--color-accent)";
const sourceName = subscription?.name || plugin.i18n.translate("ui.icsCard.calendarFallback");
const sourceName = getEventSourceName(icsEvent, plugin);

// Update icon color on wrapper to propagate to svg (icons use currentColor)
element.style.setProperty("--current-status-color", color);
Expand Down
90 changes: 90 additions & 0 deletions tests/unit/issues/issue-provider-calendar-source-name.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { describe, expect, it, jest } from "@jest/globals";
import { createICSEventCard, updateICSEventCard } from "../../../src/ui/ICSCard";
import type { ICSEvent } from "../../../src/types";

function createEvent(overrides: Partial<ICSEvent> = {}): ICSEvent {
return {
id: "google-primary-event-1",
subscriptionId: "google-primary",
title: "Team sync",
start: "2026-08-03T10:00:00",
end: "2026-08-03T11:00:00",
allDay: false,
...overrides,
};
}

function createPlugin() {
const provider = {
providerName: "Google Calendar",
extractEventIds: (event: ICSEvent) => ({
calendarId: event.subscriptionId.replace("google-", ""),
eventId: event.id,
}),
getAvailableCalendars: jest.fn(() => [
{
id: "person@example.com",
summary: "Personal",
primary: true,
},
]),
};

return {
app: {},
i18n: {
translate: (key: string) => (key === "ui.icsCard.calendarFallback" ? "Calendar" : key),
},
settings: {
calendarViewSettings: {
timeFormat: "24",
},
},
icsSubscriptionService: {
getSubscriptions: () => [],
},
calendarProviderRegistry: {
findProviderForEvent: jest.fn(() => provider),
},
};
}

describe("provider calendar source names on ICS cards", () => {
it("shows a provider calendar name for primary-alias Google events", () => {
const card = createICSEventCard(createEvent(), createPlugin() as any);

expect(card.querySelector(".task-card__metadata")?.textContent).toContain("Personal");
expect(card.querySelector(".task-card__metadata")?.textContent).not.toContain("Calendar");
});

it("refreshes the provider calendar name when an existing card updates", () => {
const plugin = createPlugin();
const card = createICSEventCard(createEvent(), plugin as any);
plugin.calendarProviderRegistry.findProviderForEvent.mockReturnValue({
providerName: "Microsoft Calendar",
extractEventIds: () => ({ calendarId: "work", eventId: "event-1" }),
getAvailableCalendars: () => [{ id: "work", summary: "Work" }],
});

updateICSEventCard(
card,
createEvent({ id: "microsoft-work-event-1", subscriptionId: "microsoft-work" }),
plugin as any
);

expect(card.querySelector(".task-card__metadata")?.textContent).toContain("Work");
expect(card.querySelector(".task-card__metadata")?.textContent).not.toContain("Personal");
});

it("uses the translated fallback when no subscription or provider owns the event", () => {
const plugin = createPlugin();
plugin.calendarProviderRegistry.findProviderForEvent.mockReturnValue(undefined);

const card = createICSEventCard(
createEvent({ id: "unknown-event", subscriptionId: "unknown" }),
plugin as any
);

expect(card.querySelector(".task-card__metadata")?.textContent).toContain("Calendar");
});
});
Loading