cinera.web: Fix issues (on mobile) with new layout

Both pages:
    Derive reliable window dimensions ourselves
    Set the orientation from the window dimensions
    Use "box-sizing: content-box" on the help keys, to fix sizing

Search page:
    Support irregular (i.e. non-square) grids
    General sizing fixes
    Fix text fitting when toggling back from List to Grid view
    Fix text fitting when textNode would overflow container
    Correctly compute optimal grid size after orientation change
    Rename .text to .cineraText to avoid CSS selector clash
    Only add click events for the main set of buttons (not its clone)

Player page:
    Size the video and timestamps bar more sensibly
This commit is contained in:
Matt Mascarenhas 2021-02-04 00:13:55 +00:00
parent 2cf8739a60
commit 545938d766
7 changed files with 1161 additions and 828 deletions

View File

@ -23,7 +23,7 @@ typedef struct
version CINERA_APP_VERSION = {
.Major = 0,
.Minor = 8,
.Patch = 1
.Patch = 2
};
#include <stdarg.h> // NOTE(matt): varargs
@ -13507,6 +13507,7 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
AppendStringToBuffer(B, Wrap0(" class=\"key_block\">"));
OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, 0);
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("1"), TRUE);
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("q"), TRUE);
@ -13535,6 +13536,7 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P
AppendHelpKeyToBuffer(B, &IndentationLevel, Wrap0("v"), TRUE);
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // key_block
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // help_paragraph

View File

@ -142,20 +142,6 @@ ul.cineraNavPlain li.current > a {
order: 2;
}
#cineraIndex .cineraTraversal .cineraButton
{
/* TODO(matt): Do the cineraTraversal as a flex box, to auto-size these buttons? */
height: 42px;
width: 42px;
padding: 2px;
margin: 2px;
display: inline-flex;
align-items: center;
justify-content: center;
}
#cineraIndex.anim .cineraTraversal,
#cineraIndex.anim .cineraTraversal * p
{
@ -179,6 +165,20 @@ ul.cineraNavPlain li.current > a {
transform: rotate(180deg);
}
#cineraIndex .cineraTraversal .cineraButton
{
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 2px;
margin: 2px;
height: 42px;
width: 42px;
}
#cineraIndex .cineraTraversal * p
{
transform: rotate(0deg);
@ -274,6 +274,7 @@ ul.cineraNavPlain li.current > a {
}
.cineraQueryContainer #query {
width: 0px;
flex-grow: 1;
}
@ -281,6 +282,7 @@ ul.cineraNavPlain li.current > a {
position: absolute;
top: 2px;
right: 5px;
font-size: small;
color: #000000;
height: 100%;
display: none;
@ -345,14 +347,23 @@ ul.cineraNavPlain li.current > a {
display: flex;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
overflow: hidden;
}
#cineraIndex #cineraIndexGrid .cineraButton.subdivision .head-item,
#cineraIndex #cineraIndexGrid .cineraButton.subdivision .tail-item
{
display: flex;
width: 100%;
height: 50%;
display: flex;
}
#cineraIndex #cineraIndexGrid .cineraButton.subdivision .head-item p,
#cineraIndex #cineraIndexGrid .cineraButton.subdivision .tail-item p
{
border: 0;
margin: 0;
padding: 0;
}
#cineraIndex #cineraIndexGrid .cineraButton.subdivision.leaf
@ -518,7 +529,7 @@ ul.cineraNavPlain li.current > a {
left: 50%;
transform: translate(-50%, -50%);
max-height: 97%;
overflow-y: scroll;
overflow-y: auto;
}
.cineraHelp .help_container.visible {
@ -526,14 +537,15 @@ ul.cineraNavPlain li.current > a {
}
.cineraHelp .help_container .help_key {
box-sizing: content-box;
font-family: Inconsolata;
font-size: 16px;
border: 1px solid;
display: inline-block;
background-color: #111111; /* Per project */
border-radius: 4px;
height: 16px;
width: 16px;
min-height: 1em;
min-width: 1em;
padding: 4px;
line-height: 16px;
margin: 2px;

View File

@ -21,6 +21,9 @@ var sourceMenus = null;
var helpButton = null;
var helpDocumentation = null;
// NOTE(matt): One set of markers per page. There is code to support multiple, which we may want to extend everywhere
var MarkersContainer = cinera.querySelector(".markers_container");
var views = {
REGULAR: 0,
THEATRE: 1,
@ -32,7 +35,7 @@ var devices = {
MOBILE: 1,
};
var cineraProps = {
var CineraProps = {
C: null,
V: views.REGULAR,
Z: null,
@ -46,11 +49,12 @@ var cineraProps = {
Display: null,
FlexDirection: null,
JustifyContent: null,
O: window.orientation,
O: null,
D: IsMobile() ? devices.MOBILE : devices.DESKTOP,
ScrollX: null,
ScrollY: null,
};
CineraProps.O = GetRealOrientation(CineraProps.IsMobile);
if(titleBar)
{
@ -169,7 +173,7 @@ if(titleBar)
}
viewsMenu = titleBar.querySelector(".views");
if(viewsMenu && cineraProps.D !== devices.MOBILE)
if(viewsMenu && CineraProps.D !== devices.MOBILE)
{
menuState.push(viewsMenu);
var viewsContainer = viewsMenu.querySelector(".views_container");
@ -276,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.D == devices.MOBILE)
{
InitMobileStyle();
}
@ -288,7 +292,7 @@ else
var player = new Player(playerContainer, onRefChanged);
if(cineraProps.D == devices.MOBILE)
if(CineraProps.D == devices.MOBILE)
{
ConnectMobileControls(player);
}
@ -302,7 +306,28 @@ if(viewsMenu && localStorage.getItem(cineraViewStorageItem))
InitScrollEventListener(cinera);
window.addEventListener("resize", function() { player.updateSize(); });
window.addEventListener("resize", function() {
if(CineraProps.IsMobile)
{
setTimeout(player.updateSize, 512);
}
else
{
player.updateSize();
}
});
window.onorientationchange = function() {
if(CineraProps.IsMobile)
{
setTimeout(player.updateSize, 512);
}
else
{
player.updateSize();
}
};
document.addEventListener("keydown", function(ev) {
var key = ev.key;
if(ev.getModifierState("Shift") && key == " ")
@ -350,9 +375,3 @@ else if(lastAnnotation = localStorage.getItem(lastAnnotationStorageItem))
{
player.setTime(lastAnnotation);
}
window.onorientationchange = function()
{
cineraProps.O = window.orientation;
player.updateSize();
};

View File

@ -207,7 +207,7 @@ function sizeAndPositionMenuContainer(TitleBar, SizerElement, Menu)
var ContainerDimX = SizerElementDimX;
var ContainerDimY = SizerElementDimY;
switch(cineraProps.O)
switch(CineraProps.O)
{
case orientations.PORTRAIT:
{
@ -286,14 +286,18 @@ ComputeTallest(Elements, UnhidingClass)
function
ComputeAndSetTallest(Selector, Elements, UnhidingClass)
{
var Result;
Selector.style.height = "unset";
Selector.style.height = ComputeTallest(Elements, UnhidingClass) + "px";
Result = ComputeTallest(Elements, UnhidingClass);
Selector.style.height = Result + "px";
return Result;
}
function ApplyMobileStyle(player)
{
var MaxWidth = MaxWidthOfElement(cinera);
var MaxHeight = MaxHeightOfElement(cinera);
var WindowDim = DeriveReliableWindowDimensions();
var MaxWidth = cinera.offsetWidth;
var MaxHeight = MaxHeightOfElement(cinera, WindowDim);
var IndicesBar = playerContainer.querySelector(".markers_container");
var Markers = IndicesBar.querySelector(".markers");
@ -305,7 +309,7 @@ function ApplyMobileStyle(player)
CineraContentWidth -= EpisodeMarkers[i].offsetWidth;
}
switch(cineraProps.O)
switch(CineraProps.O)
{
case orientations.PORTRAIT:
{
@ -326,28 +330,29 @@ function ApplyMobileStyle(player)
} break;
}
var HeightOfTallestIndex;
if(MobileCineraContentRule !== undefined)
{
MobileCineraContentRule.style.width = CineraContentWidth + "px";
var MarkerList = Markers.querySelectorAll(".marker");
ComputeAndSetTallest(MobileCineraContentRule, MarkerList, "current");
HeightOfTallestIndex = ComputeAndSetTallest(MobileCineraContentRule, MarkerList, "current");
IndicesBar.style.height = HeightOfTallestIndex + "px";
Markers.style.width = CineraContentWidth + "px";
}
var VideoMaxDimX = null;
var VideoMaxDimY = null;
var VideoMaxDimX = CineraContentWidth;
var VideoMaxDimY = MaxHeight - HeightOfTallestIndex;
switch(cineraProps.O)
switch(CineraProps.O)
{
case orientations.PORTRAIT:
{
VideoMaxDimX = MaxWidth;
VideoMaxDimY = MaxHeight - IndicesBar.offsetHeight - titleBar.offsetHeight;
VideoMaxDimY -= titleBar.offsetHeight;
} break;
case orientations.LANDSCAPE_LEFT:
case orientations.LANDSCAPE_RIGHT:
{
VideoMaxDimX = MaxWidth - titleBar.offsetWidth;
VideoMaxDimY = MaxHeight - IndicesBar.offsetHeight;
VideoMaxDimX -= titleBar.offsetWidth;
} break;
}
@ -477,7 +482,8 @@ ConnectMobileControls(player)
Player.prototype.updateSize = function() {
var width = 0;
var height = 0;
if(cineraProps.D === devices.DESKTOP)
CineraProps.O = GetRealOrientation(orientations.LANDSCAPE_LEFT, CineraProps.IsMobile);
if(CineraProps.D === devices.DESKTOP)
{
width = this.videoContainer.offsetWidth;
height = width / 16 * 9; // TODO(matt): Get the aspect ratio from the video itself?
@ -862,7 +868,7 @@ function toggleMenuVisibility(element) {
function handleMouseOverViewsMenu()
{
switch(cineraProps.V)
switch(CineraProps.V)
{
case views.REGULAR:
case views.THEATRE:
@ -904,24 +910,24 @@ function leaveFullScreen_()
}
function toggleTheatreMode() {
switch(cineraProps.V)
switch(CineraProps.V)
{
case views.REGULAR:
{
cineraProps.C = cinera.style.backgroundColor;
cineraProps.Z = cinera.style.zIndex;
cineraProps.X = cinera.style.left;
cineraProps.Y = cinera.style.top;
cineraProps.W = cinera.style.width;
cineraProps.mW = cinera.style.maxWidth;
cineraProps.H = cinera.style.height;
cineraProps.mH = cinera.style.maxHeight;
cineraProps.P = cinera.style.position;
cineraProps.Display = cinera.style.display;
cineraProps.FlexDirection = cinera.style.flexDirection;
cineraProps.JustifyContent = cinera.style.justifyContent;
cineraProps.ScrollX = window.scrollX;
cineraProps.ScrollY = window.scrollY;
CineraProps.C = cinera.style.backgroundColor;
CineraProps.Z = cinera.style.zIndex;
CineraProps.X = cinera.style.left;
CineraProps.Y = cinera.style.top;
CineraProps.W = cinera.style.width;
CineraProps.mW = cinera.style.maxWidth;
CineraProps.H = cinera.style.height;
CineraProps.mH = cinera.style.maxHeight;
CineraProps.P = cinera.style.position;
CineraProps.Display = cinera.style.display;
CineraProps.FlexDirection = cinera.style.flexDirection;
CineraProps.JustifyContent = cinera.style.justifyContent;
CineraProps.ScrollX = window.scrollX;
CineraProps.ScrollY = window.scrollY;
cinera.style.backgroundColor = "#000";
cinera.style.zIndex = 64;
@ -939,43 +945,43 @@ function toggleTheatreMode() {
viewItems[0].setAttribute("data-id", "regular");
viewItems[0].setAttribute("title", "Regular mode");
viewItems[0].firstChild.nodeValue = "📺";
} cineraProps.V = views.THEATRE; localStorage.setItem(cineraViewStorageItem, views.THEATRE); break;
} CineraProps.V = views.THEATRE; localStorage.setItem(cineraViewStorageItem, views.THEATRE); break;
case views.SUPERTHEATRE:
{
leaveFullScreen_();
}
case views.THEATRE:
{
cinera.style.backgroundColor = cineraProps.C;
cinera.style.zIndex = cineraProps.Z;
cinera.style.left = cineraProps.X;
cinera.style.top = cineraProps.Y;
cinera.style.width = cineraProps.W;
cinera.style.maxWidth = cineraProps.mW;
cinera.style.height = cineraProps.H;
cinera.style.maxHeight = cineraProps.mH;
cinera.style.position = cineraProps.P;
cinera.style.display = cineraProps.Display;
cinera.style.flexDirection = cineraProps.FlexDirection;
cinera.style.justifyContent = cineraProps.JustifyContent;
cinera.style.backgroundColor = CineraProps.C;
cinera.style.zIndex = CineraProps.Z;
cinera.style.left = CineraProps.X;
cinera.style.top = CineraProps.Y;
cinera.style.width = CineraProps.W;
cinera.style.maxWidth = CineraProps.mW;
cinera.style.height = CineraProps.H;
cinera.style.maxHeight = CineraProps.mH;
cinera.style.position = CineraProps.P;
cinera.style.display = CineraProps.Display;
cinera.style.flexDirection = CineraProps.FlexDirection;
cinera.style.justifyContent = CineraProps.JustifyContent;
window.scroll(
{
top: cineraProps.ScrollY,
left: cineraProps.ScrollX
top: CineraProps.ScrollY,
left: CineraProps.ScrollX
}
);
viewItems[0].setAttribute("data-id", "theatre");
viewItems[0].setAttribute("title", "Theatre mode");
viewItems[0].firstChild.nodeValue = "🎭";
} cineraProps.V = views.REGULAR; localStorage.removeItem(cineraViewStorageItem); break;
} CineraProps.V = views.REGULAR; localStorage.removeItem(cineraViewStorageItem); break;
}
player.updateSize();
}
function toggleSuperTheatreMode()
{
switch(cineraProps.V)
switch(CineraProps.V)
{
case views.REGULAR:
{
@ -984,12 +990,12 @@ function toggleSuperTheatreMode()
case views.THEATRE:
{
enterFullScreen_();
} cineraProps.V = views.SUPERTHEATRE; localStorage.setItem(cineraViewStorageItem, views.SUPERTHEATRE); break;
} CineraProps.V = views.SUPERTHEATRE; localStorage.setItem(cineraViewStorageItem, views.SUPERTHEATRE); break;
case views.SUPERTHEATRE:
{
leaveFullScreen_();
toggleTheatreMode();
} cineraProps.V = views.REGULAR; localStorage.removeItem(cineraViewStorageItem); break;
} CineraProps.V = views.REGULAR; localStorage.removeItem(cineraViewStorageItem); break;
}
player.updateSize();
}

View File

@ -4,6 +4,73 @@ var orientations = {
LANDSCAPE_RIGHT: -90,
};
function
DeriveReliableWindowDimensions()
{
// https://www.howtocreate.co.uk/tutorials/javascript/browserwindow
var Result = {
X: null,
Y: null,
};
var DisplaySettings = [];
for(var i = 0; i < document.body.children.length; ++i)
{
var Child = document.body.children[i];
DisplaySettings.push(Child.style.display);
Child.style.display = "none";
}
var Element = document.createElement("div");
Element.style.position = "fixed";
Element.style.top = 0;
Element.style.right = 0;
Element.style.bottom = 0;
Element.style.left = 0;
Element.style.zOffset = -1;
Element.style.opacity = 0;
var ElementInPlace = document.body.appendChild(Element);
Result.X = ElementInPlace.offsetWidth;
Result.Y = ElementInPlace.offsetHeight;
ElementInPlace.remove();
for(var i = 0; i < document.body.children.length; ++i)
{
var Child = document.body.children[i];
Child.style.display = DisplaySettings.shift();
}
return Result;
}
function
GetRealOrientation(PreferredLandscape, IsMobile)
{
var Result = window.orientation;
var WindowDim = {
X: null,
Y: null,
};
if(IsMobile)
{
WindowDim = DeriveReliableWindowDimensions();
}
else
{
WindowDim.X = document.body.clientWidth;
WindowDim.Y = document.body.clientHeight;
}
if(WindowDim.Y > WindowDim.X)
{
Result = orientations.PORTRAIT;
}
else if(Result == undefined || Result == orientations.PORTRAIT)
{
Result = PreferredLandscape;
}
return Result;
}
var DebugConsoleMessageCount = 0;
function Say(Message)
{
@ -275,7 +342,7 @@ function getElementYOffsetFromPage(el) {
}
function
MaxWidthOfElement(Element)
MaxWidthOfElement(Element, WindowDim)
{
var Result = 0;
var OriginalWidth = Element.style.width;
@ -283,21 +350,31 @@ MaxWidthOfElement(Element)
var Max = parseInt(window.getComputedStyle(Element).width);
Element.style.width = "unset";
var Default = parseInt(window.getComputedStyle(Element).width);
Element.style.width = OriginalWidth;
if(Max > window.innerWidth || Max == Default)
var InnerWidth = WindowDim ? WindowDim.X : document.body.clientWidth;
if(Max > InnerWidth || Max == Default)
{
Result = window.innerWidth;
Result = InnerWidth;
}
else
{
Result = Max;
}
Element.style.width = Result + "px";
if(Element.scrollWidth > Element.clientWidth)
{
Result = Element.clientWidth;
}
Element.style.width = OriginalWidth;
return Result;
}
function
MaxHeightOfElement(Element)
MaxHeightOfElement(Element, WindowDim)
{
var Result = 0;
var OriginalHeight = Element.style.height;
@ -305,16 +382,25 @@ MaxHeightOfElement(Element)
var Max = parseInt(window.getComputedStyle(Element).height);
Element.style.height = "unset";
var Default = parseInt(window.getComputedStyle(Element).height);
Element.style.height = OriginalHeight;
if(Max > window.innerHeight || Max == Default)
var InnerHeight = WindowDim ? WindowDim.Y : document.body.clientHeight;
if(Max > InnerHeight || Max == Default)
{
Result = window.innerHeight;
Result = InnerHeight;
}
else
{
Result = Max;
}
Element.style.height = Result + "px";
if(Element.scrollHeight > Element.clientHeight)
{
Result = Element.clientHeight;
}
Element.style.height = OriginalHeight;
return Result;
}

View File

@ -1,4 +1,5 @@
document.body.style.overflowY = "scroll";
CineraProps.Orientation = GetRealOrientation(orientations.LANDSCAPE_LEFT, CineraProps.IsMobile);
// Element Selection
//
@ -48,10 +49,12 @@ SyncNavState();
// NOTE(matt): Listeners
//
BindControlKeys();
BindGridKeys(Nav.GridSize);
BindControls();
InitResizeEventListener();
InitOrientationChangeListener();
InitScrollEventListener(Nav.Nexus);
InitScrollEventListener(Nav.Grid);
//
////

File diff suppressed because it is too large Load Diff