feat: add cover selection workflow and docker profiles
This commit is contained in:
@@ -80,6 +80,23 @@ const cropImage = async (file, normalizedConfig) => {
|
||||
return { blob, url };
|
||||
};
|
||||
|
||||
const buildCropResult = (imageMeta, blob, url) => ({
|
||||
id: imageMeta.id,
|
||||
filename: imageMeta.file?.name || imageMeta.filename,
|
||||
blob,
|
||||
url,
|
||||
order: imageMeta.order,
|
||||
});
|
||||
|
||||
export const cropSingleImage = async (image, config) => {
|
||||
if (!config || !config.imageWidth) {
|
||||
throw new Error('Kapak için geçerli bir crop ayarı bulunamadı.');
|
||||
}
|
||||
const normalized = normalizeCropConfig(config);
|
||||
const { blob, url } = await cropImage(image.file, normalized);
|
||||
return buildCropResult(image, blob, url);
|
||||
};
|
||||
|
||||
export const applyCropToImages = async (images, config) => {
|
||||
if (!images?.length) {
|
||||
throw new Error('Önce görsel yüklemelisin.');
|
||||
@@ -91,13 +108,7 @@ export const applyCropToImages = async (images, config) => {
|
||||
const results = [];
|
||||
for (const image of images) {
|
||||
const { blob, url } = await cropImage(image.file, normalized);
|
||||
results.push({
|
||||
id: image.id,
|
||||
filename: image.file.name,
|
||||
blob,
|
||||
url,
|
||||
order: image.order,
|
||||
});
|
||||
results.push(buildCropResult(image, blob, url));
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
@@ -8,13 +8,38 @@ const base64ToBlob = (base64, mimeType) => {
|
||||
return new Blob([bytes], { type: mimeType });
|
||||
};
|
||||
|
||||
const blobToBase64 = (blob) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
const result = reader.result;
|
||||
if (typeof result === 'string') {
|
||||
const commaIndex = result.indexOf(',');
|
||||
resolve(result.slice(commaIndex + 1));
|
||||
} else {
|
||||
reject(new Error('Kapak dosyası okunamadı.'));
|
||||
}
|
||||
};
|
||||
reader.onerror = () => reject(new Error('Kapak dosyası okunamadı.'));
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
|
||||
const API_BASE = import.meta.env.VITE_API_BASE_URL || 'http://localhost:4000';
|
||||
|
||||
export const createEpubFromOcr = async (text) => {
|
||||
export const createEpubFromOcr = async (text, coverImage) => {
|
||||
if (!text?.trim()) {
|
||||
throw new Error('Önce OCR adımını tamamlamalısın.');
|
||||
}
|
||||
|
||||
let coverPayload = null;
|
||||
if (coverImage?.blob) {
|
||||
coverPayload = {
|
||||
data: await blobToBase64(coverImage.blob),
|
||||
mimeType: coverImage.blob.type || 'image/png',
|
||||
filename: coverImage.filename || `cover-${Date.now()}.png`,
|
||||
};
|
||||
}
|
||||
|
||||
const response = await fetch(`${API_BASE}/generate-epub`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
@@ -25,6 +50,7 @@ export const createEpubFromOcr = async (text) => {
|
||||
author: 'imgPub',
|
||||
filename: `imgpub${Date.now()}.epub`,
|
||||
},
|
||||
cover: coverPayload,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user