image server url | post patch / append

This commit is contained in:
lovebird 2026-02-22 18:40:36 +01:00
parent d87afd8654
commit f6e1f656cf
16 changed files with 36 additions and 68 deletions

View File

@ -276,7 +276,7 @@ export const CreationWizardPopup: React.FC<CreationWizardPopupProps> = ({
// Helper function to upload internal video
const uploadInternalVideo = async (file: File): Promise<void> => {
return new Promise((resolve, reject) => {
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://192.168.1.11:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
const formData = new FormData();
formData.append('file', file);

View File

@ -49,7 +49,7 @@ const GlobalDragDrop = () => {
} else if (isUrl) {
// URL workflow
toast.info(translate('Processing link...'));
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://localhost:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
const { data: { session } } = await supabase.auth.getSession();
const headers: Record<string, string> = {};

View File

@ -51,7 +51,7 @@ export const ImageEditor = ({ imageUrl, pictureId, onSave, onClose }: ImageEdito
formData.append('file', file);
formData.append('operations', JSON.stringify(ops));
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://192.168.1.11:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
const res = await fetch(`${serverUrl}/api/images/transform`, {
method: 'POST',
body: formData

View File

@ -102,14 +102,6 @@ const PhotoCard = ({
setLocalVersionCount(versionCount);
}
}, [versionCount]);
// Legacy fetch removed in favor of passed prop
/*
useEffect(() => {
// ... legacy fetch logic ...
}, [pictureId, isOwner, user]);
*/
const handleLike = async (e: React.MouseEvent) => {
e.stopPropagation();

View File

@ -54,6 +54,7 @@ const ResponsiveImage: React.FC<ResponsiveImageProps> = React.memo(({
const ref = React.useRef<HTMLDivElement>(null);
const imgRef = React.useRef<HTMLImageElement>(null);
useEffect(() => {
if (props.loading === 'eager' || providedData) {
setIsInView(true);

View File

@ -177,7 +177,7 @@ const VideoCard = ({
const jobId = match[1];
// Use VITE_SERVER_IMAGE_API_URL or default. Do NOT infer from videoUrl if it logic fails.
let baseUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://localhost:3333';
let baseUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
// Fallback: If videoUrl is internal (same origin), use that origin.
// But for Supabase URLs, we MUST use the API server URL.
@ -265,7 +265,7 @@ const VideoCard = ({
const jobId = match[1];
// Use VITE_SERVER_IMAGE_API_URL or default
let baseUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://localhost:3333';
let baseUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
if (videoUrl.startsWith('/') || videoUrl.includes(window.location.origin)) {
baseUrl = window.location.origin;

View File

@ -22,7 +22,7 @@ export const useResponsiveImage = ({
responsiveSizes = DEFAULT_SIZES,
formats = DEFAULT_FORMATS,
enabled = true,
apiUrl,
apiUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL,
}: UseResponsiveImageProps) => {
const [data, setData] = useState<ResponsiveData | null>(null);
const [loading, setLoading] = useState(false);
@ -78,7 +78,7 @@ export const useResponsiveImage = ({
if (!requestCache.has(cacheKey)) {
const requestPromise = (async () => {
const serverUrl = apiUrl || import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://192.168.1.11:3333';
const serverUrl = apiUrl || import.meta.env.VITE_SERVER_IMAGE_API_URL;
// Resolve relative URLs to absolute so the server-side API can fetch them
const resolvedSrc = src.startsWith('/') ? `${window.location.origin}${src}` : src;
const params = new URLSearchParams({

View File

@ -106,7 +106,7 @@ export const fetchAnalytics = async (options: { limit?: number, startDate?: stri
if (options.endDate) params.append('endDate', options.endDate);
// Server URL logic from fetchMediaItemsByIds
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://localhost:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
const res = await fetch(`${serverUrl}/api/analytics?${params.toString()}`, { headers });
@ -130,7 +130,7 @@ export const clearAnalytics = async () => {
headers['Authorization'] = `Bearer ${token}`;
// Server URL logic from fetchMediaItemsByIds
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://localhost:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
const res = await fetch(`${serverUrl}/api/analytics`, {
method: 'DELETE',

View File

@ -115,7 +115,7 @@ export const createOpenAIClient = async (apiKey?: string): Promise<OpenAI | null
console.log('[createOpenAIClient] resolved token:', token ? token.substring(0, 10) + '...' : 'null');
return new OpenAI({
apiKey: token, // This is sent as Bearer token to our proxy
baseURL: `${import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://localhost:3333'}/api/openai/v1`,
baseURL: `${import.meta.env.VITE_SERVER_IMAGE_API_URL}/api/openai/v1`,
dangerouslyAllowBrowser: true // Required for client-side usage
});
} catch (error) {

View File

@ -1,57 +1,32 @@
import { supabase } from '@/integrations/supabase/client';
/**
* Uploads an image file to Supabase Storage.
* If the file is larger than the configured threshold (VITE_MAX_IMAGE_SIZE),
* it proxies the upload through the server (VITE_SERVER_IMAGE_API_URL) for resizing.
* Otherwise, it uploads directly to Supabase Storage.
* Uploads an image file via the server API (sharp processing + Supabase forwarding).
* Always goes through VITE_SERVER_IMAGE_API_URL/api/images.
*/
export const uploadImage = async (file: File, userId: string): Promise<{ publicUrl: string, meta?: any }> => {
if (!userId) throw new Error('User ID is required for upload');
console.log('uploading ', import.meta.env);
const MAX_SIZE = Number(import.meta.env.VITE_MAX_IMAGE_SIZE) || 1572864; // 1.5MB default
const SERVER_URL = import.meta.env.VITE_SERVER_IMAGE_API_URL;
if (!SERVER_URL) throw new Error('VITE_SERVER_IMAGE_API_URL is not configured');
// Use proxy if file is too large and server URL is configured
if (file.size > MAX_SIZE && SERVER_URL) {
console.log(`File size (${file.size}) exceeds threshold (${MAX_SIZE}), uploading via proxy...`);
const formData = new FormData();
formData.append('file', file);
console.log(`Uploading ${file.name} (${file.size} bytes) via server API...`);
const formData = new FormData();
formData.append('file', file);
// The server expects multipart/form-data
const response = await fetch(`${SERVER_URL}/api/images?forward=supabase&original=true`, {
method: 'POST',
body: formData,
});
const response = await fetch(`${SERVER_URL}/api/images?forward=supabase&original=true`, {
method: 'POST',
body: formData,
});
if (!response.ok) {
const errorText = await response.text();
console.error('Proxy upload failed:', errorText);
throw new Error(`Failed to upload image via proxy: ${response.statusText}`);
}
const data = await response.json();
return { publicUrl: data.url, meta: data.meta };
} else {
// Direct Supabase upload
console.log(`File size (${file.size}) within threshold (${MAX_SIZE}), uploading directly...`);
const fileExt = file.name.split('.').pop();
// Generate a unique filename using user ID and timestamp/random string
const fileName = `${userId}/${Date.now()}-${Math.random().toString(36).substring(7)}.${fileExt}`;
const { error: uploadError } = await supabase.storage
.from('pictures')
.upload(fileName, file);
if (uploadError) throw uploadError;
const { data: { publicUrl } } = supabase.storage
.from('pictures')
.getPublicUrl(fileName);
return { publicUrl };
if (!response.ok) {
const errorText = await response.text();
console.error('Server upload failed:', errorText);
throw new Error(`Failed to upload image via server: ${response.statusText}`);
}
const data = await response.json();
return { publicUrl: data.url, meta: data.meta };
};
/**

View File

@ -20,7 +20,7 @@ export const EmailPreviewPanel = ({
iframeRef,
authToken,
}: EmailPreviewPanelProps) => {
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://localhost:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
const previewPath = orgSlug
? `/org/${orgSlug}/user/${page.owner}/pages/${page.slug}/email-preview`
: `/user/${page.owner}/pages/${page.slug}/email-preview`;

View File

@ -32,7 +32,7 @@ export function useEmailActions({ page, orgSlug }: UseEmailActionsParams) {
setIsSendingEmail(true);
try {
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://localhost:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
const endpoint = orgSlug
? `${serverUrl}/org/${orgSlug}/user/${page.owner}/pages/${page.slug}/email-send`
: `${serverUrl}/user/${page.owner}/pages/${page.slug}/email-send`;

View File

@ -279,7 +279,7 @@ export const fetchMediaItemsByIds = async (
}
// Call server API endpoint
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://localhost:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
const response = await fetch(`${serverUrl}/api/media-items?${params.toString()}`);
if (!response.ok) {

View File

@ -87,7 +87,7 @@ const PlaygroundImageEditor = () => {
formData.append('file', file);
formData.append('operations', JSON.stringify(ops));
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://192.168.1.11:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
const res = await fetch(`${serverUrl}/api/images/transform`, {
method: 'POST',
body: formData

View File

@ -47,7 +47,7 @@ const VideoPlayerPlaygroundIntern = () => {
};
const trackProgress = (id: string) => {
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://192.168.1.11:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
const eventSource = new EventSource(`${serverUrl}/api/videos/jobs/${id}/progress`);
eventSource.onmessage = (event) => {
@ -77,7 +77,7 @@ const VideoPlayerPlaygroundIntern = () => {
};
const pollJob = async (id: string) => {
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://192.168.1.11:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
let attempts = 0;
const maxAttempts = 60; // 2 minutes
@ -132,7 +132,7 @@ const VideoPlayerPlaygroundIntern = () => {
const formData = new FormData();
formData.append('file', file);
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://192.168.1.11:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
try {
const xhr = new XMLHttpRequest();

View File

@ -9,7 +9,7 @@ export const uploadInternalVideo = async (
onProgress?: (progress: number) => void
): Promise<{ dbId: string; thumbnailUrl: string; meta: any }> => {
return new Promise((resolve, reject) => {
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || 'http://192.168.1.11:3333';
const serverUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL;
const formData = new FormData();
formData.append('file', file);
const title = file.name.replace(/\.[^/.]+$/, '');