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) addRowSize(newRow) → {void}

Parameters:
NameTypeDescription
newRowdynamic
Returns:
Type: 
void

(static) cancelInFlightChain() → {void}

cancelInFlightChain: Stop all tasks and unobserve their content fields before starting a new chain. Prevents observer stacking and halts unnecessary in-flight work (network, processing) when loadParts() or loadPersonVideos() is called while a previous chain is still running.

Returns:
Type: 
void

(static) init() → {void}

Returns:
Type: 
void

(static) loadParts(data) → {void}

loadParts: Start the extras loading chain appropriate for the item type.

Chain by type: Movie / Video / Recording → Chapters → AdditionalParts → People → LikeThis → SpecialFeatures Episode → Chapters → SeasonEpisodes → People → LikeThis MusicVideo → People → LikeThis Series → Seasons → People → LikeThis Season → Episodes ("Season X") → People → LikeThis BoxSet → BoxSetItems ("Movies") → People → LikeThis MusicArtist → Albums → Appears On → Songs → ArtistSimilar Photo → LikeThis PhotoAlbum → Album Photos → LikeThis TvChannel → Upcoming Programs → LikeThis Program → More on Channel → LikeThis m.top.type must be set before calling this function (done by ShowScenes.bs).

Parameters:
NameTypeDescription
dataobject
Returns:
Type: 
void

(static) loadPersonVideos(personId) → {void}

Parameters:
NameTypeDescription
personIddynamic
Returns:
Type: 
void

(static) onAdditionalPartsLoaded() → {void}

Returns:
Type: 
void

(static) onAlbumArtistAlbumsLoaded() → {void}

onAlbumArtistAlbumsLoaded: Build "More Albums" row (excluding current album) then chain to More Like This (MusicAlbum only)

Returns:
Type: 
void

(static) onAlbumSongsLoaded() → {void}

onAlbumSongsLoaded: Build "Songs" row then chain to More Albums by Artist → More Like This (MusicAlbum only)

Returns:
Type: 
void

(static) onArtistAlbumsLoaded() → {void}

onArtistAlbumsLoaded: Build "Albums" row then chain to Appears On (MusicArtist only)

Returns:
Type: 
void

(static) onArtistAppearsOnLoaded() → {void}

onArtistAppearsOnLoaded: Build "Appears On" row then chain to Songs (MusicArtist only)

Returns:
Type: 
void

(static) onArtistSimilarLoaded() → {void}

onArtistSimilarLoaded: Build "More Like This" row (MusicArtist only, end of chain). Uses Artists/{id}/Similar which is more reliable for MusicArtist than Items/{id}/Similar.

Returns:
Type: 
void

(static) onArtistSongsLoaded() → {void}

onArtistSongsLoaded: Build "Songs" row then chain to ArtistSimilar (MusicArtist only). Uses ArtistIds (broad) so songs on compilation albums surface even when album-level metadata doesn't associate the artist via AlbumArtistIds.

Returns:
Type: 
void

(static) onAudioAlbumTracksLoaded() → {void}

onAudioAlbumTracksLoaded: Build "More from {Album}" row with current track first, then tracks that follow it in order, then tracks that preceded it (wrapping around). E.g. viewing track 3 of 10 → [3, 4, 5, 6, 7, 8, 9, 10, 1, 2]

Returns:
Type: 
void

(static) onBoxSetItemsLoaded() → {void}

onBoxSetItemsLoaded: Build "Movies" row then chain to People → LikeThis (BoxSet only)

Returns:
Type: 
void

(static) onChannelProgramsLoaded() → {void}

onChannelProgramsLoaded: Build "Up Next" row then chain to More Like This (TvChannel only)

Returns:
Type: 
void

(static) onChannelProgramsRefetched() → {void}

Refetch handler for TvChannel "Up Next". Replaces the row content in place without re-chaining to LikeThisTask (unlike the initial-load handler).

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) 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) onLikeThisLoaded() → {void}

Returns:
Type: 
void

(static) onMoviesLoaded() → {void}

Returns:
Type: 
void

(static) onPeopleLoaded() → {void}

Returns:
Type: 
void

(static) onPhotoAlbumItemsLoaded() → {void}

onPhotoAlbumItemsLoaded: Build "Photos" row then chain to More Like This (PhotoAlbum only)

Returns:
Type: 
void

(static) onPlaylistItemsLoaded() → {void}

onPlaylistItemsLoaded: Build "Playlist Items" row then chain to More Like This (Playlist only). Detects whether items are all audio, all video, or mixed, and selects SQUARE vs PORTRAIT slots accordingly. Sets playlistContentKind ("audio"/"video"/"mixed"/"unknown") so ItemDetails can add the Watched button asynchronously.

Returns:
Type: 
void

(static) onProgramChannelProgramsLoaded() → {void}

onProgramChannelProgramsLoaded: Build "More on this Channel" row then chain to More Like This (Program only)

Returns:
Type: 
void

(static) onProgramChannelProgramsRefetched() → {void}

Refetch handler for Program "More on this Channel". Same in-place-update pattern as onChannelProgramsRefetched — no chain to LikeThisTask.

Returns:
Type: 
void

(static) onProgramsExpired() → {void}

Fires when JRRowList's progress tick detects at least one expired Program among this list's rows. Triggers a targeted refetch of the Channel Programs row (TvChannel "Up Next" or Program "More on this Channel") so finished broadcasts roll off and new ones take their place.

Deliberately does NOT re-chain to LikeThisTask — related content is stable over a viewing session and should not be refetched just because a program expired. m.isRefetchingChannelPrograms debounces repeated expiry signals.

Returns:
Type: 
void

(static) onRowItemFocused() → {void}

Returns:
Type: 
void

(static) onRowItemSelected() → {void}

Returns:
Type: 
void

(static) onSeasonAllEpisodesLoaded() → {void}

onSeasonAllEpisodesLoaded: Build "Episodes" row then chain to People (Season only)

Returns:
Type: 
void

(static) onSeasonEpisodesLoaded() → {void}

onSeasonEpisodesLoaded: Build "More from Season X" row with current episode first, then episodes that follow it in order, then episodes that precede it (wrapping around). E.g. viewing ep 3 of 9 → [3, 4, 5, 6, 7, 8, 9, 1, 2]

Returns:
Type: 
void

(static) onSeasonsLoaded() → {void}

onSeasonsLoaded: Build "Seasons" row then chain to People (Series only)

Returns:
Type: 
void

(static) onSeriesLoaded() → {void}

Returns:
Type: 
void

(static) onShowsLoaded() → {void}

Returns:
Type: 
void

(static) onSpecialFeaturesLoaded() → {dynamic}

Returns:
Type: 
dynamic

(static) populateRow(rowRef, title, items, rowHeight) → {object}

populateRow: Reuse an existing row ContentNode (clearing its children) or create a new one. Creating appends the row to m.top.content at the current end — correct since the async chain fires in display order. m.rowHeights is reset at chain start and rebuilt here on every call, keeping it in sync with m.top.content across refreshes where rows may appear or disappear. Returns the row for the caller to store as a named ref.

Parameters:
NameTypeDescription
rowRefobject
titlestring
itemsobject
rowHeightinteger

height for this specific row (from rowSlotSize.ROW_HEIGHT_* constants)

Returns:
Type: 
object

(static) removeRow(rowNode) → {void}

removeRow: Remove a row ContentNode from content and keep numRows in sync with content.getChildCount(). Always call this instead of m.top.content.removeChild() directly; then null the caller's ref.

Parameters:
NameTypeDescription
rowNodeobject
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 populateRow), 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