fix: prefix remaining <img>, favicon, and WebDAV URLs with basePath #319

This commit is contained in:
Linus Rath
2026-05-25 16:45:13 +02:00
parent 42ec34be21
commit e2abc8dee9
12 changed files with 49 additions and 22 deletions
+3 -2
View File
@@ -7,6 +7,7 @@ import { emailExportFilename, attachmentDownloadFilename, DEFAULT_EMAIL_TEMPLATE
import { EML_IMPORT_ACCEPT, expandImportableEmails } from "@/lib/eml-import";
import { EMAIL_IFRAME_SANITIZE_CONFIG, collapseBlockedImageContainers, escapeHtml, plainTextToSafeHtml, sanitizeEmailHtml, sanitizePlainTextRenderedHtml } from "@/lib/email-sanitization";
import { hasMeaningfulHtmlBody } from "@/lib/signature-utils";
import { withBasePath } from "@/lib/browser-navigation";
import { Button } from "@/components/ui/button";
import { Avatar } from "@/components/ui/avatar";
import { formatFileSize, cn, buildMailboxTree, MailboxNode, formatDateTime, generateUUID } from "@/lib/utils";
@@ -3270,9 +3271,9 @@ export function EmailViewer({
if (!email) {
if (isDemoMode) {
const logoSrc = resolvedTheme === 'dark'
const logoSrc = withBasePath(resolvedTheme === 'dark'
? '/branding/Bulwark_Logo_with_Lettering_White_and_Color.svg'
: '/branding/Bulwark_Logo_with_Lettering_Dark_Color.svg';
: '/branding/Bulwark_Logo_with_Lettering_Dark_Color.svg');
return (
<div className={cn("flex-1 flex flex-col items-center justify-center bg-gradient-to-br from-muted/30 to-muted/50", className)}>
<div className="text-center p-8 max-w-md">
+2 -2
View File
@@ -21,7 +21,7 @@ import { getMaxAccounts } from "@/lib/account-utils";
import { cn, formatFileSize } from "@/lib/utils";
import { PluginSlot } from "@/components/plugins/plugin-slot";
import { KeyboardShortcutsModal } from "@/components/keyboard-shortcuts-modal";
import { apiFetch, getPathPrefix } from "@/lib/browser-navigation";
import { apiFetch, getPathPrefix, withBasePath } from "@/lib/browser-navigation";
import { Avatar } from "@/components/ui/avatar";
interface NavItem {
@@ -444,7 +444,7 @@ export function NavigationRail({
)}
>
{(() => {
const logoUrl = resolvedTheme === 'dark' ? (appLogoDarkUrl || appLogoLightUrl) : (appLogoLightUrl || appLogoDarkUrl);
const logoUrl = withBasePath(resolvedTheme === 'dark' ? (appLogoDarkUrl || appLogoLightUrl) : (appLogoLightUrl || appLogoDarkUrl));
return logoUrl ? (
<div className="flex items-center justify-center py-3 px-1">
<img
+4 -2
View File
@@ -3,6 +3,7 @@
import { useEffect, useState } from "react";
import { X, Download } from "lucide-react";
import { useConfig } from "@/hooks/use-config";
import { withBasePath } from "@/lib/browser-navigation";
interface BeforeInstallPromptEvent extends Event {
prompt: () => Promise<void>;
@@ -58,7 +59,8 @@ export function PWAInstallPrompt() {
return null;
}
const logoSrc = appLogoLightUrl || faviconUrl;
const logoSrc = withBasePath(appLogoLightUrl || faviconUrl);
const darkLogoSrc = withBasePath(appLogoDarkUrl || faviconUrl);
return (
<div className="fixed bottom-4 right-4 z-50 bg-white dark:bg-neutral-900 rounded-lg shadow-lg border border-neutral-200 dark:border-neutral-800 p-4 max-w-sm animate-in slide-in-from-bottom-4">
@@ -75,7 +77,7 @@ export function PWAInstallPrompt() {
)}
{logoSrc && (
<img
src={appLogoDarkUrl || faviconUrl}
src={darkLogoSrc}
alt={appName}
className="w-8 h-8 shrink-0 object-contain hidden dark:block"
/>
+3 -2
View File
@@ -6,6 +6,7 @@ import { Folder, FolderOpen, FileText, FileCode, ImageIcon, FileAudio, File, Hom
import { SettingsSection, SettingItem, ToggleSwitch, RadioGroup } from "./settings-section";
import { loadFilesSettings, saveFilesSettings, type FilesSettings, type FolderLayout } from "@/components/files/files-settings-dialog";
import { cn } from "@/lib/utils";
import { withBasePath } from "@/lib/browser-navigation";
interface SampleFile {
name: string;
@@ -95,7 +96,7 @@ function FilesSettingsPreview({ settings }: { settings: FilesSettings }) {
)}
>
{settings.showThumbnails && file.thumbnailUrl ? (
<img src={file.thumbnailUrl} alt="" className="w-4 h-4 rounded object-cover flex-shrink-0" />
<img src={withBasePath(file.thumbnailUrl)} alt="" className="w-4 h-4 rounded object-cover flex-shrink-0" />
) : settings.showIcons ? (
getPreviewIcon(file, settings.coloredIcons, "sm")
) : null}
@@ -125,7 +126,7 @@ function FilesSettingsPreview({ settings }: { settings: FilesSettings }) {
)}
>
{settings.showThumbnails && file.thumbnailUrl ? (
<img src={file.thumbnailUrl} alt="" className="w-8 h-8 rounded object-cover flex-shrink-0" />
<img src={withBasePath(file.thumbnailUrl)} alt="" className="w-8 h-8 rounded object-cover flex-shrink-0" />
) : settings.showIcons ? (
getPreviewIcon(file, settings.coloredIcons, "lg")
) : (
+2 -1
View File
@@ -6,6 +6,7 @@ import { useSettingsStore } from "@/stores/settings-store";
import { useContactStore, getContactPhotoUri } from "@/stores/contact-store";
import { useConfig } from "@/hooks/use-config";
import { avatarHooks } from "@/lib/plugin-hooks";
import { withBasePath } from "@/lib/browser-navigation";
const IS_DEV = process.env.NODE_ENV !== "production";
@@ -236,7 +237,7 @@ export function Avatar({ name, email, contactPhotoUri, size = "md", className, d
const customAvatar = devMode && email ? CUSTOM_AVATARS[email.toLowerCase()] : null;
const pluginAvatar = pluginAvatarFailed ? null : pluginAvatarUrl;
const photoSrc = resolvedContactPhoto || pluginAvatar || customAvatar || profilePic || null;
const faviconSrc = !imgError && !domainFailed && showFavicon ? `/api/favicon?domain=${encodeURIComponent(faviconDomain!)}` : null;
const faviconSrc = !imgError && !domainFailed && showFavicon ? withBasePath(`/api/favicon?domain=${encodeURIComponent(faviconDomain!)}`) : null;
const imgSrc = disableImages ? null : (photoSrc || faviconSrc);
const isFavicon = imgSrc !== null && imgSrc === faviconSrc;