canvascraft / app.js
Onise's picture
implement feature
2c66926 verified
// ShortForge AI – App logic
class ShortForgeApp {
constructor() {
this.currentTemplate = 'narration';
this.generated = false;
this.voices = {
'fr-lea': { name: 'Lea', lang: 'fr-FR', gender: 'female' },
'fr-remy': { name: 'Rémy', lang: 'fr-FR', gender: 'male' },
'en-bella': { name: 'Bella', lang: 'en-US', gender: 'female' },
'en-mat': { name: 'Mat', lang: 'en-US', gender: 'male' }
};
this.init();
}
init() {
this.bindEvents();
this.updateTemplateButtons();
}
bindEvents() {
// Template buttons
document.querySelectorAll('.template-btn').forEach(btn => {
btn.addEventListener('click', e => {
document.querySelectorAll('.template-btn').forEach(b => b.classList.remove('active'));
e.target.classList.add('active');
this.currentTemplate = e.target.dataset.template;
this.updateTemplatePreview();
});
});
// Generate
document.getElementById('voiceSelect').addEventListener('change', () => this.updateVoicePreview());
document.getElementById('generateBtn').addEventListener('click', () => this.generate());
// Download
document.getElementById('downloadBtn').addEventListener('click', () => this.download());
// File upload
document.getElementById('loadTxt').addEventListener('click', () => this.loadTxt());
document.getElementById('loadReddit').addEventListener('click', () => this.loadReddit());
}
updateTemplateButtons() {
document.querySelectorAll('.template-btn').forEach(btn => {
btn.classList.toggle('active', btn.dataset.template === this.currentTemplate);
});
}
updateTemplatePreview() {
const templates = {
narration: 'Narration douce avec transitions lentes.',
reddit: 'Reddit story rythmé pour maximiser le retention.',
educatif: 'Format éducatif avec captions synchronisés.',
top5: 'Top 5 dynamique avec effets punchy.'
};
const desc = templates[this.currentTemplate];
const preview = document.createElement('div');
preview.className = 'mt-2 text-xs text-gray-400';
preview.textContent = desc;
const existing = document.querySelector('#templateDesc');
if (existing) existing.remove();
preview.id = 'templateDesc';
document.querySelector('.template-btn.active').parentElement.appendChild(preview);
}
updateVoicePreview() {
const select = document.getElementById('voiceSelect');
const voiceId = select.value;
const voice = this.voices[voiceId];
const preview = document.createElement('div');
preview.className = 'mt-2 text-xs text-gray-400';
preview.textContent = `${voice.name}${voice.lang} (${voice.gender})`;
const existing = document.querySelector('#voiceDesc');
if (existing) existing.remove();
preview.id = 'voiceDesc';
select.parentElement.appendChild(preview);
}
async loadTxt() {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.txt';
input.onchange = e => {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = evt => {
document.getElementById('scriptInput').value = evt.target.result;
};
reader.readAsText(file);
};
input.click();
}
loadReddit() {
const url = prompt('Collez l’URL Reddit du post :');
if (!url) return;
// Mock fetch
document.getElementById('scriptInput').value = 'Mock Reddit story récupéré !';
}
async generate() {
const script = document.getElementById('scriptInput').value.trim();
if (!script) return alert('Veuillez entrer un script.');
const btn = document.getElementById('generateBtn');
const original = btn.innerHTML;
btn.disabled = true;
btn.innerHTML = '<i data-feather="loader" class="inline w-5 h-5 mr-2 animate-spin"></i>Génération…';
feather.replace();
// Simulate API
await new Promise(r => setTimeout(r, 3000));
// Fake video
const video = document.getElementById('previewVideo');
video.src = 'https://sample-videos.com/shorts/9-16/mp4/20.mp4';
document.getElementById('previewPlayer').classList.remove('hidden');
document.getElementById('previewPlaceholder').classList.add('hidden');
document.getElementById('downloadBtn').classList.remove('hidden');
// Save to localStorage
const history = JSON.parse(localStorage.getItem('sf-history') || '[]');
history.unshift({ script, template: this.currentTemplate, timestamp: Date.now() });
localStorage.setItem('sf-history', JSON.stringify(history.slice(0, 10)));
this.generated = true;
btn.disabled = false;
btn.innerHTML = original;
feather.replace();
}
download() {
if (!this.generated) return;
const link = document.createElement('a');
link.href = 'https://sample-videos.com/shorts/9-16/mp4/20.mp4';
link.download = 'shortforge-video.mp4';
link.click();
}
}
document.addEventListener('DOMContentLoaded', () => {
new ShortForgeApp();
});
// History quick-load
window.addEventListener('load', () => {
const history = JSON.parse(localStorage.getItem('sf-history') || '[]');
if (history.length > 0) {
const last = history[0];
document.getElementById('scriptInput').placeholder = `Dernier script: "${last.script.substring(0, 50)}…"`;
}
});