Redesign controls: centered 3-column grid with play/pause

- Center all controls in screen with dark background panel
- 3-column CSS Grid layout:
  Row 1: Prev | Play/Pause | Next
  Row 2: Always On Top | Fullscreen | Auto-Resize
- Add play/pause toggle button (space key)
- Make always-on-top more aggressive (250ms focus interval)
- Update play/pause icon based on media state
- Larger, more prominent navigation buttons
This commit is contained in:
russell@unturf.com 2026-01-21 10:41:25 -05:00
parent 55fe55041f
commit a93d5e457f
2 changed files with 87 additions and 77 deletions

View file

@ -17,6 +17,7 @@
const alwaysOnTopBtn = document.getElementById('alwaysOnTopBtn');
const fullscreenBtn = document.getElementById('fullscreenBtn');
const autoResizeBtn = document.getElementById('autoResizeBtn');
const playPauseBtn = document.getElementById('playPauseBtn');
/**
* Navigate to another product
@ -27,6 +28,19 @@
}
};
/**
* Toggle play/pause
*/
window.togglePlayPause = function() {
if (media && (media.tagName === 'VIDEO' || media.tagName === 'AUDIO')) {
if (media.paused) {
media.play();
} else {
media.pause();
}
}
};
/**
* Toggle fullscreen mode
*/
@ -83,10 +97,11 @@
if (focusInterval) {
clearInterval(focusInterval);
}
// Focus window every 500ms to keep it on top
// Focus window every 250ms to aggressively keep it on top
window.focus(); // Focus immediately
focusInterval = setInterval(() => {
window.focus();
}, 500);
}, 250);
}
/**
@ -142,6 +157,19 @@
}
}
/**
* Update play/pause button appearance
*/
function updatePlayPauseButton() {
if (playPauseBtn && media && (media.tagName === 'VIDEO' || media.tagName === 'AUDIO')) {
if (media.paused) {
playPauseBtn.textContent = '▶';
} else {
playPauseBtn.textContent = '⏸';
}
}
}
/**
* Resize window to match media aspect ratio
*/
@ -222,6 +250,11 @@
case 'Escape':
window.close();
break;
case ' ':
case 'Spacebar':
e.preventDefault();
togglePlayPause();
break;
case 'ArrowLeft':
e.preventDefault();
if (window.playerData && window.playerData.prevProductId) {
@ -301,8 +334,13 @@
// Resize window when media loads (for video and images)
if (media) {
if (media.tagName === 'VIDEO') {
if (media.tagName === 'VIDEO' || media.tagName === 'AUDIO') {
media.addEventListener('loadedmetadata', resizeWindowToMedia);
// Update play/pause button when media state changes
media.addEventListener('play', updatePlayPauseButton);
media.addEventListener('pause', updatePlayPauseButton);
// Initial update
updatePlayPauseButton();
} else if (media.tagName === 'IMG') {
media.addEventListener('load', resizeWindowToMedia);
}

View file

@ -40,14 +40,11 @@
display: block;
}
/* Player controls overlay */
/* Player controls overlay - centered grid */
.player-controls {
grid-area: media;
display: grid;
grid-template-columns: auto 1fr auto;
align-items: end;
padding: 1rem;
background: linear-gradient(transparent, rgba(0,0,0,0.7));
place-items: center;
z-index: 10;
pointer-events: none;
opacity: 0;
@ -58,81 +55,52 @@
opacity: 1;
}
.player-controls button {
/* Controls grid - 3 columns, multiple rows */
.controls-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 0.75rem;
background: rgba(0,0,0,0.8);
padding: 1.5rem;
border-radius: 8px;
pointer-events: auto;
cursor: pointer;
}
/* Navigation buttons */
.nav-btn {
.controls-grid button {
background: rgba(255,255,255,0.2);
border: none;
color: white;
font-size: 2rem;
padding: 1rem;
padding: 0.75rem 1rem;
border-radius: 4px;
transition: background 0.2s;
cursor: pointer;
font-size: 1rem;
white-space: nowrap;
min-width: 100px;
}
.nav-btn:hover {
.controls-grid button:hover:not(:disabled) {
background: rgba(255,255,255,0.4);
}
.nav-btn:disabled {
.controls-grid button.active {
background: rgba(255,255,255,0.6);
}
.controls-grid button:disabled {
opacity: 0.3;
cursor: not-allowed;
}
/* Center controls */
.center-controls {
display: grid;
grid-template-columns: auto auto auto;
gap: 0.5rem;
justify-content: center;
/* Larger buttons for prev/next/play */
.controls-grid button.nav-btn {
font-size: 1.5rem;
padding: 1rem;
}
.center-controls button {
background: rgba(255,255,255,0.2);
border: none;
color: white;
padding: 0.5rem 0.75rem;
border-radius: 4px;
transition: background 0.2s;
white-space: nowrap;
font-size: 0.9rem;
}
.center-controls button:hover {
background: rgba(255,255,255,0.4);
}
.center-controls button.active {
background: rgba(255,255,255,0.6);
}
/* Responsive: stack controls vertically on very small windows */
@media (max-width: 700px) {
.player-controls {
grid-template-columns: 1fr;
grid-template-rows: auto auto auto;
gap: 0.5rem;
padding: 0.5rem;
}
.nav-btn {
font-size: 1.5rem;
padding: 0.5rem;
}
.center-controls {
grid-template-columns: 1fr;
gap: 0.25rem;
}
.center-controls button {
font-size: 0.85rem;
padding: 0.4rem;
}
.controls-grid button.play-btn {
font-size: 1.5rem;
padding: 1rem;
}
/* Product title overlay */
@ -183,23 +151,27 @@
<div class="product-title">{{ product.title }}</div>
<div class="player-controls">
{% if prev_product_id %}
<button class="nav-btn" id="prevBtn" onclick="navigate('{{ prev_product_id }}')" title="Previous (Left Arrow)">◀</button>
{% else %}
<button class="nav-btn" disabled>◀</button>
{% endif %}
<div class="controls-grid">
<!-- Row 1: Navigation -->
{% if prev_product_id %}
<button class="nav-btn" id="prevBtn" onclick="navigate('{{ prev_product_id }}')" title="Previous (Left Arrow)">◀</button>
{% else %}
<button class="nav-btn" disabled>◀</button>
{% endif %}
<div class="center-controls">
<button id="fullscreenBtn" onclick="toggleFullscreen()" title="Fullscreen (F)">⛶ Full</button>
<button class="play-btn" id="playPauseBtn" onclick="togglePlayPause()" title="Play/Pause (Space)">⏸</button>
{% if next_product_id %}
<button class="nav-btn" id="nextBtn" onclick="navigate('{{ next_product_id }}')" title="Next (Right Arrow)">▶</button>
{% else %}
<button class="nav-btn" disabled>▶</button>
{% endif %}
<!-- Row 2: Features -->
<button id="alwaysOnTopBtn" onclick="toggleAlwaysOnTop()" title="Always on Top (T)">📌 On Top</button>
<button id="fullscreenBtn" onclick="toggleFullscreen()" title="Fullscreen (F)">⛶ Full</button>
<button id="autoResizeBtn" onclick="toggleAutoResize()" title="Auto-Resize Window (R)">↔ Resize</button>
</div>
{% if next_product_id %}
<button class="nav-btn" id="nextBtn" onclick="navigate('{{ next_product_id }}')" title="Next (Right Arrow)">▶</button>
{% else %}
<button class="nav-btn" disabled>▶</button>
{% endif %}
</div>
</div>