mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: add HEIC preview support to collage store
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { COLLAGE_TEMPLATES, getDefaultTemplate } from "@/lib/collage-templates";
|
import { COLLAGE_TEMPLATES, getDefaultTemplate } from "@/lib/collage-templates";
|
||||||
|
import { fetchDecodedPreview, needsServerPreview, revokePreviewUrl } from "@/lib/image-preview";
|
||||||
|
|
||||||
export type AspectRatio = "free" | "1:1" | "4:3" | "3:2" | "16:9" | "9:16" | "4:5";
|
export type AspectRatio = "free" | "1:1" | "4:3" | "3:2" | "16:9" | "9:16" | "4:5";
|
||||||
export type OutputFormat = "png" | "jpeg" | "webp";
|
export type OutputFormat = "png" | "jpeg" | "webp";
|
||||||
@@ -9,6 +10,8 @@ export interface CollageImage {
|
|||||||
id: string;
|
id: string;
|
||||||
file: File;
|
file: File;
|
||||||
blobUrl: string;
|
blobUrl: string;
|
||||||
|
previewBlobUrl?: string;
|
||||||
|
previewLoading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CellTransform {
|
export interface CellTransform {
|
||||||
@@ -110,6 +113,7 @@ export const useCollageStore = create<CollageState>((set, get) => ({
|
|||||||
id: `img-${++nextImageId}`,
|
id: `img-${++nextImageId}`,
|
||||||
file: f,
|
file: f,
|
||||||
blobUrl: URL.createObjectURL(f),
|
blobUrl: URL.createObjectURL(f),
|
||||||
|
previewLoading: needsServerPreview(f),
|
||||||
}));
|
}));
|
||||||
const state = get();
|
const state = get();
|
||||||
const allImages = [...state.images, ...newImages];
|
const allImages = [...state.images, ...newImages];
|
||||||
@@ -127,12 +131,33 @@ export const useCollageStore = create<CollageState>((set, get) => ({
|
|||||||
resultSize: null,
|
resultSize: null,
|
||||||
error: null,
|
error: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const img of newImages) {
|
||||||
|
if (img.previewLoading) {
|
||||||
|
const imgId = img.id;
|
||||||
|
fetchDecodedPreview(img.file).then((url) => {
|
||||||
|
const current = get();
|
||||||
|
const idx = current.images.findIndex((i) => i.id === imgId);
|
||||||
|
if (idx === -1) return;
|
||||||
|
const updated = [...current.images];
|
||||||
|
updated[idx] = {
|
||||||
|
...updated[idx],
|
||||||
|
previewLoading: false,
|
||||||
|
...(url ? { previewBlobUrl: url } : {}),
|
||||||
|
};
|
||||||
|
set({ images: updated });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
removeImage: (index) => {
|
removeImage: (index) => {
|
||||||
const state = get();
|
const state = get();
|
||||||
const img = state.images[index];
|
const img = state.images[index];
|
||||||
if (img) URL.revokeObjectURL(img.blobUrl);
|
if (img) {
|
||||||
|
URL.revokeObjectURL(img.blobUrl);
|
||||||
|
if (img.previewBlobUrl) revokePreviewUrl(img.previewBlobUrl);
|
||||||
|
}
|
||||||
const newImages = state.images.filter((_, i) => i !== index);
|
const newImages = state.images.filter((_, i) => i !== index);
|
||||||
if (newImages.length === 0) {
|
if (newImages.length === 0) {
|
||||||
get().reset();
|
get().reset();
|
||||||
@@ -152,7 +177,10 @@ export const useCollageStore = create<CollageState>((set, get) => ({
|
|||||||
|
|
||||||
clearImages: () => {
|
clearImages: () => {
|
||||||
const state = get();
|
const state = get();
|
||||||
for (const img of state.images) URL.revokeObjectURL(img.blobUrl);
|
for (const img of state.images) {
|
||||||
|
URL.revokeObjectURL(img.blobUrl);
|
||||||
|
if (img.previewBlobUrl) revokePreviewUrl(img.previewBlobUrl);
|
||||||
|
}
|
||||||
set({
|
set({
|
||||||
images: [],
|
images: [],
|
||||||
cellAssignments: [],
|
cellAssignments: [],
|
||||||
@@ -237,7 +265,10 @@ export const useCollageStore = create<CollageState>((set, get) => ({
|
|||||||
setError: (e) => set({ error: e, phase: "editing" }),
|
setError: (e) => set({ error: e, phase: "editing" }),
|
||||||
reset: () => {
|
reset: () => {
|
||||||
const state = get();
|
const state = get();
|
||||||
for (const img of state.images) URL.revokeObjectURL(img.blobUrl);
|
for (const img of state.images) {
|
||||||
|
URL.revokeObjectURL(img.blobUrl);
|
||||||
|
if (img.previewBlobUrl) revokePreviewUrl(img.previewBlobUrl);
|
||||||
|
}
|
||||||
nextImageId = 0;
|
nextImageId = 0;
|
||||||
set({
|
set({
|
||||||
images: [],
|
images: [],
|
||||||
|
|||||||
Reference in New Issue
Block a user