286 lines
10 KiB
JavaScript
286 lines
10 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
||
const form = document.getElementById('generation-form');
|
||
const mediaType = document.getElementById('media-type');
|
||
const videoProviderContainer = document.getElementById('video-provider-container');
|
||
const generateBtn = document.getElementById('generate-btn');
|
||
const placeholderText = document.getElementById('placeholder-text');
|
||
const loadingState = document.getElementById('loading-state');
|
||
const contentContainer = document.getElementById('content-container');
|
||
const actionButtons = document.getElementById('action-buttons');
|
||
const downloadBtn = document.getElementById('download-btn');
|
||
const editBtn = document.getElementById('edit-btn');
|
||
const providerBadge = document.getElementById('provider-badge');
|
||
const infoOverlay = document.getElementById('info-overlay');
|
||
const statusMessage = document.getElementById('status-message');
|
||
|
||
// Editor Elements
|
||
const editorModal = new bootstrap.Modal(document.getElementById('editorModal'));
|
||
const editorCanvas = document.getElementById('editor-canvas');
|
||
const ctx = editorCanvas.getContext('2d');
|
||
const filterRanges = document.querySelectorAll('.filter-range');
|
||
const resetFiltersBtn = document.getElementById('reset-filters');
|
||
const saveEditedBtn = document.getElementById('save-edited-btn');
|
||
const editorLoading = document.getElementById('editor-loading');
|
||
|
||
// AI Magic Elements
|
||
const aiEditPrompt = document.getElementById('ai-edit-prompt');
|
||
const applyAiMagicBtn = document.getElementById('apply-ai-magic');
|
||
const removeBgBtn = document.getElementById('remove-bg-btn');
|
||
const upscaleBtn = document.getElementById('upscale-btn');
|
||
|
||
let currentImage = null;
|
||
let originalPrompt = '';
|
||
|
||
// Local storage for settings
|
||
const getRapidKey = () => localStorage.getItem('rapidapi_key') || '';
|
||
const setRapidKey = (key) => localStorage.setItem('rapidapi_key', key);
|
||
|
||
// Sync input with local storage
|
||
const keyInput = document.getElementById('rapidapi-key-input');
|
||
if (keyInput) {
|
||
keyInput.value = getRapidKey();
|
||
keyInput.addEventListener('change', (e) => setRapidKey(e.target.value));
|
||
}
|
||
|
||
// Toggle video provider field
|
||
mediaType.addEventListener('change', () => {
|
||
if (mediaType.value === 'video') {
|
||
videoProviderContainer.style.display = 'block';
|
||
} else {
|
||
videoProviderContainer.style.display = 'none';
|
||
}
|
||
});
|
||
|
||
form.addEventListener('submit', async (e) => {
|
||
e.preventDefault();
|
||
|
||
const formData = new FormData(form);
|
||
formData.append('rapidapi_key', getRapidKey());
|
||
originalPrompt = formData.get('prompt');
|
||
|
||
// UI State: Loading
|
||
placeholderText.classList.add('d-none');
|
||
contentContainer.classList.add('d-none');
|
||
actionButtons.classList.add('d-none');
|
||
infoOverlay.classList.add('d-none');
|
||
statusMessage.classList.add('d-none');
|
||
loadingState.classList.remove('d-none');
|
||
generateBtn.disabled = true;
|
||
|
||
try {
|
||
const response = await fetch('api/generate.php', {
|
||
method: 'POST',
|
||
body: formData
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
renderResult(result);
|
||
} else {
|
||
alert('Ошибка: ' + (result.error || 'Что-то пошло не так'));
|
||
resetUI();
|
||
}
|
||
} catch (error) {
|
||
console.error('Generation error:', error);
|
||
alert('Сетевая ошибка при генерации');
|
||
resetUI();
|
||
} finally {
|
||
loadingState.classList.add('d-none');
|
||
generateBtn.disabled = false;
|
||
}
|
||
});
|
||
|
||
function renderResult(result) {
|
||
contentContainer.innerHTML = '';
|
||
contentContainer.classList.remove('d-none');
|
||
actionButtons.classList.remove('d-none');
|
||
infoOverlay.classList.remove('d-none');
|
||
|
||
providerBadge.textContent = result.provider;
|
||
if (result.is_ai) {
|
||
providerBadge.className = 'badge badge-ai shadow-sm';
|
||
} else {
|
||
providerBadge.className = 'badge badge-stock shadow-sm';
|
||
}
|
||
|
||
if (result.message) {
|
||
statusMessage.textContent = result.message;
|
||
statusMessage.classList.remove('d-none');
|
||
}
|
||
|
||
if (result.type === 'photo') {
|
||
const img = document.createElement('img');
|
||
img.src = result.url;
|
||
img.className = 'img-fluid shadow-sm rounded mx-auto d-block';
|
||
img.style.maxHeight = '480px';
|
||
img.style.objectFit = 'contain';
|
||
img.id = 'active-result-img';
|
||
contentContainer.appendChild(img);
|
||
|
||
editBtn.classList.remove('d-none');
|
||
editBtn.onclick = () => {
|
||
originalPrompt = result.prompt || originalPrompt;
|
||
openEditor(result.url);
|
||
};
|
||
} else {
|
||
const video = document.createElement('video');
|
||
video.src = result.url;
|
||
video.controls = true;
|
||
video.autoplay = true;
|
||
video.className = 'rounded mx-auto d-block shadow-sm';
|
||
video.style.maxWidth = '100%';
|
||
video.style.maxHeight = '480px';
|
||
contentContainer.appendChild(video);
|
||
editBtn.classList.add('d-none');
|
||
}
|
||
|
||
downloadBtn.onclick = () => {
|
||
const a = document.createElement('a');
|
||
a.href = result.url;
|
||
a.download = `generation_${Date.now()}.${result.type === 'photo' ? 'jpg' : 'mp4'}`;
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
document.body.removeChild(a);
|
||
};
|
||
}
|
||
|
||
function resetUI() {
|
||
placeholderText.classList.remove('d-none');
|
||
contentContainer.classList.add('d-none');
|
||
actionButtons.classList.add('d-none');
|
||
infoOverlay.classList.add('d-none');
|
||
}
|
||
|
||
// Editor Logic
|
||
function openEditor(url) {
|
||
currentImage = new Image();
|
||
currentImage.crossOrigin = "Anonymous";
|
||
currentImage.src = url;
|
||
currentImage.onload = () => {
|
||
editorCanvas.width = currentImage.width;
|
||
editorCanvas.height = currentImage.height;
|
||
applyFilters();
|
||
editorModal.show();
|
||
};
|
||
}
|
||
|
||
function applyFilters() {
|
||
if (!currentImage) return;
|
||
|
||
let filters = '';
|
||
filterRanges.forEach(range => {
|
||
const filter = range.dataset.filter;
|
||
const value = range.value;
|
||
|
||
if (filter === 'brightness' || filter === 'contrast' || filter === 'saturate') {
|
||
filters += `${filter}(${value}%) `;
|
||
} else if (filter === 'blur') {
|
||
filters += `${filter}(${value}px) `;
|
||
} else {
|
||
filters += `${filter}(${value}%) `;
|
||
}
|
||
});
|
||
|
||
ctx.filter = filters;
|
||
ctx.clearRect(0, 0, editorCanvas.width, editorCanvas.height);
|
||
ctx.drawImage(currentImage, 0, 0);
|
||
}
|
||
|
||
filterRanges.forEach(range => {
|
||
range.addEventListener('input', applyFilters);
|
||
});
|
||
|
||
resetFiltersBtn.addEventListener('click', () => {
|
||
filterRanges.forEach(range => {
|
||
if (range.dataset.filter === 'brightness' || range.dataset.filter === 'contrast' || range.dataset.filter === 'saturate') {
|
||
range.value = 100;
|
||
} else {
|
||
range.value = 0;
|
||
}
|
||
});
|
||
applyFilters();
|
||
});
|
||
|
||
saveEditedBtn.addEventListener('click', () => {
|
||
const link = document.createElement('a');
|
||
link.download = `edited_${Date.now()}.png`;
|
||
link.href = editorCanvas.toDataURL('image/png');
|
||
link.click();
|
||
});
|
||
|
||
// AI Magic Handlers
|
||
async function performAiEdit(action, customPrompt = '') {
|
||
if (!currentImage) return;
|
||
|
||
editorLoading.classList.remove('d-none');
|
||
editorLoading.classList.add('d-flex');
|
||
|
||
try {
|
||
const response = await fetch('api/edit.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
action: action,
|
||
original_prompt: originalPrompt,
|
||
edit_prompt: customPrompt,
|
||
image_url: currentImage.src
|
||
})
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
// Load new image into canvas
|
||
const newImg = new Image();
|
||
newImg.crossOrigin = "Anonymous";
|
||
newImg.src = result.url + '?t=' + Date.now();
|
||
newImg.onload = () => {
|
||
currentImage = newImg;
|
||
editorCanvas.width = newImg.width;
|
||
editorCanvas.height = newImg.height;
|
||
applyFilters();
|
||
editorLoading.classList.add('d-none');
|
||
editorLoading.classList.remove('d-flex');
|
||
};
|
||
} else {
|
||
alert('Ошибка ИИ: ' + (result.error || 'Не удалось применить изменения'));
|
||
editorLoading.classList.add('d-none');
|
||
editorLoading.classList.remove('d-flex');
|
||
}
|
||
} catch (error) {
|
||
console.error('AI Edit error:', error);
|
||
alert('Сетевая ошибка при работе с ИИ');
|
||
editorLoading.classList.add('d-none');
|
||
editorLoading.classList.remove('d-flex');
|
||
}
|
||
}
|
||
|
||
applyAiMagicBtn.addEventListener('click', () => {
|
||
const prompt = aiEditPrompt.value.trim();
|
||
if (!prompt) {
|
||
alert('Введите описание изменений');
|
||
return;
|
||
}
|
||
performAiEdit('magic', prompt);
|
||
});
|
||
|
||
removeBgBtn.addEventListener('click', () => {
|
||
performAiEdit('remove_bg');
|
||
});
|
||
|
||
upscaleBtn.addEventListener('click', () => {
|
||
performAiEdit('upscale');
|
||
});
|
||
|
||
// History Edit Buttons
|
||
document.addEventListener('click', (e) => {
|
||
if (e.target.closest('.history-edit-btn')) {
|
||
const btn = e.target.closest('.history-edit-btn');
|
||
const url = btn.dataset.url;
|
||
const card = btn.closest('.card');
|
||
originalPrompt = card.querySelector('.card-text').textContent;
|
||
openEditor(url);
|
||
}
|
||
});
|
||
}); |