From c7518e58788c17ad2ca8340ab5c7633489aa9518 Mon Sep 17 00:00:00 2001 From: RblSb Date: Sat, 25 Jan 2025 15:32:55 +0300 Subject: Add experimental unpauseWithoutLeader option Also extended requestLeaderOnPause, so you can unpause when someone else is a leader by video click with this one. Only works for raw videos and doesn't work in FF, so there is new unsafe option that can break everything with enough clients. There is also leader button hints when you touch player as non-leader for easier ux. --- src/client/Player.hx | 60 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 8 deletions(-) (limited to 'src/client/Player.hx') diff --git a/src/client/Player.hx b/src/client/Player.hx index 911092e..92f34e9 100644 --- a/src/client/Player.hx +++ b/src/client/Player.hx @@ -12,6 +12,7 @@ import client.players.Vk; import client.players.Youtube; import haxe.Http; import haxe.Json; +import haxe.Timer; import js.html.Audio; import js.html.Element; import js.html.InputElement; @@ -37,6 +38,9 @@ class Player { var needsVolumeReset = false; final voiceOverVolume = 0.3; + /** If player was clicked and pause/play event was not generated by browser events. **/ + public var inUserInteraction = false; + public function new(main:Main):Void { this.main = main; youtube = new Youtube(main, this); @@ -57,12 +61,18 @@ class Player { if (resizeObserver != null) { resizeObserver.observe(playerEl); } else { - final timer = new haxe.Timer(50); + final timer = new Timer(50); timer.run = () -> { if (isLoaded) return; Buttons.onViewportResize(); } } + + playerEl.addEventListener("click", e -> { + inUserInteraction = true; + // for some reason Chrome has ~300ms event delay + Timer.delay(() -> inUserInteraction = false, 350); + }, {}); } function initItemButtons():Void { @@ -249,7 +259,7 @@ class Player { el.setAttribute("name", state); final el2 = ge("#pause-indicator-portrait"); - el2.setAttribute("name", "pause"); + el2.setAttribute("name", state); var isVisible = isPause || main.hasLeader(); el2.style.display = isVisible ? "" : "none"; } @@ -262,10 +272,23 @@ class Player { public function onPlay():Void { audioTrack?.play(); + if (!isLoaded) return; + if (videoList.length == 0) return; + final hasAutoPause = main.hasLeaderOnPauseRequest(); if (!main.isLeader()) { - // paused and no leader - instant pause - if (main.lastState.paused) pause(); + // user click, so we can unpause by removing leader + // (doesn't work in Firefox because of no video click propagation) + final allowUnpause = (hasAutoPause && inUserInteraction); + if (allowUnpause || main.hasUnpauseWithoutLeader()) { + main.removeLeader(); + } else { + // paused and no leader - instant pause + if (main.lastState.paused) { + pause(); + main.blinkLeaderButton(); + } + } return; } main.send({ @@ -274,7 +297,6 @@ class Player { time: getTime() } }); - final hasAutoPause = main.hasLeaderOnPauseRequest() && videoList.length > 0; if (hasAutoPause) { // do not remove leader if user cannot request it back if (main.hasPermission(RequestLeaderPerm)) main.toggleLeader(); @@ -284,6 +306,7 @@ class Player { public function onPause():Void { audioTrack?.pause(); + if (!isLoaded) return; final item = videoList.currentItem ?? return; // do not send pause if video is ended if (getTime() >= item.duration - 0.01) return; @@ -311,7 +334,10 @@ class Player { } if (!main.isLeader()) { // no pause and no permission - instant play - if (!main.lastState.paused) play(); + if (!main.lastState.paused) { + play(); + main.blinkLeaderButton(); + } return; } // we are leader, so just send pause @@ -332,7 +358,21 @@ class Player { skipSetTime = false; return; } - if (!main.isLeader()) return; + if (videoList.length == 0) return; + if (!main.isLeader()) { + if (main.hasLeader() || main.lastState.pausedByServer) { + final off = isPaused() ? 0 : main.timeFromLastState; + final time = main.lastState.time; + final delta = Math.abs(time - getTime()); + setTime(time); + main.blinkLeaderButton(); + } else { + // we dont want to seek back here because + // after seek can happen pause that will give auto-leader, + // so seeking will work + } + return; + } main.send({ type: SetTime, setTime: { @@ -349,7 +389,11 @@ class Player { skipSetRate = false; return; } - if (!main.isLeader()) return; + if (videoList.length == 0) return; + if (!main.isLeader()) { + main.blinkLeaderButton(); + return; + } main.send({ type: SetRate, setRate: { -- cgit v1.2.3