hide messages

This commit is contained in:
Andrey Kondratev
2025-11-10 17:22:10 +05:00
parent 21a32ffc79
commit cd2c3b6989
3 changed files with 71 additions and 6 deletions

View File

@@ -1026,7 +1026,7 @@ class QuixoticApp {
// Remove existing message if any // Remove existing message if any
const existingMessage = document.querySelector('.tg-status-message'); const existingMessage = document.querySelector('.tg-status-message');
if (existingMessage) { if (existingMessage) {
existingMessage.remove(); this.hideMessage(existingMessage as HTMLElement);
} }
// Create message element // Create message element
@@ -1034,15 +1034,37 @@ class QuixoticApp {
messageEl.className = `tg-status-message tg-status-message--${type}`; messageEl.className = `tg-status-message tg-status-message--${type}`;
messageEl.textContent = message; messageEl.textContent = message;
// Add click handler to dismiss
let hideTimeout: NodeJS.Timeout;
const hideHandler = () => {
clearTimeout(hideTimeout);
this.hideMessage(messageEl);
};
messageEl.addEventListener('click', hideHandler);
// Add to body (fixed position, won't affect layout) // Add to body (fixed position, won't affect layout)
document.body.appendChild(messageEl); document.body.appendChild(messageEl);
// Auto-remove after 5 seconds // Auto-remove after 3 seconds (было 5)
hideTimeout = setTimeout(() => {
if (messageEl.parentNode) {
this.hideMessage(messageEl);
}
}, 3000);
}
private hideMessage(messageEl: HTMLElement): void {
// Add hiding class for fade-out animation
messageEl.classList.add('tg-status-message--hiding');
// Remove after animation completes (300ms)
setTimeout(() => { setTimeout(() => {
if (messageEl.parentNode) { if (messageEl.parentNode) {
messageEl.remove(); messageEl.remove();
} }
}, 5000); }, 300);
} }
private escapeHtml(text: string): string { private escapeHtml(text: string): string {
@@ -1133,13 +1155,27 @@ class QuixoticApp {
this.stopAudioPreview(); this.stopAudioPreview();
}); });
// Play audio // Play audio with autoplay error handling
try {
await this.currentAudio.play(); await this.currentAudio.play();
this.triggerHaptic('light'); this.triggerHaptic('light');
} catch (playError: any) {
console.error('Autoplay error:', playError);
// If autoplay is blocked, show message and clean up
if (playError.name === 'NotAllowedError') {
this.stopAudioPreview();
item.classList.remove('tg-list-item--loading-preview');
this.showMessage('🔇 Воспроизведение заблокировано. Нажмите еще раз.', 'warning');
return;
}
throw playError;
}
} catch (error) { } catch (error) {
console.error('Preview error:', error); console.error('Preview error:', error);
item.classList.remove('tg-list-item--loading-preview'); item.classList.remove('tg-list-item--loading-preview');
this.stopAudioPreview();
this.showMessage('❌ Не удалось воспроизвести превью', 'error'); this.showMessage('❌ Не удалось воспроизвести превью', 'error');
} }
} }

View File

@@ -666,6 +666,16 @@ body {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0, 0, 0, 0.12); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0, 0, 0, 0.12);
max-width: 320px; max-width: 320px;
margin: 0 auto; margin: 0 auto;
cursor: pointer;
transition: opacity 0.3s ease, transform 0.3s ease;
}
.tg-status-message:active {
transform: scale(0.98);
}
.tg-status-message--hiding {
animation: tg-fade-out 0.3s ease-out forwards;
} }
.tg-status-message--success { .tg-status-message--success {
@@ -686,6 +696,12 @@ body {
color: #ffffff; color: #ffffff;
} }
.tg-status-message--warning {
background: #ff9500;
border: 1px solid #e68500;
color: #ffffff;
}
@keyframes tg-slide-down { @keyframes tg-slide-down {
from { from {
opacity: 0; opacity: 0;
@@ -698,6 +714,18 @@ body {
} }
} }
@keyframes tg-fade-out {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-12px);
}
}
/* Update notification */ /* Update notification */
.tg-update-notification { .tg-update-notification {
position: fixed; position: fixed;

View File

@@ -29,6 +29,7 @@ app.use((req: Request, res: Response, next) => {
'style-src \'self\' \'unsafe-inline\'; ' + 'style-src \'self\' \'unsafe-inline\'; ' +
'img-src \'self\' data: https:; ' + 'img-src \'self\' data: https:; ' +
'font-src \'self\'; ' + 'font-src \'self\'; ' +
'media-src \'self\' blob: data:; ' +
'connect-src \'self\' https://telegram.org; ' + 'connect-src \'self\' https://telegram.org; ' +
'frame-ancestors \'self\'; ' + 'frame-ancestors \'self\'; ' +
'base-uri \'self\'; ' + 'base-uri \'self\'; ' +