37689-vm/assets/js/main.js
2026-01-25 17:56:38 +00:00

286 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
});
});