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
31 changes: 25 additions & 6 deletions src/services/ICSSubscriptionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ export class ICSSubscriptionService extends EventEmitter {
throw new Error("Unknown subscription type");
}

const events = this.parseICS(icsData, subscription.id);
const events = this.parseICS(icsData, subscription);

// Update cache
const cache: ICSCache = {
Expand Down Expand Up @@ -296,7 +296,7 @@ export class ICSSubscriptionService extends EventEmitter {
}
}

private parseICS(icsData: string, subscriptionId: string): ICSEvent[] {
private parseICS(icsData: string, subscription: ICSSubscription): ICSEvent[] {
try {
const jcalData = ICAL.parse(icsData);
const comp = new ICAL.Component(jcalData);
Expand Down Expand Up @@ -331,6 +331,20 @@ export class ICSSubscriptionService extends EventEmitter {
}
});

// Create Regex filter if user sets subscription.filter
let regExp: RegExp | null = null;
const filter = subscription.filter?.trim();

if (filter) {
try {
// Fix double escaping
const match = filter.match(/^\/(.+)\/([a-z]*)$/i);
regExp = match ? new RegExp(match[1], match[2]) : new RegExp(filter);
} catch {
regExp = null;
}
}

// Second pass: process events
vevents.forEach((vevent: ICAL.Component) => {
try {
Expand All @@ -344,6 +358,11 @@ export class ICSSubscriptionService extends EventEmitter {

// Extract basic properties
const summary = event.summary || "Untitled Event";

if (regExp && !regExp.test(summary)) {
return;
}

const description = event.description || undefined;
const location = event.location || undefined;

Expand All @@ -360,12 +379,12 @@ export class ICSSubscriptionService extends EventEmitter {
const endISO = endDate ? this.icalTimeToISOString(endDate) : undefined;

// Generate unique ID
const uid = event.uid || `${subscriptionId}-${events.length}`;
const eventId = `${subscriptionId}-${uid}`;
const uid = event.uid || `${subscription.id}-${events.length}`;
const eventId = `${subscription.id}-${uid}`;

const icsEvent: ICSEvent = {
id: eventId,
subscriptionId: subscriptionId,
subscriptionId: subscription.id,
title: summary,
description: description,
start: startISO,
Expand Down Expand Up @@ -430,7 +449,7 @@ export class ICSSubscriptionService extends EventEmitter {
if (modifiedStart) {
events.push({
id: `${eventId}-${instanceCount}`,
subscriptionId: subscriptionId,
subscriptionId: subscription.id,
title: modifiedEvent.summary || summary,
description: modifiedEvent.description || description,
start: this.icalTimeToISOString(modifiedStart),
Expand Down
6 changes: 6 additions & 0 deletions src/settings/tabs/integrationsTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,7 @@ export function renderIntegrationsTab(
enabled: false, // Start disabled until user fills in details
type: "remote" as const,
refreshInterval: 60,
filter: ""
};

if (!plugin.icsSubscriptionService) {
Expand Down Expand Up @@ -1589,6 +1590,7 @@ function renderICSSubscriptionsList(

const colorInput = createCardInput("color", "", subscription.color);
const refreshInput = createCardNumberInput(5, 1440, 5, subscription.refreshInterval || 60);
const filterInput = createCardInput("text", "", subscription.filter);

// Update handlers
const updateSubscription = async (updates: Partial<typeof subscription>) => {
Expand Down Expand Up @@ -1617,6 +1619,9 @@ function renderICSSubscriptionsList(
const minutes = parseInt(refreshInput.value) || 60;
updateSubscription({ refreshInterval: minutes });
});
filterInput.addEventListener("change", () =>
updateSubscription({ filter: filterInput.value })
);

// Type change handler - re-render the subscription list to update input type
typeSelect.addEventListener("change", async () => {
Expand Down Expand Up @@ -1750,6 +1755,7 @@ function renderICSSubscriptionsList(
},
{ label: "Color:", input: colorInput },
{ label: "Refresh (min):", input: refreshInput },
{ label: "Filter (regex):", input: filterInput }
];

createCard(container, {
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ export interface ICSSubscription {
color: string;
enabled: boolean;
refreshInterval: number; // minutes (for remote) or check interval (for local)
filter: string;
}

export interface ICSEvent {
Expand Down