Members

(static, constant) EXTRAS_BOTTOM_SAFE_PADDING

Extra clearance so the focused row's bottom edge sits comfortably above the 5% action-safe zone. Adjusting this shifts BOTTOM and MIDDLE positions equally relative to the action zone.

Default Value
  • 18

(static, constant) EXTRAS_ROWLIST_DEFAULT_Y

Default RowList translation.y: places the focused row (TOP) 18px below the panel top edge.

Default Value
  • 18

Methods

(static) applyRowLayout() → {void}

applyRowLayout: Write the layout for the rows on screen in one setFields.

numRows must always equal the actual row count so floatingFocus never needs to scroll: if numRows < rowCount, navigation scrolls internally, which moves the focused row's RowList Y unpredictably and breaks updatePanelPosition's translation formula.

Returns:
Type: 
void

(static) cancelRun() → {void}

cancelRun: Drop the run in flight, if any. Its Task node is released with it, so nothing it delivers later can reach onExtrasRowReady, which only ever drains the current node.

Returns:
Type: 
void

(static) commitRows() → {void}

commitRows: Bring the rows on screen in line with the run's results in one pass, and write NOTHING that has not changed, because every write to an on-screen row redraws the counter (see startRun).

  • A row whose title, slot shape and source-content digest match what is on screen is left untouched (extrasRows.isRowUnchanged).
  • A changed row that is already on screen is reused so focus position survives; its new items are appended BEFORE the old ones are removed, so it is never momentarily empty (the same rule HomeRows.populateRowFromData follows).
  • A row whose fetch failed is KEPT: no answer says nothing about what the item has, and removing it would delete good content on a flaky refresh. See extrasRows.rowDisposition.
  • The layout is written only when a row was added, removed or re-shaped.

Which of those applies to each row is decided by extrasRows.commitActions, which is unit-tested; this applies its answer to the nodes.

Returns:
Type: 
void

(static) containsNode(nodes, node) → {boolean}

Parameters:
NameTypeDescription
nodesobject
nodedynamic
Returns:
Type: 
boolean

(static) fillRow(existing, kind, title, result) → {object}

fillRow: The row node for kind, holding result.items: the row already on screen when there is one, a new node otherwise.

Parameters:
NameTypeDescription
existingdynamic
kindstring
titlestring
resultobject
Returns:
Type: 
object

(static) finishRunIfResolved() → {void}

finishRunIfResolved: Once every slot of the run has resolved, commit and close the run.

Returns:
Type: 
void

(static) init() → {void}

Returns:
Type: 
void

(static) loadParts(data) → {void}

loadParts: Load the extras rows for an item. m.top.type must be set first (ItemDetails does). Rows per type are decided by extrasRows.plan; the server version decides whether a Collections row is one of them.

Parameters:
NameTypeDescription
dataobject
Returns:
Type: 
void

(static) loadPersonVideos(personId) → {void}

Parameters:
NameTypeDescription
personIddynamic
Returns:
Type: 
void

(static) onDestroy() → {void}

onDestroy: Full teardown releasing all resources before component removal. Called by ItemDetails.onDestroy() before nulling the extrasGrid reference.

Returns:
Type: 
void

(static) onExtrasRowReady() → {void}

onExtrasRowReady: Drain every result the orchestrator has appended since the last wake: wake events coalesce, appended children don't.

Returns:
Type: 
void

(static) onKeyEvent(key, press) → {boolean}

onKeyEvent: Anticipate the next row on UP/DOWN so the panel translation animation starts in sync with the RowList floatingFocus animation rather than after it completes. Returns false so the RowList handles the actual navigation.

Parameters:
NameTypeDescription
keystring
pressboolean
Returns:
Type: 
boolean

(static) onProgramsExpired() → {void}

Fires when JRRowList's progress tick detects at least one expired Program among this list's rows. Refetches only the Channel Programs row (TvChannel "Up Next" / Program "More on this Channel") so finished broadcasts roll off; related content is stable over a viewing session and is not refetched.

Skipped while any run is in flight: starting a run cancels the one in progress, which would throw away its other rows. The tick raises the flag again on its next pass while a program is still expired, so nothing is lost by waiting.

Returns:
Type: 
void

(static) onRowItemFocused() → {void}

Returns:
Type: 
void

(static) onRowItemSelected() → {void}

Returns:
Type: 
void

(static) resetForLoad() → {void}

resetForLoad: State a full load starts from. A targeted refetch (onProgramsExpired) skips this: it must not move the panel or reopen the readiness signal.

Returns:
Type: 
void

(static) resolveSlot(slot, status, result) → {void}

resolveSlot: Record one row's outcome for the commit.

Parameters:
NameTypeDescription
slotinteger
statusstring
resultobject

the finished row: { items, shape, digest, contentKind }

Returns:
Type: 
void

(static) setPlan(plan) → {void}

setPlan: Adopt a plan, stamping each row with slot, its index: the key results come back on.

Parameters:
NameTypeDescription
planobject
Returns:
Type: 
void

(static) startRun(runRows, people, data) → {void}

startRun: Load runRows (all of m.plan, or a subset of it for a targeted refetch).

Nothing reaches the RowList until the WHOLE run has resolved; then commitRows applies every change in one pass. That is the point of this component's shape, not an incidental: RowList redraws its "X of Y" row counter on any write to rows already on screen (a row appended below them, a live row's items replaced), even when the count it shows does not change, and that redraw read as a flicker. Measured on device: committing rows as each resolved blinked once per commit after the first, and one commit that rewrote unchanged rows still blinked once.

Parameters:
NameTypeDescription
runRowsobject

plan rows to load this run

peopledynamic

the item's People array, for a Cast row (invalid when there is none)

datadynamic

the item node, for rows built on this thread (Chapters)

Returns:
Type: 
void

(static) updatePanelPosition(rowIndex) → {void}

updatePanelPosition: Set targetTranslationY so ItemDetails.bs can animate the RowList's translation within extrasGrp. extrasGrp stays fixed at extrasLayout.PANEL_OPEN_Y (306).

numRows always equals the total row count (set in applyRowLayout), so floatingFocus never scrolls internally. All rows stay at fixed RowList-relative Y positions: row 0: RowList Y = 0 row N: RowList Y = sum(heights[0..N-1]) + N * m.rowSpacing (= focusedRowY)

Visible screen height between panel top and action zone: extrasLayout.ACTION_SAFE_BOTTOM_Y - extrasLayout.PANEL_OPEN_Y = 720px.

Three position classes: TOP: row 0 (or only row): focused row at RowList Y=0, default translation (18px). BOTTOM: last row: focused row bottom edge at action zone - EXTRAS_BOTTOM_SAFE_PADDING. extrasLayout.PANEL_OPEN_Y + translationY + focusedRowY + rowHeight = extrasLayout.ACTION_SAFE_BOTTOM_Y - EXTRAS_BOTTOM_SAFE_PADDING translationY = (extrasLayout.ACTION_SAFE_BOTTOM_Y - extrasLayout.PANEL_OPEN_Y - EXTRAS_BOTTOM_SAFE_PADDING) - rowHeight - focusedRowY MIDDLE: rows 1..N-2: focused row centered in the visible area. translationY = int((extrasLayout.ACTION_SAFE_BOTTOM_Y - extrasLayout.PANEL_OPEN_Y - rowHeight) / 2) - focusedRowY

Negative translationY moves the RowList above extrasGrp Y=0. The clippingRect Group in ExtrasSlider.xml clips that overflow so the previous row only peeks within the panel bounds. targetTranslationY is observed by ItemDetails.bs which runs the gridAnime Animation. Called early from onKeyEvent (before RowList focuses the row) and confirmed by onRowItemFocused.

Parameters:
NameTypeDescription
rowIndexinteger
Returns:
Type: 
void

(static) updateSize() → {void}

Returns:
Type: 
void