From 33f6186aa16eb211aaf0158a1a769ec3a538b908 Mon Sep 17 00:00:00 2001 From: Matt Mascarenhas Date: Wed, 10 Feb 2021 22:41:46 +0000 Subject: [PATCH] cinera.web: Fix player sizing and auto-scrolling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Video size may be based on the height if the width-based is too tall • Auto-scrolling improvements: • It now cannot oscillate • It doesn't happen at all if scrolled to the very top / bottom Thanks to @Freak_ on freenode for the report --- cinera/cinera.c | 2 +- cinera/cinera_player_post.js | 8 +-- cinera/cinera_player_pre.js | 12 +++- cinera/cinera_pre.js | 103 ++++++++++++++++++++++------------- cinera/cinera_search_pre.js | 14 +---- 5 files changed, 82 insertions(+), 57 deletions(-) diff --git a/cinera/cinera.c b/cinera/cinera.c index fc6d1c1..5beb58f 100644 --- a/cinera/cinera.c +++ b/cinera/cinera.c @@ -23,7 +23,7 @@ typedef struct version CINERA_APP_VERSION = { .Major = 0, .Minor = 8, - .Patch = 5 + .Patch = 6 }; #include // NOTE(matt): varargs diff --git a/cinera/cinera_player_post.js b/cinera/cinera_player_post.js index 5c478eb..e6511b5 100644 --- a/cinera/cinera_player_post.js +++ b/cinera/cinera_player_post.js @@ -50,7 +50,7 @@ var CineraProps = { FlexDirection: null, JustifyContent: null, O: null, - D: IsMobile() ? devices.MOBILE : devices.DESKTOP, + IsMobile: IsMobile(), ScrollX: null, ScrollY: null, }; @@ -173,7 +173,7 @@ if(titleBar) } viewsMenu = titleBar.querySelector(".views"); - if(viewsMenu && CineraProps.D !== devices.MOBILE) + if(viewsMenu && !CineraProps.IsMobile) { menuState.push(viewsMenu); var viewsContainer = viewsMenu.querySelector(".views_container"); @@ -280,7 +280,7 @@ var MobileCineraContentRule = GetOrSetRule(MobileCineraContentRuleSelector); var MenuContainerRuleSelector = ".cineraMenus > .menu .quotes_container, .cineraMenus > .menu .references_container, .cineraMenus > .menu .filter_container, .cineraMenus > .menu .views_container, .cineraMenus > .menu .link_container, .cineraMenus > .menu .credits_container"; var MenuContainerRule = GetOrSetRule(MenuContainerRuleSelector); -if(CineraProps.D == devices.MOBILE) +if(CineraProps.IsMobile) { InitMobileStyle(); } @@ -292,7 +292,7 @@ else var player = new Player(playerContainer, onRefChanged); -if(CineraProps.D == devices.MOBILE) +if(CineraProps.IsMobile) { ConnectMobileControls(player); } diff --git a/cinera/cinera_player_pre.js b/cinera/cinera_player_pre.js index e255dea..466881e 100644 --- a/cinera/cinera_player_pre.js +++ b/cinera/cinera_player_pre.js @@ -483,13 +483,21 @@ Player.prototype.updateSize = function() { var width = 0; var height = 0; CineraProps.O = GetRealOrientation(orientations.LANDSCAPE_LEFT, CineraProps.IsMobile); - if(CineraProps.D === devices.DESKTOP) + if(!CineraProps.IsMobile) { + var VisibleArea = GetWindowDim(false); + var AvailableHeight = VisibleArea.Y - titleBar.offsetHeight; width = this.videoContainer.offsetWidth; height = width / 16 * 9; // TODO(matt): Get the aspect ratio from the video itself? + if(height > AvailableHeight) + { + height = AvailableHeight; + width = height / 9 * 16; + } this.markersContainer.style.height = height + "px"; - var MenuMaxHeight = cinera.offsetHeight - titleBar.offsetHeight - 4; + var VacantPixelsBelowMenus = 4; + var MenuMaxHeight = cinera.offsetHeight - titleBar.offsetHeight - VacantPixelsBelowMenus; MenuContainerRule.style.maxHeight = MenuMaxHeight + "px"; } else diff --git a/cinera/cinera_pre.js b/cinera/cinera_pre.js index b73354f..4f4796b 100644 --- a/cinera/cinera_pre.js +++ b/cinera/cinera_pre.js @@ -44,22 +44,30 @@ DeriveReliableWindowDimensions() } function -GetRealOrientation(PreferredLandscape, IsMobile) +GetWindowDim(IsMobile) { - var Result = window.orientation; - var WindowDim = { + var Result = { X: null, Y: null, }; + if(IsMobile) { - WindowDim = DeriveReliableWindowDimensions(); + Result = DeriveReliableWindowDimensions(); } else { - WindowDim.X = document.body.clientWidth; - WindowDim.Y = window.innerHeight; + Result.X = document.body.clientWidth; + Result.Y = window.innerHeight; } + return Result; +} + +function +GetRealOrientation(PreferredLandscape, IsMobile) +{ + var Result = window.orientation; + var WindowDim = GetWindowDim(IsMobile); if(WindowDim.Y > WindowDim.X) { Result = orientations.PORTRAIT; @@ -262,52 +270,73 @@ GetOrSetRule(SelectorText) return Result; } +function IsInRangeEx(Min, N, Max) +{ + return N > Min && N < Max; +} + /* Auto-scrolling */ var LastScrollYPos = 0; var ScrollTicking = false; var ScrollerFunction; var ScrollCondition; -function ScrollTo(Element, ScrollPos, StickyObscuringElement) { - var BoundingRect = Element.getBoundingClientRect(); - var Height = BoundingRect.height; - var PercentageOfInView = 89; - var GatherableHeight = Height * (1 - PercentageOfInView / 100); - var ScrollY = BoundingRect.top; - var YOffsetFromPage = getElementYOffsetFromPage(Element); - - var DesiredScroll = null; - var Ceiling = StickyObscuringElement ? StickyObscuringElement.offsetHeight : 0; - - if(ScrollY < Ceiling) +function ScrollTo(Element, ScrollPos, IsMobile, StickyObscuringElement) { + var ScrolledToTop = ScrollPos == 0; + var ScrolledToBottom = (window.innerHeight + Math.ceil(window.pageYOffset)) >= document.body.scrollHeight; + if(!ScrolledToTop || !ScrolledToBottom) { - if(ScrollY < 0) { ScrollY = -ScrollY; } - GatherableHeight -= Ceiling; - if(ScrollY <= GatherableHeight) + var Ceiling = StickyObscuringElement ? StickyObscuringElement.offsetHeight : 0; + var VisibleArea = GetWindowDim(IsMobile); + VisibleArea.Y -= Ceiling; + + var PercentageOfVisibleHeightToGather = 5; + var GatherableHeight = VisibleArea.Y * PercentageOfVisibleHeightToGather / 100; + + var BoundingRect = Element.getBoundingClientRect(); + + var ElementTop = BoundingRect.top - Ceiling; + var ElementBottom = ElementTop + BoundingRect.height; + + var UpperProtrusion = -ElementTop; + var LowerProtrusion = ElementBottom - VisibleArea.Y; + + var DesiredScroll = null; + var YOffsetFromPage = getElementYOffsetFromPage(Element); + if(IsInRangeEx(0, UpperProtrusion, GatherableHeight)) { - DesiredScroll = YOffsetFromPage - Ceiling; + if(!ScrolledToBottom) + { + DesiredScroll = YOffsetFromPage - Ceiling; + } } - } - else - { - var LowerProtrusion = ScrollY - (window.innerHeight - Height); - if(LowerProtrusion > 0 && LowerProtrusion <= GatherableHeight) + else if(IsInRangeEx(0, LowerProtrusion, GatherableHeight)) { - DesiredScroll = ScrollPos + LowerProtrusion; + if(!ScrolledToTop) + { + if(IsInRangeEx(0, UpperProtrusion + LowerProtrusion, GatherableHeight)) + { + DesiredScroll = YOffsetFromPage - Ceiling; + } + else + { + DesiredScroll = ScrollPos + LowerProtrusion; + } + } } - } - if(DesiredScroll !== null) - { - window.scrollTo({ - top: DesiredScroll, - behavior: "smooth" - }); + if(DesiredScroll !== null && DesiredScroll != ScrollPos) + { + window.scrollTo({ + top: DesiredScroll, + behavior: "smooth" + }); + } } } function -InitScrollEventListener(Element, StickyObscuringElement) +InitScrollEventListener(Element, IsMobile, StickyObscuringElement) { window.addEventListener('scroll', function() { if(ScrollCondition == undefined || ScrollCondition == true) @@ -317,7 +346,7 @@ InitScrollEventListener(Element, StickyObscuringElement) if (!ScrollTicking) { window.requestAnimationFrame(function() { clearTimeout(ScrollerFunction); - ScrollerFunction = setTimeout(ScrollTo, 2000, Element, LastScrollYPos, StickyObscuringElement); + ScrollerFunction = setTimeout(ScrollTo, 2000, Element, LastScrollYPos, IsMobile, StickyObscuringElement); ScrollTicking = false; }); diff --git a/cinera/cinera_search_pre.js b/cinera/cinera_search_pre.js index a13f505..4f9ec40 100644 --- a/cinera/cinera_search_pre.js +++ b/cinera/cinera_search_pre.js @@ -2938,19 +2938,7 @@ ComputeOptimalGridSize() Y: null, }; - var WindowDim = { - X: null, - Y: null, - }; - if(CineraProps.IsMobile) - { - WindowDim = DeriveReliableWindowDimensions(); - } - else - { - WindowDim.X = document.body.clientWidth; - WindowDim.Y = window.innerHeight; - } + var WindowDim = GetWindowDim(CineraProps.IsMobile); var DimReduction = { X: 0, Y: Nav.Controls.Header.offsetHeight,