Fix bugs in timezone handling and local file support

- Fix timezone conversion for recurrence exceptions
- Fix type safety: use PathInfo type instead of any
- Fix Windows path detection to support forward slashes (C:/)
- Fix file URL normalization for Windows (file:///C:/) and Unix
- Add safety check for setTimeout DOM manipulation in settings
- Add CSS fallback for themes without --interactive-success variable
- Improve error message handling when response.text is undefined
This commit is contained in:
Michalis Efstratiadis 2025-05-29 14:18:32 +03:00
parent 13aca6c302
commit 965bf3dca4
No known key found for this signature in database
4 changed files with 21 additions and 11 deletions

View file

@ -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 {

View file

@ -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);
});
}

View file

@ -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

View file

@ -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);
}