import { Capacitor } from '@capacitor/core'; import { ScreenBrightness } from '@capacitor-community/screen-brightness'; import { VolumeControl } from 'capacitor-volume-control'; export function swipeControls(node, props = { enabled: true, immersePlayer: () => {} }) { if (!props.enabled) return; const isNative = Capacitor.isNativePlatform(); let brightness = 50; let volume = 50; // Start at middle volume (range 0-100) let startX = 0; let startY = 0; let isDragging = false; let activeControl = null; let timeoutId; let updateTimeoutId; const indicators = document.createElement('div'); indicators.className = 'swipe-control-indicators'; indicators.style.cssText = ` position: absolute; bottom: 60px; left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 20px; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; background-color: rgba(0, 0, 0, 0.6); color: white; padding: 8px 12px; border-radius: 4px; font-family: Arial, sans-serif; font-size: 14px; `; indicators.innerHTML = `
100%
50%
`; node.style.position = 'relative'; node.appendChild(indicators); const brightnessValue = indicators.querySelector('.brightness-value'); const volumeValue = indicators.querySelector('.volume-value'); function handleTouchStart(event) { if (!props.enabled) return; if (!isNative) return; isDragging = true; startX = event.touches[0].clientX; startY = event.touches[0].clientY; const rect = node.getBoundingClientRect(); activeControl = (event.touches[0].clientX - rect.left) < rect.width / 2 ? 'brightness' : 'volume'; } function handleTouchMove(event) { if (!props.enabled) return; if (!isNative || !isDragging) return; const currentY = event.touches[0].clientY; const deltaY = startY - currentY; const rect = node.getBoundingClientRect(); const sensitivity = 0.5 * (200 / rect.height); if (activeControl === 'brightness') { brightness = Math.max(0, Math.min(100, brightness + deltaY * sensitivity)); updateBrightness(); } else if (activeControl === 'volume') { volume = Math.max(0, Math.min(100, volume + deltaY * sensitivity)); debouncedUpdateVolume(); } showControlsIndicator(); startY = currentY; } function handleTouchEnd() { if (!props.enabled) return; isDragging = false; activeControl = null; } async function updateBrightness() { try { await ScreenBrightness.setBrightness({ brightness: brightness / 100 }); brightnessValue.textContent = `${Math.round(brightness)}%`; } catch (error) { console.error('Error updating brightness:', error); } } let lastVolume = 50; const VOLUME_CHANGE_THRESHOLD = 1; function debouncedUpdateVolume() { clearTimeout(updateTimeoutId); // Update UI immediately volumeValue.textContent = `${Math.round(volume)}%`; updateTimeoutId = setTimeout(async () => { if (Math.abs(volume - lastVolume) >= VOLUME_CHANGE_THRESHOLD) { try { await VolumeControl.setVolume({ volume: Math.round(volume), showUI: false }); lastVolume = volume; } catch (error) { console.error('Error updating volume:', error); // Retry logic setTimeout(() => debouncedUpdateVolume(), 50); } } }, 33); } function showControlsIndicator() { indicators.style.opacity = '1'; clearTimeout(timeoutId); timeoutId = setTimeout(() => { indicators.style.opacity = '0'; props.immersePlayer(); }, 500); } node.addEventListener('touchstart', handleTouchStart); node.addEventListener('touchmove', handleTouchMove, { passive: false }); node.addEventListener('touchend', handleTouchEnd); async function init() { if (isNative) { try { // const { brightness: currentBrightness } = await ScreenBrightness.getBrightness(); const { volume: currentVolume } = await VolumeControl.getVolume(); brightness = 50; volume = currentVolume; // updateBrightness(); brightnessValue.textContent = `50%`; debouncedUpdateVolume(); } catch (error) { console.error('Error initializing brightness and volume:', error); } } } init(); return { destroy() { node.removeEventListener('touchstart', handleTouchStart); node.removeEventListener('touchmove', handleTouchMove); node.removeEventListener('touchend', handleTouchEnd); clearTimeout(timeoutId); node.removeChild(indicators); } }; }