|
12 | 12 | import "pkg:/source/utils/streamSelection.bs" |
13 | 13 |
|
14 | 14 | ' Gap between bottom of itemInfoRows and top of extras pane when extras are open |
15 | | -const ITEM_DETAILS_EXTRAS_PADDING = 48 |
| 15 | +const ITEM_DETAILS_EXTRAS_PADDING = 24 |
16 | 16 | ' Minimum display height for the logo image — images too small are scaled up (aspect ratio preserved). |
17 | 17 | const LOGO_MIN_DISPLAY_HEIGHT = 212 ' Note: LOGO_MAX_DISPLAY_WIDTH takes precedence for very wide/flat logos; this minimum may not be reached. |
18 | 18 | ' Maximum display width for the logo image — prevents very wide/flat logos from overlapping buttons |
|
59 | 59 | m.itemDetailsSlider = m.top.findNode("itemDetailsSlider") |
60 | 60 | m.itemDetailsSliderInterp = m.top.findNode("itemDetailsSliderInterp") |
61 | 61 | m.extrasActive = false |
62 | | - m.animationTargetCalculated = false |
63 | 62 | m.extrasLoaded = false |
64 | 63 |
|
65 | 64 | ' Inner group: title + infoGroup + directorGenreGroup (never changes during activate/deactivate) |
|
1285 | 1284 | end function |
1286 | 1285 |
|
1287 | 1286 | sub itemContentChanged() |
1288 | | - m.animationTargetCalculated = false |
1289 | 1287 | m.seasonSeriesData = invalid |
1290 | 1288 | item = m.top.itemContent |
1291 | 1289 |
|
|
1842 | 1840 | sub onItemDetailsRendered() |
1843 | 1841 | if m.itemDetails.renderTracking = "none" then return |
1844 | 1842 | updateTextGradient() |
1845 | | - ' Only calculate animation target once per content load — itemInfoRows height is stable after metadata is set. |
1846 | | - if not m.animationTargetCalculated |
1847 | | - m.animationTargetCalculated = true |
1848 | | - updateItemDetailsAnimationTarget() |
1849 | | - end if |
1850 | 1843 | end sub |
1851 | 1844 |
|
1852 | 1845 | ' updateItemDetailsAnimationTarget: Slide itemDetails so the bottom of itemInfoRows sits just |
1853 | 1846 | ' above the extras pane. boundingRect() on a child returns LOCAL coords relative to the parent's |
1854 | 1847 | ' translation point, so we use translation[1] (not boundingRect().y) as the screen origin. |
| 1848 | +' Called just-in-time from the DOWN key handler to guarantee the layout is fully settled |
| 1849 | +' (text wrapping complete) before measuring. Eager calculation via renderTracking races |
| 1850 | +' with async text layout, producing stale targets — especially for long descriptions. |
1855 | 1851 | sub updateItemDetailsAnimationTarget() |
1856 | | - if m.extrasActive then return |
1857 | | - |
1858 | 1852 | currentTransY = m.itemDetails.translation[1] |
1859 | 1853 | itemInfoRowsLocalRect = m.itemInfoRows.boundingRect() |
1860 | 1854 | screenBottomOfInfoRows = currentTransY + itemInfoRowsLocalRect.y + itemInfoRowsLocalRect.height |
|
2458 | 2452 |
|
2459 | 2453 | populateInfoGroupSeason(m.top.itemContent, m.global.user.settings) |
2460 | 2454 |
|
2461 | | - ' Row heights changed — reset so onItemDetailsRendered() recalculates the extras animation target |
2462 | | - m.animationTargetCalculated = false |
2463 | | - |
2464 | 2455 | ' Update logo using series data if the season didn't carry parentLogoItemId |
2465 | 2456 | if isValid(m.itemLogo) and not m.itemLogo.visible |
2466 | 2457 | setItemLogo(m.seasonSeriesData) |
|
2515 | 2506 | m.itemDescription.text = content[0] |
2516 | 2507 | m.itemDescription.visible = true |
2517 | 2508 | setDescriptionInLayout(true) |
2518 | | - ' Row heights changed — reset so onItemDetailsRendered() recalculates the extras animation target |
2519 | | - m.animationTargetCalculated = false |
2520 | 2509 | end sub |
2521 | 2510 |
|
2522 | 2511 | ' onFirstEpisodeLoaded: Start playback of first episode for Series Play button |
|
2581 | 2570 | m.top.lastFocus = m.extrasGrid |
2582 | 2571 | m.extrasGrid.setFocus(true) |
2583 | 2572 |
|
| 2573 | + ' Calculate animation target with the fully-settled layout before activating extras |
| 2574 | + updateItemDetailsAnimationTarget() |
2584 | 2575 | activateExtras() |
2585 | 2576 |
|
2586 | 2577 | ' Hide description and tracks before sliding up so they don't show during the transition |
|
0 commit comments