Fix double audio playback and add UID handling for personal stream

- Fixed double playback issue on stream page by properly scoping event delegation in streams-ui.js
- Added init-personal-stream.js to handle UID for personal stream playback
- Improved error handling and logging for audio playback
- Added proper event propagation control to prevent duplicate event handling
This commit is contained in:
oib
2025-07-18 16:51:39 +02:00
parent 17616ac5b8
commit 402e920bc6
24 changed files with 4074 additions and 1090 deletions

69
static/css/colors.css Normal file
View File

@ -0,0 +1,69 @@
/*
* Color System Documentation
*
* This file documents the color variables used throughout the application.
* All colors should be defined as CSS variables in :root, and these variables
* should be used consistently across all CSS and JavaScript files.
*/
:root {
/* Primary Colors */
--primary-color: #4a6fa5; /* Main brand color */
--primary-hover: #3a5a8c; /* Darker shade for hover states */
/* Text Colors */
--text-color: #f0f0f0; /* Main text color */
--text-muted: #888; /* Secondary text, less important info */
--text-light: #999; /* Lighter text for disabled states */
--text-lighter: #bbb; /* Very light text, e.g., placeholders */
/* Background Colors */
--background: #1a1a1a; /* Main background color */
--surface: #2a2a2a; /* Surface color for cards, panels, etc. */
--code-bg: #222; /* Background for code blocks */
/* Border Colors */
--border: #444; /* Default border color */
--border-light: #555; /* Lighter border */
--border-lighter: #666; /* Even lighter border */
/* Status Colors */
--success: #2e8b57; /* Success messages, confirmations */
--warning: #ff6600; /* Warnings, important notices */
--error: #ff4444; /* Error messages, destructive actions */
--error-hover: #ff6666; /* Hover state for error buttons */
--info: #1e90ff; /* Informational messages, links */
--link-hover: #74c0fc; /* Hover state for links */
/* Transitions */
--transition: all 0.2s ease; /* Default transition */
}
/*
* Usage Examples:
*
* .button {
* background-color: var(--primary-color);
* color: var(--text-color);
* border: 1px solid var(--border);
* transition: var(--transition);
* }
*
* .button:hover {
* background-color: var(--primary-hover);
* }
*
* .error-message {
* color: var(--error);
* background-color: color-mix(in srgb, var(--error) 10%, transparent);
* border-left: 3px solid var(--error);
* }
*/
/*
* Accessibility Notes:
* - Ensure text has sufficient contrast with its background
* - Use semantic color names that describe the purpose, not the color
* - Test with color blindness simulators for accessibility
* - Maintain consistent color usage throughout the application
*/

View File

@ -0,0 +1,268 @@
/* File upload and list styles */
#user-upload-area {
border: 2px dashed var(--border);
border-radius: 8px;
padding: 2rem;
text-align: center;
margin: 1rem 0;
cursor: pointer;
transition: all 0.2s ease-in-out;
background-color: var(--surface);
}
#user-upload-area:hover,
#user-upload-area.highlight {
border-color: var(--primary);
background-color: rgba(var(--primary-rgb), 0.05);
}
#user-upload-area p {
margin: 0;
color: var(--text-secondary);
}
#file-list {
list-style: none;
padding: 0;
margin: 1rem 0 0;
}
#file-list {
margin: 1.5rem 0;
padding: 0;
}
#file-list li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.75rem 1rem;
margin: 0.5rem 0;
background-color: var(--surface);
border-radius: 6px;
border: 1px solid var(--border);
transition: all 0.2s ease-in-out;
}
#file-list li:hover {
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
transform: translateY(-1px);
}
#file-list li.no-files,
#file-list li.loading-message,
#file-list li.error-message {
display: block;
text-align: center;
color: var(--text-muted);
padding: 2rem 1.5rem;
background-color: transparent;
border: 2px dashed var(--border);
margin: 1rem 0;
border-radius: 8px;
font-size: 1.1em;
}
#file-list li.loading-message {
color: var(--primary);
font-style: italic;
}
#file-list li.error-message {
color: var(--error);
border-color: var(--error);
}
#file-list li.error-message .login-link {
color: var(--primary);
text-decoration: none;
font-weight: bold;
margin-left: 0.3em;
}
#file-list li.error-message .login-link:hover {
text-decoration: underline;
}
#file-list li.no-files:hover {
background-color: rgba(var(--primary-rgb), 0.05);
border-color: var(--primary);
transform: none;
box-shadow: none;
}
.file-item {
width: 100%;
}
.file-info {
display: flex;
align-items: center;
flex: 1;
min-width: 0; /* Allows text truncation */
}
.file-icon {
margin-right: 0.75rem;
font-size: 1.2em;
flex-shrink: 0;
}
.file-name {
color: var(--primary);
text-decoration: none;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 0.5rem;
}
.file-name:hover {
text-decoration: underline;
}
.file-size {
color: var(--text-muted);
font-size: 0.85em;
margin-left: 0.5rem;
white-space: nowrap;
flex-shrink: 0;
}
.file-actions {
display: flex;
gap: 0.5rem;
margin-left: 1rem;
flex-shrink: 0;
}
.download-button,
.delete-button {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.4rem 0.8rem;
border-radius: 4px;
font-size: 0.85rem;
cursor: pointer;
transition: all 0.2s ease;
text-decoration: none;
border: 1px solid transparent;
}
.download-button {
background-color: var(--primary);
color: white;
}
.download-button:hover {
background-color: var(--primary-hover);
transform: translateY(-1px);
}
.delete-button {
background-color: transparent;
color: var(--error);
border-color: var(--error);
}
.delete-button:hover {
background-color: rgba(var(--error-rgb), 0.1);
}
.button-icon {
font-size: 1em;
}
.button-text {
display: none;
}
/* Show text on larger screens */
@media (min-width: 640px) {
.button-text {
display: inline;
}
.download-button,
.delete-button {
padding: 0.4rem 1rem;
}
}
/* Responsive adjustments */
@media (max-width: 480px) {
#file-list li {
flex-direction: column;
align-items: flex-start;
gap: 0.75rem;
}
.file-actions {
width: 100%;
margin-left: 0;
justify-content: flex-end;
}
.file-name {
max-width: 100%;
}
}
#file-list li a {
color: var(--primary);
text-decoration: none;
flex-grow: 1;
margin-right: 1rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#file-list li a:hover {
text-decoration: underline;
}
.file-size {
color: var(--text-secondary);
font-size: 0.9em;
margin-left: 0.5rem;
}
.delete-file {
background: none;
border: none;
color: var(--error);
cursor: pointer;
padding: 0.25rem 0.5rem;
border-radius: 4px;
transition: background-color 0.2s;
}
.delete-file:hover {
background-color: rgba(var(--error-rgb), 0.1);
}
/* Loading state */
#file-list.loading {
opacity: 0.7;
pointer-events: none;
}
/* Mobile optimizations */
@media (max-width: 768px) {
#user-upload-area {
padding: 1.5rem 1rem;
}
#file-list li {
padding: 0.5rem;
font-size: 0.9rem;
}
.file-size {
display: block;
margin-left: 0;
margin-top: 0.25rem;
}
}

View File

@ -1,7 +1,7 @@
/* Footer styles */
footer {
background: #2c3e50;
color: #ecf0f1;
color: var(--text-color);
padding: 2rem 0;
margin-top: 3rem;
width: 100%;
@ -26,30 +26,30 @@ footer {
}
.footer-links a {
color: #ecf0f1;
color: var(--text-color);
text-decoration: none;
transition: color 0.2s;
}
.footer-links a:hover,
.footer-links a:focus {
color: #3498db;
color: var(--info);
text-decoration: underline;
}
.separator {
color: #7f8c8d;
color: var(--text-muted);
margin: 0 0.25rem;
}
.footer-hint {
margin-top: 1rem;
font-size: 0.9rem;
color: #bdc3c7;
color: var(--text-light);
}
.footer-hint a {
color: #3498db;
color: var(--info);
text-decoration: none;
}

View File

@ -81,7 +81,7 @@ header {
.nav-link:focus {
background: rgba(255, 255, 255, 0.1);
text-decoration: none;
color: #fff;
color: var(--text-color);
}
/* Active navigation item */

54
static/css/section.css Normal file
View File

@ -0,0 +1,54 @@
/* section.css - Centralized visibility control with class-based states */
/* Base section visibility - all sections hidden by default */
main > section {
display: none;
position: absolute;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
opacity: 0;
}
/* Active section styling - only visibility properties */
main > section.active {
display: block;
position: relative;
overflow: visible;
clip: auto;
white-space: normal;
opacity: 1;
}
/* Authentication-based visibility classes */
.guest-only { display: block; }
.auth-only {
display: none;
}
/* Show auth-only elements when authenticated */
body.authenticated .auth-only {
display: block;
}
/* Ensure me-page and its direct children are visible when me-page is active */
#me-page:not([hidden]) > .auth-only,
#me-page:not([hidden]) > section,
#me-page:not([hidden]) > article,
#me-page:not([hidden]) > div,
/* Ensure account deletion section is visible when privacy page is active and user is authenticated */
#privacy-page:not([hidden]) .auth-only,
#privacy-page:not([hidden]) #account-deletion {
display: block !important;
visibility: visible !important;
opacity: 1 !important;
}
body.authenticated .guest-only {
display: none;
}
.always-visible {
display: block !important;
}