Commit Graph

696 Commits

Author SHA1 Message Date
Arkadiusz Fal
40267573a9 Suspend the orientation lock while the Duo hinge is open
The in-app orientation lock pinned the player to the orientation it
opened in even where programmatic rotation is refused, so rotating the
half-open device did nothing. OrientationManager now ignores lock
requests and drops the current lock while canRotateProgrammatically is
false. The YATTEE_FORCE_TABLETOP override only applies on the interior
display size and flags the same state, matching a real .partiallyOpen
hinge instead of forcing the layout on the folded exterior display.
2026-10-01 22:35:47 +02:00
Arkadiusz Fal
83895a1fd9 Reflect the video below the hinge in the tabletop layout
The iPhone Duo tabletop layout mirrors every presented frame into the
lower half, blurred and fading out, like a screen standing on a glossy
table. The render view blits a quarter-resolution copy of the display
framebuffer into a ring of IOSurface-backed buffers (no Y flip, so the
surface is already mirrored) and hands it to a CALayer hosted by
MPVReflectionView; the simulator's software renderer feeds the same
layer a flipped CGImage. Off during PiP, for audio-only streams, and
via the new Playback → Foldable → "Reflection Below Video" setting.
2026-10-01 20:59:48 +02:00
Arkadiusz Fal
2fd52fff27 Support the iPhone Duo interior display in the player
The interior display refuses programmatic rotation
(UISceneErrorDomain 101: "The current windowing mode does not allow for
programmatic changes to interface orientation"), so the rotate/fullscreen
button did nothing there and the failure was swallowed.

- OrientationManager tracks `canRotateProgrammatically` (from the hinge
  state, cleared when a geometry request is refused) and is @Observable.
- The fullscreen button takes the iPad path when rotation is unavailable:
  details toggle in portrait, floating panel toggle in landscape, icon
  follows the panel state; orientation lock is hidden. The refused request
  itself falls back to the details toggle. Accelerometer-driven rotation
  requests are gated the same way.
- Corner layout gate is size-only on iOS (≥900×600 including safe areas,
  so the status bar toggling with the layout can't oscillate it); the
  layout-mode setting is exposed on foldables via a hinge presence check.
- Corner layout on iPhone always hides the status bar (the interior's
  landscape bar is a ~57pt column) and pads by the live top inset only,
  instead of the transient 82pt inset seen while unfolding.
- The player hosting controller nudges its safe area after size
  transitions so fold/unfold doesn't leave SwiftUI with stale insets.
2026-10-01 08:53:37 +02:00
Arkadiusz Fal
2d65bc756f Animate the tabletop layout switch on hinge changes 2026-10-01 06:46:06 +02:00
Arkadiusz Fal
8a8f3a6000 Restore search field activation when selecting the search tab on iOS 27
iOS 27 changed the default TabSearchActivation so a role: .search tab no
longer focuses the search field on selection. Opt back into the iOS 26
behavior with .tabViewSearchActivation(.searchTabSelection).
2026-09-30 23:57:22 +02:00
Arkadiusz Fal
123be0b3ff Tighten the tabletop controls layout
The tabletop top bar sits below the hinge, not under the status bar, so
the top safe area padding is no longer added on top of the tabletop
offset. The side sliders reserve only the icon row and a small margin
from the lower-half center zone instead of the fullscreen allowance, and
the dimming scrim is skipped since no control overlaps the video.
2026-09-30 23:43:41 +02:00
Arkadiusz Fal
66d7d5b944 Keep tabletop video in the upper half while dragging the panel
The hidden video position was derived from the tabletop layout height,
which only applies while the panel is hidden. Dragging the visible panel
down therefore interpolated the video towards the full-screen center and
it snapped back to the upper half once the hidden state flipped. Derive
the hidden position from the hinge state directly so every drag, dismiss
and reveal targets the upper-half center.
2026-09-30 23:18:36 +02:00
Arkadiusz Fal
11a0dfddd0 Extend iPhone channel banner under horizontal safe area insets
On the iPhone Duo exterior display the vertical status bar adds an 84pt
trailing safe area inset, which left the channel banner short of the
screen edge. The banner and its gradient are now widened by the outer
container's horizontal insets on compact layouts and offset so each side
bleeds by its own inset; the avatar and name stay centered on the content
width. iPad/Mac keep using backgroundExtensionEffect.
2026-09-30 22:49:39 +02:00
Arkadiusz Fal
99d3d31031 Add iPhone Duo tabletop player layout and exterior display insets
Observe the foldable hinge with `onHingeChange` (iOS 27.1): while it is
partially open and the portrait panel is hidden, the video is fitted to
the upper half of the screen and every control (title bar, center
controls, side sliders, bottom bar) moves to the lower half. Pinch to
fill is disabled in that state. `YATTEE_FORCE_TABLETOP=1` in the launch
environment forces the layout on simulators without a hinge control.

The exterior display has a vertical status bar with a trailing safe
area inset, which squeezed the fullscreen portrait player into the
content width. The video and controls layers now span the full window
width (shifted under the leading inset, like the existing vertical
handling) and the controls pad their edges by the sheet's actual
asymmetric horizontal insets instead of the symmetric max.

Requires the iOS 27.1 SDK (Xcode 27.1).
2026-09-30 22:02:12 +02:00
Arkadiusz Fal
39041e4b39 Replace UIScreen.main with scene-local context
- List row hairlines read displayScale from the SwiftUI environment
- MPV render views take contentScaleFactor from traitCollection and
  re-apply it on UITraitDisplayScale changes
- ExpandedPlayerWindow scales against the presenting view's own height
- MPVPiPBridge sizes the PiP layer from the container view's window
  scene screen (UIScreen.main kept only as a nil-window fallback)
- WideScreenPlayerLayout falls back to the offered geometry size
- Remote control fullscreen state comes from the player sheet's layout
  pass via NavigationCoordinator.isWideScreenLayoutActive instead of
  screen bounds aspect
- Orientation TODOs for Dynamic Island side detection and
  prefersInterfaceOrientationLocked
2026-09-30 19:15:45 +02:00
Arkadiusz Fal
3395847763 Use Command-Enter to open links on macOS 2026-09-29 23:34:56 +02:00
Arkadiusz Fal
1071fc56b3 Stop inline macOS playback when its window closes 2026-09-29 23:26:00 +02:00
Arkadiusz Fal
60222fa5f3 Fix inline macOS player aspect resizing 2026-09-29 23:08:16 +02:00
Arkadiusz Fal
6df08d2cbc Fix macOS related video carousel chrome 2026-09-29 23:06:52 +02:00
Arkadiusz Fal
0812485d0e Hide main window traffic lights with corner player controls 2026-09-29 22:20:28 +02:00
Arkadiusz Fal
423c310bd4 Show every video info action in the macOS toolbar
The toolbar layout on macOS now lists Play, Download, Share, Add to Playlist
and Bookmark as separate toolbar items, with a spacer setting Play apart from
the secondary actions. The primary action picker stays iOS-only, where the
pinned action plus the ⋯ menu layout is kept, and macOS gets its own settings
footer text.

The macOS items are written out explicitly rather than with ForEach: a ForEach
inside the toolbar builder is evaluated once and never re-renders on state
changes, which left the bookmark and download icons stale.
2026-09-28 23:48:17 +02:00
Arkadiusz Fal
e0a07e93d2 Hide the description section when a video has no description
Direct media links have no description, so the info page showed a divider
and a "No description available" placeholder under the channel row. Skip
the section entirely (divider included) unless there is a description or
details are still loading, and drop the unused player.noDescription string.
2026-09-28 23:47:59 +02:00
Arkadiusz Fal
309d17941d Keep the macOS player controls hoverable when the corner layout panels come back
Exiting native fullscreen from the corner layout restores the panels, and
the controls view read that as a floating details panel opening: it set a
hide override and ignored mouse movement for as long as the panel stayed
visible, so hovering the video no longer showed the controls. Only a
floating (unpinned) panel covers the video, so the flag now excludes
pinned panels, matching the existing widescreen rule. Corner panels are
pinned, so the fullscreen restore and the title-tap toggle keep the
controls responsive to hover.
2026-09-28 23:45:24 +02:00
Arkadiusz Fal
8d340048ea Hide the corner layout panels when the macOS player enters native fullscreen
The fullscreen button in the corner layout zoomed the whole video-plus-
panels arrangement onto the screen and left the panels there. Now the
button hides the panels first (the video grows over them inside the
current window), waits for that animation, then runs the native zoom, so
the fullscreen space shows the video alone. On exit the window returns to
its size first and the panels slide back in, unless the user re-showed
them while fullscreen. System-initiated transitions (green button, Window
menu, Mission Control) hide the panels as the zoom starts.

Hiding the panels re-arms the separate window's aspect lock; an entering
flag parks it during the transition and the restore on exit skips the
parked replay, so the window keeps its corner size instead of auto-
fitting to the video. The preset's remembered panel visibility is left
untouched by the fullscreen session.
2026-09-28 23:05:05 +02:00
Arkadiusz Fal
96eeadb479 Stop the macOS player window oscillating when a drag crosses the corner layout threshold
The corner layout resolves from the window width. Dragging the window
narrower than the threshold dropped the layout mid-drag, which re-locked
the aspect ratio and auto-fitted the window back to the video size. The
fitted width was above the threshold again, so the layout re-entered
corner mode and unlocked, and the cycle repeated on every layout pass for
the rest of the drag (visible as the window abruptly jumping in size).

Aspect lock/unlock requests made during a live resize are now parked and
applied in windowDidEndLiveResize, since changing contentAspectRatio or
contentResizeIncrements under the cursor makes AppKit's resize handler
switch modes and snap the frame. Auto-fit never runs during a live resize,
and the corner-layout change handler skips it when the change was caused
by the user's drag: the drag owns the size.

The free-resize size floor in windowWillResize now clamps width and height
independently. Preserving the proposed ratio (correct only under an aspect
lock) widened the window while dragging just the bottom edge past the
minimum height.
2026-09-28 23:00:40 +02:00
Arkadiusz Fal
99692a3554 Fix macOS corner layout window resize and re-lock the aspect ratio when panels hide
Entering the corner layout cleared the window's aspect-ratio lock by setting
contentAspectRatio to zero. That doesn't remove the constraint: AppKit keeps
its aspect-ratio resize handler active with a degenerate 0:0 ratio, so every
interactive resize resolved to the current size and the window couldn't be
resized at all. Reset contentResizeIncrements to 1x1 instead, the supported
way back to free resizing (aspect ratio and resize increments are mutually
exclusive).

Free resize now also requires the corner panels to be visible. With the
panels hidden only the video remains, so the window follows the ratio lock
(and auto-fit, when on) exactly like the stacked layout. The new
AppEnvironment.isCornerPanelLayoutActive gate covers the layout-change
handler, window creation, and the fullscreen-exit replay.
2026-09-28 20:19:10 +02:00
Arkadiusz Fal
14fe028ece Lock the comments row in the pages editor when it sits below the video 2026-09-27 23:43:32 +02:00
Arkadiusz Fal
5786a0210a Use the macOS capsule mini player on iOS 18 and drop its duplicate close button
The iOS 18 overlay layout appended a hardcoded close button after the
preset buttons, and the default mini player preset already includes
Close, so the bar showed two X buttons. Replace the full-width material
bar with the same 420pt capsule macOS uses (shared capsuleLayout), and
only add the fallback close button when the active preset has none.

Inset the iOS 18 overlay 16pt horizontally; clear the bottom tab bar in
compact width and float 12pt above the edge in regular width, where
sidebarAdaptable keeps the tabs at the top.
2026-09-27 22:09:22 +02:00
Arkadiusz Fal
d2fb465234 Cap the expanded comments pill at 600pt on wide panels
The excerpt stretches to the panel width, which on the iPad corner
layout's below-video panel meant a pill spanning the whole window. The
own-row expanded pill is now capped at 600pt, centered above the player
pill; the bottom-row variant already had a 400pt cap.
2026-09-27 20:45:18 +02:00
Arkadiusz Fal
0bfbd47882 Replace per-page corner regions with one "Below Video" picker
The corner layout's below-video host is the portrait info panel, not a
page host: it can render only Info, plus Comments as the panel's pill on
iOS. The page editor still offered "Below Video" for every page, so
assigning Related there was accepted, stored, listed as such, and then
silently rendered in the side column.

- The Layout section gains a "Below Video" picker in corner mode:
  Nothing / Info / Info and Comments (macOS offers the first two). It
  writes the info/comments regions; the per-page Location section and
  its strings are gone.
- PanelSettings.normalizedPages clamps regions to what the host can
  render (only info/comments below, comments only together with info),
  so older presets self-correct. effectiveRegion(for:) resolves the
  platform-specific placement and is used by both the pages list labels
  and CornerPlayerLayout, replacing its own region checks.
- The layout schematic drops the below-video block for "Nothing"; the
  corner-mode footer explains the constraint.
- Tests cover the picker round-trip and the clamping.
2026-09-27 20:05:20 +02:00
Arkadiusz Fal
7f74b50e94 Make the player pill an on/off setting on iPad, drop the dead wide-layout pill overlay
On iPad both orientations show the video next to a panel, the corner
layout hosts the portrait panel in landscape, and Split View windows make
"portrait" mean "narrow", so the portrait/landscape visibility split never
matched what the user saw. PillVisibility now treats any mode except Never
as visible on iPad, and the pill editor shows a Show pill toggle there
(writes Both/Never, reads synced orientation modes as on). iPhone keeps
the four-way picker.

ExpandedPlayerSheet's bottomPillsOverlay was unreferenced; the floating
panel renders its own pill row.
2026-09-27 16:36:42 +02:00
Arkadiusz Fal
61786ec6f7 Move the wide-layout pin button into the panel page bar
The pin now sits as an icon-only pill at the leading edge of the page
bar, before the page pills, instead of floating on the resize grabber.
It stays fixed while the pages scroll and fills with the accent color
while pinned. The page bar is kept visible when a pin action is present
even if only one page is available, so the control never disappears.
iPhone (floating-only) still shows no pin.

Removes PanelPinButton, which had no other users.
2026-09-27 14:27:11 +02:00
Arkadiusz Fal
1370f68c37 Rework details panel settings: pinned info, per-orientation visibility, section defaults
Pages list
- Info is pinned first and always enabled in every layout: normalized
  pages force it to the front and enabled (older presets self-correct),
  disabling it is a no-op, and any move that would displace it snaps
  back. The iOS/macOS list renders it outside the reorderable ForEach
  (no drag handle, nothing drops above it) and the editors hide its
  enabled toggle; tvOS also hides its move buttons. The "at least one
  page must stay enabled" guard and its strings are gone since Info
  always counts.
- iPhone never renders queue or comments as pages, so its Sections list
  hides them (PanelSettings.hiddenSettingsPageTypes). Reordering goes
  through moveVisiblePages, which keeps hidden entries in their stored
  slots. Comments get their own group on the Details Panel screen
  (pill mode + avatars) and the overlay hosts pass the avatars flag.

Default visibility
- "When Player Opens" is now configured per orientation
  (portraitDefaultVisibility / landscapeDefaultVisibility). The legacy
  single value is still decoded and seeds both until set individually;
  presets that never set it default to portrait Visible, landscape
  Hidden. macOS shows one picker (no portrait layout).
- "Remember Last" no longer leaks across orientations: separate
  remembered flags, written by the portrait toggles and by the wide and
  corner layouts respectively, with the old shared flag read once as a
  fallback. The corner layout seeded from the portrait resolution
  before; it now uses landscape.

Section options (iOS inline-sections hosts)
- Chapters and Related editors gain "Expanded by Default" (on by
  default). The Info editor gains a Description group with "Expanded by
  Default" (off) and a "Collapsed Lines" stepper (1–10, default 3).
  Applied when the panel appears and on each video change.
- Expanding a collapsed section scrolls its header to the top of the
  panel: PanelPageScrollView can hand its scroll proxy to page content
  and each inline section is wrapped in one anchored container.
- The portrait panel's bottom fade sized its touch blocker from a stale
  "expanded comments pill" answer that ignored collapse on scroll, so a
  collapsed section header (the last item) sat under it and could not
  be tapped. The predicate now tracks the pill's actual collapse state.
2026-09-26 23:50:30 +02:00
Arkadiusz Fal
0b2cb4deeb Honor the comments avatars setting in the overlay and pill, align replies without avatars
The "Author Avatars" toggle only reached the iPad/macOS comments page.
The expanded comments overlay now takes the same flag (hosts pass it in
the next commit), and the expanded comments pill shows the comments icon
instead of the author avatar when avatars are off.

The replies block in a comment used a hardcoded 44pt leading inset for
the avatar column regardless of the toggle, so "Show replies" was
indented past the comment text when avatars were hidden. The toggle now
aligns with the text (44pt with avatars, 0 without) and nested replies
keep a smaller 16pt inset without avatars so the hierarchy still reads.
2026-09-26 23:21:37 +02:00
Arkadiusz Fal
4210b0ab05 Simplify the wide-layout details panel: floating-only on iPhone, side as a preset setting
iPhone landscape now uses the floating panel only, always on the right;
the pin and side-toggle buttons on the grabber are gone and the pinned
setting resolves to false on phone.

iPad and macOS default to the pinned side-by-side layout, keep the pin
button to switch to floating, and pick the panel side in the preset's
panel settings instead of an on-screen arrow. The pinned state persists
as a layout preference: closing the player or the hidden default
visibility no longer resets it.

Removes PanelAlignmentButton, the global floatingDetailsPanelSide setting
and its key, FloatingPanelSide.opposite, and the legacy
wideLayoutPanelAlignment preset field.
2026-09-26 22:48:11 +02:00
Arkadiusz Fal
c33d66ca1f Keep the landscape panel in place while Notification Center is open
WideScreenPlayerLayout looked up safe area insets and window bounds only
from a foregroundActive scene. Notification Center and Control Center move
the scene to foregroundInactive, so the lookup failed, insets dropped to
zero and the panel and video jumped to the screen edge. Fall back to an
inactive foreground scene (and then any scene) before giving up.
2026-09-26 21:00:18 +02:00
Arkadiusz Fal
967a2de9c9 Drop the extra top inset above the title in the iPhone floating panel 2026-09-26 15:44:51 +02:00
Arkadiusz Fal
2b2f6e8394 Fade the collapsed description under "more" with a mask instead of a painted gradient
The "more" label covered the end of the last line with a
systemBackground gradient, which rendered as a black block over the
floating panel's translucent material in landscape. The text is now
alpha-masked so the fade works on any host background.
2026-09-26 13:35:12 +02:00
Arkadiusz Fal
a81e618e74 Configure details panel sections on iPhone and honor their order
iPhone has no page switcher: the portrait panel already rendered one info
page with chapters and related videos as collapsible inline sections. The
landscape floating panel now renders the same panel (no page bar, comments
stay on the pill/overlay), and the settings screen calls the list
"Sections" there, with the page bar labels toggle hidden.

The inline sections were hardcoded to chapters then related and ignored
the configured order, enablement, and thumbnail toggles. The info page now
receives the enabled section pages from PanelSettings.inlineSections(in:)
and renders them in list order with their own settings.
2026-09-25 23:54:27 +02:00
Arkadiusz Fal
9387bdf42c Present video action sheets in the system color scheme from the floating panel
The unpinned floating details panel forces a dark color scheme on its
content so it reads over the video. The play now / play next and resume
sheets opened from a related video inherited that scheme, giving white
text on the light system sheet background.

The panel now publishes the real system scheme via a
presentationColorScheme environment value and the sheets reapply it.
2026-09-25 23:53:31 +02:00
Arkadiusz Fal
5af052b428 Jump panel pages to the top and clear stale chapters when the video changes
Tapping a related video kept the panel scrolled where it was, so the new
title was out of view, and the chapters section kept showing the previous
video's chapters until the new ones resolved.

The scroll config now carries the video identity and the shared page
scroll view scrolls to the top (without animation, resetting the reported
offset) whenever it changes. PlayerState.setCurrentVideo clears chapters
on a video id change, alongside comments and storyboards.
2026-09-25 21:44:43 +02:00
Arkadiusz Fal
f6ba35c1f5 Remove the tracks details panel page
The quality selector sheet already covers quality, audio, subtitles and
rate, so the embedded tracks page duplicated it. Drop the page type, its
per-page settings, the editor toggles, and the visibleSections plumbing
in QualitySelectorView.
2026-09-25 20:26:09 +02:00
Arkadiusz Fal
1fe1c2cd74 Attach the overscroll collapse gesture to the geometrically matching scroll view
The handler picked the first scroll view under the nearest ancestor,
which in the corner layout is one of the side column pages, so pulling
down on the expanded below-video panel never collapsed it. Match the
background view's window frame instead and re-attach when the match
changes.
2026-09-25 19:57:33 +02:00
Arkadiusz Fal
f4204105eb Fix clipped top controls and stale top padding in corner fullscreen
The fullscreen video layer extends up into the status bar strip and is
shifted with an offset; `.clipped()` came after the offset, so it clipped
to the unshifted frame and cut the top strip (title row, avatar) off. Clip
before the offset instead.

The player controls read the main window's safe area only on geometry
changes. With the corner layout keeping its geometry fixed across the
status bar hide, the value went stale and the controls kept the status bar
height as top padding in fullscreen. Refresh it when the status bar
visibility changes, with a few delayed re-reads to cover the fade.
2026-09-25 09:05:12 +02:00
Arkadiusz Fal
95124d87bb Fade corner layout panels while the video grows over them on toggle 2026-09-24 23:48:47 +02:00
Arkadiusz Fal
66ecbb9eb3 Grow the corner layout video over static panels instead of sliding them out
The fullscreen toggle used to slide both panels off screen while the video
frame grew into the freed space. Panels now stay at their home positions
as layers under the video, and the video frame grows over them to hide and
shrinks back to reveal. Both panels stay in the hierarchy while covered, so
scroll position and loaded content survive toggles; hit testing,
accessibility and the dismiss-pan exclusion frames are switched off while
covered (PanelResizeGrabber gets a publishesFrame flag for this).

Side column gestures (grabber overdrag, trailing edge swipe) drive the
video's trailing edge over the static column. The below panel's handle drag
keeps sliding the panel off the bottom, with the video growing in lockstep
so the edges coincide. The below panel is raised above the video only while
expanding over it, and drops back under it after the collapse spring has
fully settled.

Hiding the status bar in the fullscreen state changed the top safe area and
reflowed the whole layout mid-transition. The layout now ignores the top
safe area and pads by a fixed status bar height (remembered by
StatusBarVisibilityController while the bar is visible); the fullscreen
video grows up into that strip as part of the same animation.
2026-09-24 23:43:33 +02:00
Arkadiusz Fal
b1625afb4a Collapse the corner side column by overdrag and fix the fast reveal glitch
Overdragging the side column's resize grabber past its minimum width now
slides the column off the trailing edge (the video grows with it), and a
swipe in from the trailing screen edge brings it back following the
finger. The seek pan skips that edge strip while the column is
collapsed. Showing the panel again restores every region hidden by its
own drag handle.

Swiping the below-video panel back up right after hiding it showed the
video clipped to a short centered box that sprang back to full size.
The hide flipped to the hidden layout in a `.logicallyComplete`
completion while the slide spring was still registered on the SwiftUI
host of the mpv render view; a reveal drag interrupting it made the
release spring start from a bogus shrunken rect. All slide-off
completions now wait for `.removed` and bail if a new drag took over.
The visibility-keyed `.animation` modifiers key on a toggle generation
bumped only by the animated show/hide paths, so drag flips never start
the toggle easing. The partnerless `matchedGeometryEffect` on the
widescreen video frame is dropped.
2026-09-24 22:21:47 +02:00
Arkadiusz Fal
bfbb729a8c Align side column page content and tabs with the grabber inset
The corner layout side column puts a 12pt resize grabber strip before the
panel, and every page then added the standard 16pt horizontal padding, so
content sat ~28pt from the left edge but 16pt from the right.

Add a PanelHorizontalInsets environment value with a panelHorizontalPadding()
modifier that the info, comments, related and chapters pages use instead of
.padding(.horizontal). The side column trims the leading inset by the grabber
width so content is 16pt from the column's outer edge on both sides; other
hosts keep the defaults. Queue and tracks are List-backed and get the same
leading delta as a scroll content margin. The page bar follows the same insets
so the first pill lines up with the content.
2026-09-24 22:01:01 +02:00
Arkadiusz Fal
7f672d2c57 Make info panel chapter and related sections collapsible
Section headers in the inline info panel now toggle their content with a
rotating chevron. Collapsed state resets when the video changes. Also let
the collapsed description text take full width.
2026-09-24 19:00:27 +02:00
Arkadiusz Fal
ed2884d7ec Stop mpv render from blocking until frame target time
mpv_render_context_render slept until each frame's display time
(~40ms at 25fps) inside CAOpenGLLayer.display(), blocking main-thread
CoreAnimation commits and hitching UI scrolling during playback. Pass
MPV_RENDER_PARAM_BLOCK_FOR_TARGET_TIME=0 and let CGL vsync pace
presentation instead.
2026-09-24 06:38:01 +02:00
Arkadiusz Fal
22451804db Route corner layout pages by region and harden page selection
The below-video panel now renders only when the info page is assigned
to that region; comments assigned below become the portrait panel's
pill (iOS), and every other below-video page falls back to the side
column instead of disappearing. Page selection snaps to the first
configured page when the current one is disabled or reordered away,
and the page bar highlight follows the actually rendered page. The
related tab stays visible with a spinner while video details load
instead of vanishing until they arrive.
2026-09-23 23:52:08 +02:00
Arkadiusz Fal
4a85f7355a Track the active chapter in PlayerState instead of per-tick time reads
Chapter lists highlighted the active row by reading currentTime in the
view body, re-rendering every row many times per second during
playback. PlayerState now stores a change-guarded activeChapterID
updated when time or chapters change, so views observe only chapter
transitions.
2026-09-23 23:47:21 +02:00
Arkadiusz Fal
e7458ba629 Move comments pill mode into the comments page settings
The pill mode now lives on CommentsPageSettings and is edited in the
comments page editor instead of a standalone settings section. The
legacy value on PlayerPillSettings is kept for decoding old presets
and migrated by effectivePanelSettings. Comments are loaded when
either the comments page is enabled or the pill is not disabled.
2026-09-23 22:45:38 +02:00
Arkadiusz Fal
924facacc4 Restore portrait panel title position and drag handle fade
The panel content wrapper added a 10pt top padding that pushed the
scroll view down, sitting the title 6pt lower and hard-clipping
scrolled content below the drag handle instead of fading it through
the full top gradient. Drop the outer padding and restore the scroll
top inset to 10pt to match the pre-redesign look.
2026-09-23 21:44:34 +02:00
Arkadiusz Fal
52ec8c9f05 Block player dismiss pan from the panel resize grabber strip
Starting a column resize drag with a diagonal (downward) motion let the
window-level dismiss pan begin, cancelling the resize and dragging the
player down instead. The grabber now publishes its strip frame (with 8pt
slop on each side) to NavigationCoordinator, and the dismiss pan refuses
to begin from touches inside it — same exclusion pattern as the corner
layout's below-video panel frame.
2026-09-23 18:38:24 +02:00