mirror of
https://github.com/wahyd4/links.git
synced 2026-08-09 05:06:16 +10:00
Load text through url
This commit is contained in:
@@ -331,6 +331,52 @@
|
||||
border-color: #9ca3af;
|
||||
}
|
||||
|
||||
/* Loading overlay styles */
|
||||
.loading-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(4px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.3s ease, visibility 0.3s ease;
|
||||
}
|
||||
|
||||
.loading-overlay.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 4px solid #e5e7eb;
|
||||
border-top: 4px solid #8e44ad;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
color: #374151;
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.tts-container {
|
||||
padding: 1rem;
|
||||
@@ -354,6 +400,15 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Loading Overlay -->
|
||||
<div id="loading-overlay" class="loading-overlay">
|
||||
<div class="loading-spinner"></div>
|
||||
<div class="loading-text">
|
||||
<div id="loading-message">{% trans "Preparing Text-to-Speech..." %}</div>
|
||||
<div class="text-sm text-gray-500 mt-2">{% trans "Please wait while we process your text" %}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tts-container">
|
||||
<!-- Header -->
|
||||
<div class="tts-header">
|
||||
@@ -777,7 +832,140 @@ function downloadAudio() {
|
||||
|
||||
// Auto-focus on text input when page loads
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.getElementById('text-input').focus();
|
||||
const textInput = document.getElementById('text-input');
|
||||
|
||||
// Check for URL parameters
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const textParam = urlParams.get('text');
|
||||
|
||||
if (textParam) {
|
||||
// Show loading overlay
|
||||
showLoadingOverlay();
|
||||
|
||||
// Decode and set the text
|
||||
const decodedText = decodeURIComponent(textParam);
|
||||
textInput.value = decodedText;
|
||||
textInput.dispatchEvent(new Event('input')); // Update character counter
|
||||
|
||||
// Auto-generate TTS after a short delay to ensure UI is ready
|
||||
setTimeout(() => {
|
||||
updateLoadingMessage('{% trans "Generating speech audio..." %}');
|
||||
generateSpeechFromURL();
|
||||
}, 500);
|
||||
} else {
|
||||
// Normal behavior - just focus the input
|
||||
textInput.focus();
|
||||
}
|
||||
});
|
||||
|
||||
function showLoadingOverlay() {
|
||||
const overlay = document.getElementById('loading-overlay');
|
||||
overlay.classList.add('show');
|
||||
}
|
||||
|
||||
function hideLoadingOverlay() {
|
||||
const overlay = document.getElementById('loading-overlay');
|
||||
overlay.classList.remove('show');
|
||||
}
|
||||
|
||||
function updateLoadingMessage(message) {
|
||||
const loadingMessage = document.getElementById('loading-message');
|
||||
loadingMessage.textContent = message;
|
||||
}
|
||||
|
||||
function generateSpeechFromURL() {
|
||||
const textInput = document.getElementById('text-input');
|
||||
const text = textInput.value.trim();
|
||||
|
||||
if (!text) {
|
||||
hideLoadingOverlay();
|
||||
alert('{% trans "No text found in URL parameter." %}');
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the existing generateSpeech logic but with URL-specific handling
|
||||
if (isLoading) return;
|
||||
|
||||
isLoading = true;
|
||||
const speakBtn = document.getElementById('speak-btn');
|
||||
const audioPlayer = document.getElementById('audio-player');
|
||||
const status = document.getElementById('audio-status');
|
||||
const playBtn = document.getElementById('play-pause-btn');
|
||||
|
||||
// Show audio player and update status (but keep loading overlay)
|
||||
audioPlayer.style.display = 'block';
|
||||
status.textContent = '{% trans "Generating..." %}';
|
||||
status.className = 'audio-status status-generating';
|
||||
speakBtn.disabled = true;
|
||||
speakBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>{% trans "Generating..." %}';
|
||||
playBtn.disabled = true;
|
||||
|
||||
fetch('{% url "tts-api" %}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRFToken': '{{ csrf_token }}',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
text: text
|
||||
})
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('TTS generation failed');
|
||||
}
|
||||
return response.blob();
|
||||
})
|
||||
.then(blob => {
|
||||
// Store the blob for download functionality
|
||||
currentAudioBlob = blob;
|
||||
|
||||
const audioUrl = URL.createObjectURL(blob);
|
||||
const audio = document.getElementById('tts-audio');
|
||||
|
||||
audio.src = audioUrl;
|
||||
currentAudio = audio;
|
||||
|
||||
audio.addEventListener('loadedmetadata', function() {
|
||||
status.textContent = '{% trans "Ready" %}';
|
||||
status.className = 'audio-status status-ready';
|
||||
playBtn.disabled = false;
|
||||
document.getElementById('download-btn').disabled = false;
|
||||
updateTotalTime();
|
||||
setupAudioEvents();
|
||||
|
||||
// Hide loading overlay - audio is ready
|
||||
updateLoadingMessage('{% trans "Audio ready! Click play to start..." %}');
|
||||
setTimeout(() => {
|
||||
hideLoadingOverlay();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
audio.addEventListener('error', function() {
|
||||
status.textContent = '{% trans "Error" %}';
|
||||
status.className = 'audio-status status-error';
|
||||
playBtn.disabled = true;
|
||||
document.getElementById('download-btn').disabled = true;
|
||||
hideLoadingOverlay();
|
||||
alert('{% trans "Failed to generate audio. Please try again." %}');
|
||||
});
|
||||
|
||||
audio.load();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('TTS Error:', error);
|
||||
status.textContent = '{% trans "Failed" %}';
|
||||
status.className = 'audio-status status-error';
|
||||
playBtn.disabled = true;
|
||||
document.getElementById('download-btn').disabled = true;
|
||||
hideLoadingOverlay();
|
||||
alert('{% trans "Failed to generate audio. Please try again." %}');
|
||||
})
|
||||
.finally(() => {
|
||||
isLoading = false;
|
||||
speakBtn.disabled = false;
|
||||
speakBtn.innerHTML = '<i class="fas fa-volume-up mr-2"></i>{% trans "Speak" %}';
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user