Files
wehub-resource-sync 91e75e620b
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Has been cancelled
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Has been cancelled
CD: Docs MCP Server / build (linux/amd64) (push) Has been cancelled
CD: Docs MCP Server / build (linux/arm64) (push) Has been cancelled
CD: Docs MCP Server / merge (push) Has been cancelled
CI: cua-driver distro-compat matrix / Resolve release version (push) Has been cancelled
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Has been cancelled
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Has been cancelled
CI: cua-driver distro-compat matrix / Distro compat summary (push) Has been cancelled
CI: Rust Linux unit / Rust Linux unit and compile (push) Has been cancelled
CI: Rust Windows unit / Rust Windows unit and compile (push) Has been cancelled
CI: Nix Linux Rust source / Nix / compositor build (push) Has been cancelled
CI: Nix Linux Rust source / Nix / driver package (push) Has been cancelled
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:03:19 +08:00

318 lines
9.6 KiB
HTML

<main
class="flex flex-col h-full w-full p-6 overflow-auto"
role="main"
aria-label="Video player interface"
>
<div class="max-w-2xl mx-auto w-full">
<h1 class="text-xl font-semibold text-gray-900 mb-4">Video Player</h1>
<!-- Video Player -->
<div class="bg-black rounded-lg overflow-hidden shadow-lg">
<!-- Mock Video Display -->
<div
class="relative bg-gradient-to-br from-gray-800 to-gray-900 aspect-video flex items-center justify-center"
>
<div id="video-display" class="text-center">
<iconify-icon
id="play-icon"
icon="mdi:play"
class="text-white hidden"
style="font-size: 4rem"
></iconify-icon>
<iconify-icon
id="pause-icon"
icon="mdi:pause"
class="text-white"
style="font-size: 4rem"
></iconify-icon>
</div>
<div
class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-3"
>
<div class="text-white text-sm">Sample Video</div>
</div>
</div>
<!-- Controls -->
<div class="bg-gray-900 p-3">
<!-- Progress/Seek Bar -->
<div class="mb-3">
<input
type="range"
id="seek-bar"
min="0"
max="225"
value="0"
class="w-full h-1 bg-gray-700 rounded-lg appearance-none cursor-pointer seek-slider"
aria-label="Video progress"
aria-valuemin="0"
aria-valuemax="225"
aria-valuenow="0"
/>
</div>
<!-- Control Buttons -->
<div class="flex items-center gap-3">
<!-- Play/Pause Button -->
<button
id="play-pause-btn"
class="p-2 hover:bg-gray-800 rounded transition-colors"
aria-label="Play or pause video"
>
<iconify-icon
id="play-pause-icon"
icon="mdi:pause"
class="text-white"
style="font-size: 1.5rem"
></iconify-icon>
</button>
<!-- Volume Controls -->
<div class="relative volume-control-container">
<button
id="volume-btn"
class="p-2 hover:bg-gray-800 rounded transition-colors"
aria-label="Volume control"
>
<iconify-icon
id="volume-icon"
icon="mdi:volume-high"
class="text-white"
style="font-size: 1.25rem"
></iconify-icon>
</button>
<!-- Collapsible Volume Slider (hidden by default) -->
<div
id="volume-slider-container"
class="hidden absolute bottom-full left-0 mb-2 bg-gray-800 rounded-lg p-3 shadow-lg"
>
<div class="flex flex-col items-center gap-2" style="height: 100px">
<input
type="range"
id="volume-slider"
min="0"
max="100"
value="50"
orient="vertical"
class="h-full volume-slider-vertical"
aria-label="Volume level"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="50"
/>
<span id="volume-display" class="text-white text-xs">50%</span>
</div>
</div>
</div>
<!-- Time Display -->
<div class="text-white text-sm ml-auto">
<span id="current-time">0:00</span> / <span id="duration">3:45</span>
</div>
</div>
</div>
</div>
<div class="mt-4 p-3 bg-blue-50 border border-blue-200 rounded">
<p class="text-sm text-blue-800">
<iconify-icon icon="mdi:information" class="text-blue-600"></iconify-icon>
Use the video player controls
</p>
</div>
</div>
<style>
/* Seek bar slider styling */
.seek-slider::-webkit-slider-thumb {
appearance: none;
width: 14px;
height: 14px;
background: white;
cursor: pointer;
border-radius: 50%;
}
.seek-slider::-moz-range-thumb {
width: 14px;
height: 14px;
background: white;
cursor: pointer;
border-radius: 50%;
border: none;
}
/* Vertical volume slider styling */
.volume-slider-vertical {
writing-mode: bt-lr;
-webkit-appearance: slider-vertical;
width: 8px;
background: #4b5563;
border-radius: 4px;
}
.volume-slider-vertical::-webkit-slider-thumb {
appearance: none;
width: 16px;
height: 16px;
background: white;
cursor: pointer;
border-radius: 50%;
}
.volume-slider-vertical::-moz-range-thumb {
width: 16px;
height: 16px;
background: white;
cursor: pointer;
border-radius: 50%;
border: none;
}
</style>
<script>
// Initialize player state
const initialState = '{{INITIAL_STATE}}';
let isPlaying = initialState === 'playing';
let volume = 50;
let isMuted = false;
let currentTime = 0;
const totalDuration = 225; // 3:45 in seconds
// Store state globally for evaluation
window.__playerState = {
is_playing: isPlaying,
volume: volume,
is_muted: isMuted,
current_time: currentTime,
};
// Update UI based on state
function updateUI() {
const playPauseIcon = document.getElementById('play-pause-icon');
const playIcon = document.getElementById('play-icon');
const pauseIcon = document.getElementById('pause-icon');
const volumeIcon = document.getElementById('volume-icon');
const volumeDisplay = document.getElementById('volume-display');
const volumeSlider = document.getElementById('volume-slider');
const seekBar = document.getElementById('seek-bar');
// Update play/pause
if (isPlaying) {
playPauseIcon.setAttribute('icon', 'mdi:pause');
playIcon.classList.add('hidden');
pauseIcon.classList.remove('hidden');
} else {
playPauseIcon.setAttribute('icon', 'mdi:play');
playIcon.classList.remove('hidden');
pauseIcon.classList.add('hidden');
}
// Update volume
if (isMuted) {
volumeIcon.setAttribute('icon', 'mdi:volume-off');
volumeDisplay.textContent = '0%';
} else {
if (volume === 0) {
volumeIcon.setAttribute('icon', 'mdi:volume-off');
} else if (volume < 50) {
volumeIcon.setAttribute('icon', 'mdi:volume-low');
} else {
volumeIcon.setAttribute('icon', 'mdi:volume-high');
}
volumeDisplay.textContent = volume + '%';
}
volumeSlider.value = volume;
volumeSlider.setAttribute('aria-valuenow', volume);
// Update seek bar
seekBar.value = currentTime;
seekBar.setAttribute('aria-valuenow', currentTime);
// Update global state
window.__playerState = {
is_playing: isPlaying,
volume: volume,
is_muted: isMuted,
current_time: currentTime,
};
}
// Play/Pause button
document.getElementById('play-pause-btn').addEventListener('click', function () {
isPlaying = !isPlaying;
updateUI();
});
// Volume button and slider controls
const volumeBtn = document.getElementById('volume-btn');
const volumeSliderContainer = document.getElementById('volume-slider-container');
const volumeControlContainer = document.querySelector('.volume-control-container');
let volumeSliderVisible = false;
// Click volume button to toggle mute
volumeBtn.addEventListener('click', function (e) {
e.stopPropagation();
isMuted = !isMuted;
updateUI();
});
// Show volume slider on hover
volumeControlContainer.addEventListener('mouseenter', function () {
volumeSliderContainer.classList.remove('hidden');
volumeSliderVisible = true;
});
// Keep slider visible when interacting with it
volumeSliderContainer.addEventListener('mouseenter', function () {
volumeSliderVisible = true;
});
// Hide when mouse leaves the entire volume control area
volumeControlContainer.addEventListener('mouseleave', function (e) {
// Only hide if we're not over the slider container
if (!volumeSliderContainer.contains(e.relatedTarget)) {
volumeSliderContainer.classList.add('hidden');
volumeSliderVisible = false;
}
});
// Volume slider
const volumeSlider = document.getElementById('volume-slider');
volumeSlider.addEventListener('input', function () {
volume = parseInt(this.value);
if (isMuted && volume > 0) {
isMuted = false;
}
updateUI();
});
// Seek bar
const seekBar = document.getElementById('seek-bar');
seekBar.addEventListener('input', function () {
currentTime = parseInt(this.value);
const minutes = Math.floor(currentTime / 60);
const seconds = currentTime % 60;
document.getElementById('current-time').textContent =
minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
updateUI();
});
// Simulate video time progression when playing
setInterval(() => {
if (isPlaying && currentTime < totalDuration) {
currentTime += 1;
const minutes = Math.floor(currentTime / 60);
const seconds = currentTime % 60;
document.getElementById('current-time').textContent =
minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
updateUI();
}
}, 1000);
// Initialize UI
updateUI();
</script>
</main>