mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-03 08:53:36 +00:00
fix background image not showing
This commit is contained in:
@@ -13,7 +13,8 @@ import { Label } from '@/components/ui/label';
|
|||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { useAppStore, defaultBackgroundSettings } from '@/store/app-store';
|
import { useAppStore, defaultBackgroundSettings } from '@/store/app-store';
|
||||||
import { getHttpApiClient, getServerUrlSync } from '@/lib/http-api-client';
|
import { getHttpApiClient } from '@/lib/http-api-client';
|
||||||
|
import { getAuthenticatedImageUrl } from '@/lib/api-fetch';
|
||||||
import { useBoardBackgroundSettings } from '@/hooks/use-board-background-settings';
|
import { useBoardBackgroundSettings } from '@/hooks/use-board-background-settings';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import {
|
import {
|
||||||
@@ -62,12 +63,13 @@ export function BoardBackgroundModal({ open, onOpenChange }: BoardBackgroundModa
|
|||||||
// Update preview image when background settings change
|
// Update preview image when background settings change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentProject && backgroundSettings.imagePath) {
|
if (currentProject && backgroundSettings.imagePath) {
|
||||||
const serverUrl = import.meta.env.VITE_SERVER_URL || getServerUrlSync();
|
|
||||||
// Add cache-busting query parameter to force browser to reload image
|
// Add cache-busting query parameter to force browser to reload image
|
||||||
const cacheBuster = imageVersion ? `&v=${imageVersion}` : `&v=${Date.now()}`;
|
const cacheBuster = imageVersion ?? Date.now().toString();
|
||||||
const imagePath = `${serverUrl}/api/fs/image?path=${encodeURIComponent(
|
const imagePath = getAuthenticatedImageUrl(
|
||||||
backgroundSettings.imagePath
|
backgroundSettings.imagePath,
|
||||||
)}&projectPath=${encodeURIComponent(currentProject.path)}${cacheBuster}`;
|
currentProject.path,
|
||||||
|
cacheBuster
|
||||||
|
);
|
||||||
setPreviewImage(imagePath);
|
setPreviewImage(imagePath);
|
||||||
} else {
|
} else {
|
||||||
setPreviewImage(null);
|
setPreviewImage(null);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { cn } from '@/lib/utils';
|
|||||||
import { ImageIcon, X, Loader2, FileText } from 'lucide-react';
|
import { ImageIcon, X, Loader2, FileText } from 'lucide-react';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
import { getElectronAPI } from '@/lib/electron';
|
import { getElectronAPI } from '@/lib/electron';
|
||||||
import { getServerUrlSync } from '@/lib/http-api-client';
|
import { getAuthenticatedImageUrl } from '@/lib/api-fetch';
|
||||||
import { useAppStore, type FeatureImagePath, type FeatureTextFilePath } from '@/store/app-store';
|
import { useAppStore, type FeatureImagePath, type FeatureTextFilePath } from '@/store/app-store';
|
||||||
import {
|
import {
|
||||||
sanitizeFilename,
|
sanitizeFilename,
|
||||||
@@ -94,9 +94,8 @@ export function DescriptionImageDropZone({
|
|||||||
// Construct server URL for loading saved images
|
// Construct server URL for loading saved images
|
||||||
const getImageServerUrl = useCallback(
|
const getImageServerUrl = useCallback(
|
||||||
(imagePath: string): string => {
|
(imagePath: string): string => {
|
||||||
const serverUrl = import.meta.env.VITE_SERVER_URL || getServerUrlSync();
|
|
||||||
const projectPath = currentProject?.path || '';
|
const projectPath = currentProject?.path || '';
|
||||||
return `${serverUrl}/api/fs/image?path=${encodeURIComponent(imagePath)}&projectPath=${encodeURIComponent(projectPath)}`;
|
return getAuthenticatedImageUrl(imagePath, projectPath);
|
||||||
},
|
},
|
||||||
[currentProject?.path]
|
[currentProject?.path]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useAppStore, defaultBackgroundSettings } from '@/store/app-store';
|
import { useAppStore, defaultBackgroundSettings } from '@/store/app-store';
|
||||||
import { getServerUrlSync } from '@/lib/http-api-client';
|
import { getAuthenticatedImageUrl } from '@/lib/api-fetch';
|
||||||
|
|
||||||
interface UseBoardBackgroundProps {
|
interface UseBoardBackgroundProps {
|
||||||
currentProject: { path: string; id: string } | null;
|
currentProject: { path: string; id: string } | null;
|
||||||
@@ -22,14 +22,14 @@ export function useBoardBackground({ currentProject }: UseBoardBackgroundProps)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const imageUrl = getAuthenticatedImageUrl(
|
||||||
|
backgroundSettings.imagePath,
|
||||||
|
currentProject.path,
|
||||||
|
backgroundSettings.imageVersion
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
backgroundImage: `url(${
|
backgroundImage: `url(${imageUrl})`,
|
||||||
import.meta.env.VITE_SERVER_URL || getServerUrlSync()
|
|
||||||
}/api/fs/image?path=${encodeURIComponent(
|
|
||||||
backgroundSettings.imagePath
|
|
||||||
)}&projectPath=${encodeURIComponent(currentProject.path)}${
|
|
||||||
backgroundSettings.imageVersion ? `&v=${backgroundSettings.imageVersion}` : ''
|
|
||||||
})`,
|
|
||||||
backgroundSize: 'cover',
|
backgroundSize: 'cover',
|
||||||
backgroundPosition: 'center',
|
backgroundPosition: 'center',
|
||||||
backgroundRepeat: 'no-repeat',
|
backgroundRepeat: 'no-repeat',
|
||||||
|
|||||||
@@ -153,3 +153,37 @@ export async function apiDeleteRaw(
|
|||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
return apiFetch(endpoint, 'DELETE', options);
|
return apiFetch(endpoint, 'DELETE', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an authenticated image URL for use in <img> tags or CSS background-image
|
||||||
|
* Adds authentication via query parameter since headers can't be set for image loads
|
||||||
|
*
|
||||||
|
* @param path - Image path
|
||||||
|
* @param projectPath - Project path
|
||||||
|
* @param version - Optional cache-busting version
|
||||||
|
* @returns Full URL with auth credentials
|
||||||
|
*/
|
||||||
|
export function getAuthenticatedImageUrl(
|
||||||
|
path: string,
|
||||||
|
projectPath: string,
|
||||||
|
version?: string | number
|
||||||
|
): string {
|
||||||
|
const serverUrl = getServerUrl();
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
path,
|
||||||
|
projectPath,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (version !== undefined) {
|
||||||
|
params.set('v', String(version));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add auth credential as query param (needed for image loads that can't set headers)
|
||||||
|
const apiKey = getApiKey();
|
||||||
|
if (apiKey) {
|
||||||
|
params.set('apiKey', apiKey);
|
||||||
|
}
|
||||||
|
// Note: Session token auth relies on cookies which are sent automatically by the browser
|
||||||
|
|
||||||
|
return `${serverUrl}/api/fs/image?${params.toString()}`;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user