diff --git a/src/services/CalendarService.ts b/src/services/CalendarService.ts index fdfbc93..62b956c 100644 --- a/src/services/CalendarService.ts +++ b/src/services/CalendarService.ts @@ -3,7 +3,7 @@ import { Component, Event as ICalEvent, parse, Time } from "ical.js"; import { DateTime } from "luxon"; import { CalendarSource } from "../settings/types"; import MemoChron from "../main"; -import { getPathInfo, isLocalPath, isRemoteUrl, PathType } from "../utils/pathUtils"; +import { getPathInfo, isLocalPath, isRemoteUrl, PathType, PathInfo } from "../utils/pathUtils"; export interface CalendarEvent { id: string; @@ -273,7 +273,7 @@ export class CalendarService { if (response.status !== 200) { console.error( - `Failed to fetch calendar ${source.name}: ${response.status} ${response.text}` + `Failed to fetch calendar ${source.name}: ${response.status} ${response.text || 'Unknown error'}` ); return []; } @@ -310,7 +310,7 @@ export class CalendarService { }); } - private async fetchLocalCalendar(pathInfo: any) { + private async fetchLocalCalendar(pathInfo: PathInfo) { try { let content: string; @@ -580,8 +580,8 @@ export class CalendarService { if (!exception) return null; const exTzid = this.extractExceptionTimezone(exception, tzid); - const startDate = this.convertTimezone(exception.startDate.toJSDate(), exTzid); - const endDate = this.convertTimezone(exception.endDate.toJSDate(), exTzid); + const startDate = this.convertIcalTimeToDate(exception.startDate, exTzid); + const endDate = this.convertIcalTimeToDate(exception.endDate, exTzid); if (startDate <= periodEnd && endDate >= periodStart) { return { diff --git a/src/settings/SettingsTab.ts b/src/settings/SettingsTab.ts index 6db4e9d..9107922 100644 --- a/src/settings/SettingsTab.ts +++ b/src/settings/SettingsTab.ts @@ -448,7 +448,10 @@ export class SettingsTab extends PluginSettingTab { input.inputEl.addEventListener("blur", () => { setTimeout(() => { - suggestionContainer.classList.remove("is-visible"); + // Check if container still exists before manipulating + if (suggestionContainer && suggestionContainer.parentNode) { + suggestionContainer.classList.remove("is-visible"); + } }, 200); }); } diff --git a/src/utils/pathUtils.ts b/src/utils/pathUtils.ts index 78cc80c..be5ee4e 100644 --- a/src/utils/pathUtils.ts +++ b/src/utils/pathUtils.ts @@ -29,10 +29,10 @@ export function detectPathType(path: string): PathType { } // Check for absolute paths - // Windows: C:\, D:\, etc. + // Windows: C:\, D:\, C:/, D:/, etc. // Unix: / if ( - (path.length >= 3 && path[1] === ":" && path[2] === "\\") || + (path.length >= 3 && path[1] === ":" && (path[2] === "\\" || path[2] === "/")) || path.startsWith("/") ) { return PathType.ABSOLUTE_PATH; @@ -45,8 +45,15 @@ export function detectPathType(path: string): PathType { export function normalizeFilePath(path: string, type: PathType): string { switch (type) { case PathType.FILE_URL: - // Remove file:// prefix and decode URI components - return decodeURIComponent(path.replace(/^file:\/\//, "")); + // Remove file:// or file:/// prefix and decode URI components + // Windows often uses file:///C:/path, Unix uses file:///path + let normalized = decodeURIComponent(path.replace(/^file:\/\/\/?/, "")); + // On Windows, if path starts with a drive letter without slash, it's already correct + // On Unix, we need to ensure the leading slash is preserved + if (!normalized.startsWith("/") && !normalized.match(/^[A-Za-z]:/)) { + normalized = "/" + normalized; + } + return normalized; case PathType.VAULT_RELATIVE: // Normalize path for Obsidian diff --git a/styles.css b/styles.css index b6c12e7..cbb4698 100644 --- a/styles.css +++ b/styles.css @@ -304,7 +304,7 @@ .memochron-path-type-local, .memochron-path-type-vault { - background-color: var(--interactive-success); + background-color: var(--interactive-success, var(--color-green)); color: var(--text-on-accent); }