mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 16:31:05 +02:00
cc67be341f
On a window too short for the stacked single-column layout -- a phone, or a narrow desktop window -- the ROM / SAVE FILES / Play / SAVE SLOT stack ran past the bottom of the window while the footer stayed pinned there and drew over it. Nothing clipped the panel and nothing scrolled it, so the overflow was unreachable. Everything under the tab bar (panel, updater banner, footer) is now one scrolling column, used only when it is taller than the room below the tab bar. The strip, logo and tab bar stay pinned, so navigation is always on screen, and the footer is laid out downward from footerTop right after the content instead of upward from the window bottom. - RomImporter.pageScrollFor is the whole decision, pure and covered by tests/engine/launcher_page_scroll.lua. A window that grows back drags the offset down with it, so the page never stays parked past its own end. - The panels return their natural height as they draw, so the measurement is the previous frame's: the same one-frame settle the slot and mod lists already rely on. - One scroll axis at a time. While the page scrolls, the panels draw paged: the slot and mod lists take their natural height, keep no inner scroll region and report a max of 0, so wheel, right stick and drag all move the page. Two-column layouts do not overflow, paged stays false, and every one of these behaves exactly as before. - inside() and _ptIn() reject a rect that scrolled out of the viewport, so a control that slid under the tab bar cannot be clicked through it. Tab chips are pinned and exempt. pageScroll resets on a tab change. Android had no scroll gesture at all: the launcher is handed no move events (main.lua forwards neither touchmoved nor mousemoved while it is up) and its mouse emulation was never trusted, which is what "no reliable pointer polling" referred to. That was survivable while every scroll region was an inner list, and useless once the page itself scrolls, since a phone is exactly where it overflows. love.touch is pollable, so _pointerHold reads the first active touch there and hands _updateSlotDrag the same (held, y) pair the mouse gives on desktop. Slot rows and mod toggles consequently arm on press and commit on release on Android too, matching desktop, so a swipe that starts on a card scrolls instead of selecting it. All of it is gated on touchPollable: without love.touch every Android path is exactly what it was. conf.lua also grows minwidth/minheight (480x360) for the desktop window, under which the cards stop being readable. Mobile is fullscreen and ignores it. Verified on the Android emulator (1080x2400) against a build of the parent commit: before, the footer painted over the SAVE SLOT card with no way to reach it; after, the page pans by touch and the footer is reachable and intact.
64 lines
3.2 KiB
Lua
64 lines
3.2 KiB
Lua
-- Launcher page scroll (src/import/RomImporter.lua): the column under the tab
|
|
-- bar -- panel, updater banner, footer -- scrolls as one when the window is too
|
|
-- short to hold it. Before this, a stacked single-column layout on a narrow
|
|
-- window ran under a footer pinned to the window bottom, and the part below the
|
|
-- fold could not be reached at all. The arithmetic is pure, so pin it here
|
|
-- rather than in a screenshot.
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
if not _G.love then _G.love = require("tests.love_stub") end
|
|
|
|
local T = require("tests.modkit")
|
|
local RomImporter = require("src.import.RomImporter")
|
|
|
|
local pageScrollFor = RomImporter.pageScrollFor
|
|
|
|
-- ------------------------------------------------------------- fits: inert
|
|
local paged, scroll, maxPage = pageScrollFor(400, 600, 0)
|
|
T.eq(paged, false, "a column shorter than the viewport does not scroll")
|
|
T.eq(maxPage, 0, "and has nowhere to scroll to")
|
|
T.eq(scroll, 0, "and sits at the top")
|
|
|
|
-- An exact fit is still not a scroll: one pixel of slack would show a thumb
|
|
-- for nothing and put the wheel on the page instead of the slot list.
|
|
paged, _, maxPage = pageScrollFor(600, 600, 0)
|
|
T.eq(paged, false, "a column exactly as tall as the viewport does not scroll")
|
|
T.eq(maxPage, 0, "an exact fit has no scroll extent")
|
|
|
|
-- --------------------------------------------------------- overflows: scrolls
|
|
paged, scroll, maxPage = pageScrollFor(900, 600, 0)
|
|
T.eq(paged, true, "a column taller than the viewport scrolls")
|
|
T.eq(maxPage, 300, "the extent is exactly the overflow")
|
|
T.eq(scroll, 0, "a fresh page starts at the top")
|
|
|
|
-- The bottom of the travel shows the footer: the whole overflow is reachable,
|
|
-- which is the point of the change (#footer under the fold).
|
|
_, scroll = pageScrollFor(900, 600, 300)
|
|
T.eq(scroll, 300, "the offset can reach the end of the column")
|
|
_, scroll = pageScrollFor(900, 600, 5000)
|
|
T.eq(scroll, 300, "an offset past the end clamps to it")
|
|
_, scroll = pageScrollFor(900, 600, -40)
|
|
T.eq(scroll, 0, "an offset above the top clamps to it")
|
|
|
|
-- ------------------------------------------------------- the window grows back
|
|
-- Resizing taller has to pull the page back down with it; leaving the offset
|
|
-- where it was would park the content above the viewport with no way back.
|
|
_, scroll, maxPage = pageScrollFor(900, 800, 300)
|
|
T.eq(maxPage, 100, "a taller window leaves less to scroll")
|
|
T.eq(scroll, 100, "and drags a deeper offset back to the new end")
|
|
paged, scroll = pageScrollFor(900, 900, 300)
|
|
T.eq(paged, false, "growing past the content stops the scrolling")
|
|
T.eq(scroll, 0, "and returns the page to the top")
|
|
|
|
-- ---------------------------------------------------------------- degenerate
|
|
-- draw() computes the viewport from the window height, so a window smaller than
|
|
-- the pinned header hands this a negative number; it must not become extra
|
|
-- travel.
|
|
_, _, maxPage = pageScrollFor(500, -120, 0)
|
|
T.eq(maxPage, 500, "a negative viewport counts as no room, not as more of it")
|
|
paged, scroll, maxPage = pageScrollFor(nil, nil, nil)
|
|
T.eq(paged, false, "a first frame with nothing measured yet does not scroll")
|
|
T.eq(scroll, 0, "and sits at the top")
|
|
T.eq(maxPage, 0, "with no extent")
|
|
|
|
T.finish("launcher page scroll")
|