Skip to content

Top-align the artwork side by side and keep the player's times on one line - #1645

Merged
GianniCarlo merged 2 commits into
developfrom
feat/player-side-by-side-alignment
Oct 14, 2026
Merged

GianniCarlo merged 2 commits into
developfrom
feat/player-side-by-side-alignment

Conversation

@GianniCarlo

Copy link
Copy Markdown
Collaborator

Problem

The player's side-by-side layout (artwork beside the controls, #1639) looked off on iPhone Duo closed in landscape (678 × 466 pt):

  • The artwork is limited by its column's width there (about 250 pt), and it was centered vertically in its column, so it dropped below the chapter title while the controls start at the top.
  • The cover screen has its camera on one side only, so the content sat 22 pt from the other edge and about 108 pt from the camera side.
  • With hours in the times under the slider (a chapter or the whole book over an hour, e.g. "11:59:59"), the remaining time could wrap onto a second line; it fit on develop by a few points, and not with any less width.

Changes

  • PlayerView (PlayerContentView): side by side, the artwork sits at the top of its column, level with the title row. On iPhone it already filled the column's height, so nothing moves there. Each side also keeps at least 40 pt from the edge (the same as the gap between the artwork and the controls); where the safe area already gives more (iPhone, the camera side), nothing changes. The insets are read with a GeometryReader, in the same layout pass, so a rotation never shows uneven margins.
  • ListeningProgressView: the times never wrap. Each side reserves the width of the longer time (the other one is laid out hidden), so the label between them stays centered, and it's the one that gives way when the row is short, truncating from the start so the numbers stay ("…pter 3 of 6").

Testing

  • iPhone Duo simulator (iOS 27.1), closed in landscape: artwork top level with the title row; 40 pt from the edge without the camera (was 22 pt); a 12-hour test book shows "03:04 · …pter 1 of 1 · 11:59:59" on one line (develop: the time nearly touching the middle label; with the 40 pt margins and the old row it wrapped as "11:59:5 / 9").
  • iPhone 17 Pro simulator (iOS 27.0): landscape unchanged (same artwork frame, 86 pt side margins); portrait stacked and centered.
  • iPhone SE simulator (iOS 27.0) with the 12-hour book: portrait shows "00:12 · Chapter 1 of 1 · -11:59:47" on one line.
  • iOS 26.5 simulator: the release check's testFreshLaunch, testImport and testPlayback pass (player.currentTime still found by its identifier).
  • Unit tests: all 972 pass.

Not re-checked: the L pose's top half (the same rules apply there; its side margins were about 24 pt, so they become 40 pt).

…e line

- PlayerView: side by side, the artwork sits at the top of its column, level with the
  title row. Where its width limits it (iPhone Duo closed in landscape) it no longer drops
  below the title. Each side also keeps at least 40 pt from the edge (the gap between the
  artwork and the controls): the closed Duo has its camera on one side only, which left
  the content 22 pt from the other edge. The safe-area insets are read in the same layout
  pass (GeometryReader), so a rotation never shows uneven margins.
- ListeningProgressView: the times under the slider never wrap. Each side reserves the
  width of the longer time (the other is laid out hidden), so the label between them stays
  centered and is the one that gives way, truncating from the start ("...pter 3 of 6").
  With hours (a chapter or the whole book over an hour) the time wrapped on the closed
  Duo.
Comment thread BookPlayer/Player/Views/ListeningProgressView.swift Outdated
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

✅ Claude PR Review — PASS

Layout-only SwiftUI change. PlayerContentView is now wrapped in a GeometryReader. Side by side, each edge gets at least 40 pt (the safe-area inset counts toward it) and the artwork is top-aligned. ListeningProgressView keeps the times on one line: each side reserves the width of the longer time with a hidden placeholder, and the middle label is the part that gets cut. Nothing here touches concurrency, the player or audio session, CoreData/SwiftData, or auth and subscriptions. The player.currentTime identifier is still on the visible elapsed-time text, and views marked .hidden() are left out of accessibility, so VoiceOver and the release-check UI test are unaffected. Earlier finding #1 is fixed in this version: the times no longer have .lineLimit(1) and wrap at the largest Dynamic Type sizes instead of being cut off. One optional note: cutting from the start hides the number in the "%@ left" form of the middle label.

Findings: 1 info

Previously raised

Finding Status
BookPlayer/Player/Views/ListeningProgressView.swift:53 (warn) ⚠︎ moved ✅ verified fixed in a5a7d9f

Model claude-opus-5-5 · run log · 1 new · 0 carried over · 1 verified closed · 0 resolved · advisory (a human should still review). Findings are de-duplicated across pushes; an earlier finding closes only when the verification pass judges it against the current code — fixed, no longer applicable, accepted by a maintainer, or a duplicate of a finding reported on this push.

The times under the slider keep the room they need first, so at regular text sizes they
stay on one line as before; only when even they don't fit (the largest text sizes) were
they cut off by the one-line limit. Without it they wrap wherever the player has the
height for it.
Text(progressLabel)
.lineLimit(1)
/// The end ("3 of 6") is the part worth keeping
.truncationMode(.head)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 INFO — .truncationMode(.head) suits player_chapter_description ("Chapter %d of %d"), but this label also shows player_book_remaining_title ("%@ left", from bookRemainingLabel) and the percentage. With head truncation the book-remaining form loses its number when squeezed ("…m left" or "…left"). Translations that put the numbers first have the same problem. Option 1: pick the mode per form, e.g. .head only when prefersChapterContext is on and the chapter form is showing, .tail otherwise. Option 2: add a small .minimumScaleFactor(0.85) before any truncation, so the label shrinks a little before it's cut.

@GianniCarlo
GianniCarlo merged commit 075eff7 into develop Oct 14, 2026
3 checks passed
@GianniCarlo
GianniCarlo deleted the feat/player-side-by-side-alignment branch October 14, 2026 15:29

This branch was successfully deployed

1 active deployment
reviewer — a5a7d9fe Deployed Oct 14, 2026 by GianniCarlo via review #267
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant