- Add uploadHistory.js: localStorage CRUD + canvas thumbnail generation - Add UploadPicker.js: reusable upload button + history panel component - Add i2i/i2v models from schema_data.json to models.js (115 models) - Add generateI2I, generateI2V, uploadFile methods to muapi.js - ImageStudio: dynamically switches between t2i and i2i models based on image presence - VideoStudio: dynamically switches between t2v and i2v models based on image presence - Fix i2i/i2v model display names derived from slugs instead of generic variant labels
52 lines
1.7 KiB
JavaScript
52 lines
1.7 KiB
JavaScript
const STORAGE_KEY = 'muapi_uploads';
|
||
const MAX_UPLOADS = 20;
|
||
|
||
export function getUploadHistory() {
|
||
try {
|
||
return JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
|
||
} catch {
|
||
return [];
|
||
}
|
||
}
|
||
|
||
export function saveUpload({ id, name, uploadedUrl, thumbnail, timestamp }) {
|
||
const history = getUploadHistory();
|
||
history.unshift({ id, name, uploadedUrl, thumbnail, timestamp });
|
||
localStorage.setItem(STORAGE_KEY, JSON.stringify(history.slice(0, MAX_UPLOADS)));
|
||
}
|
||
|
||
export function removeUpload(id) {
|
||
const history = getUploadHistory().filter(e => e.id !== id);
|
||
localStorage.setItem(STORAGE_KEY, JSON.stringify(history));
|
||
}
|
||
|
||
/**
|
||
* Generates a square 80×80 base64 JPEG thumbnail from a File.
|
||
* @param {File} file
|
||
* @returns {Promise<string|null>}
|
||
*/
|
||
export async function generateThumbnail(file) {
|
||
return new Promise((resolve) => {
|
||
const objectUrl = URL.createObjectURL(file);
|
||
const img = new Image();
|
||
img.onload = () => {
|
||
const SIZE = 80;
|
||
const canvas = document.createElement('canvas');
|
||
canvas.width = SIZE;
|
||
canvas.height = SIZE;
|
||
const ctx = canvas.getContext('2d');
|
||
// Center-crop to square
|
||
const size = Math.min(img.width, img.height);
|
||
const sx = (img.width - size) / 2;
|
||
const sy = (img.height - size) / 2;
|
||
ctx.drawImage(img, sx, sy, size, size, 0, 0, SIZE, SIZE);
|
||
URL.revokeObjectURL(objectUrl);
|
||
resolve(canvas.toDataURL('image/jpeg', 0.6));
|
||
};
|
||
img.onerror = () => {
|
||
URL.revokeObjectURL(objectUrl);
|
||
resolve(null);
|
||
};
|
||
img.src = objectUrl;
|
||
});
|
||
}
|