File size: 1,497 Bytes
7bafae7
 
 
 
 
561e6f0
 
7bafae7
 
561e6f0
 
7bafae7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561e6f0
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import {
  optimizeImage,
  supportsWebpOptimization,
} from "./image-optimizer";

/**
 * Upload an image file to the backend.
 * Optimizes to WebP variants client-side before uploading.
 * Returns the URL of the largest variant for use in the editor.
 */
export async function uploadImage(file: File): Promise<string> {
  // Try client-side optimization first
  if (supportsWebpOptimization() && file.type.startsWith("image/")) {
    try {
      const optimized = await optimizeImage(file);
      const urls: string[] = [];

      for (const variant of optimized.variants) {
        const ext = "webp";
        const name = file.name.replace(/\.[^.]+$/, "");
        const optimizedFile = new File(
          [variant.blob],
          `${name}-${variant.suffix}.${ext}`,
          { type: "image/webp" }
        );

        const url = await uploadSingleFile(optimizedFile);
        urls.push(url);
      }

      // Return the largest variant URL
      return urls[urls.length - 1];
    } catch (err) {
      console.warn("[upload] Client-side optimization failed, uploading original:", err);
    }
  }

  return uploadSingleFile(file);
}

async function uploadSingleFile(file: File): Promise<string> {
  const form = new FormData();
  form.append("file", file);

  const res = await fetch("/api/upload", { method: "POST", body: form });

  if (!res.ok) {
    const text = await res.text();
    throw new Error(`Upload failed: ${text}`);
  }

  const { url } = await res.json();
  return url;
}