Members

(static, constant) ESTIMATED_BUTTON_ROW_HEIGHT_PX

First-frame estimate for the button row's total rendered height. Used by anchorDateLabel() before boundingRect() has settled (it reports height=0 during initial render). Observed to land around 130 px for the typical 2-line-label icon button. A later renderTracking callback replaces this with the real measured height once layout completes.

Default Value
  • 130

(static, constant) ITEM_DETAILS_EXTRAS_PADDING

Gap between bottom of itemInfoRows and top of extras pane when extras are open

Default Value
  • 24

(static, constant) LOGO_MAX_DISPLAY_HEIGHT

Maximum display height for non-Person primary images — prevents portrait posters from extending above the metadata rows. Person photos are exempt because their info rows are short and don't reach the right edge where the photo sits.

Default Value
  • 336

(static, constant) LOGO_MAX_DISPLAY_WIDTH

Maximum display width for the logo image — prevents very wide/flat logos from overlapping buttons

Default Value
  • 500

(static, constant) LOGO_MIN_DISPLAY_HEIGHT

Minimum display height for the logo image — images too small are scaled up (aspect ratio preserved).

Default Value
  • 212

Methods

(static) SetDefaultAudioTrack(mediaStreams) → {void}

SetDefaultAudioTrack: Auto-select the best audio stream based on user language prefs, storing the result on m.top.selectedAudioStreamIndex. The dropdown trigger label is refreshed separately by applyDropdown() using the same index.

Parameters:
NameTypeDescription
mediaStreamsobject
Returns:
Type: 
void

(static) activateExtras() → {void}

Returns:
Type: 
void

(static) anchorDateLabel() → {integer}

anchorDateLabel: Derive the date label's Y position from the button group's position. Returns dateLabelY so callers (e.g. logo positioning) can use it without duplicating the math. Safe to call multiple times — idempotent, and safe to call BEFORE the button group has finished laying out: falls back to the group's fixed translation + ESTIMATED_BUTTON_ROW_HEIGHT_PX so the label never lands off-screen. A later renderTracking callback refines the position once the real rendered height is known.

Returns:

dateLabelY — the Y coordinate used for the date label

Type: 
integer

(static) applyDropdown(dropdown, items, selectedId, applicable) → {void}

applyDropdown: Push items + selection into a single TrackDropdown. Hides the slot when the track type isn't applicable (keeps layout order stable for the other two slots).

Parameters:
NameTypeDescription
dropdownobject
itemsobject
selectedIdstring
applicableboolean
Returns:
Type: 
void

(static) buildAudioDropdownItems(streams) → {object}

buildAudioDropdownItems: Convert the MediaStreams array into dropdown items for audio. Item id is the stringified server-side stream index, matching the ItemDetails contract that selectedAudioStreamIndex is an integer spanning all stream types.

Parameters:
NameTypeDescription
streamsobject
Returns:
Type: 
object

(static) buildSubtitleDropdownItems(streams) → {object}

buildSubtitleDropdownItems: Convert the MediaStreams array into dropdown items for subtitles.

Two shapes are returned depending on whether the item actually has subtitle streams: No subtitle streams at all → [{ id:"-1", title:"None" }]. Rendered as a static non-interactive slot so the "Subtitles" title row still shows and the layout stays consistent across items. "None" (not "Off") because the user has no choice to make — subtitles simply don't exist on this item. One or more subtitle streams → [{ id:"-1", title:"Off" }, ...tracks]. The "Off" entry lets the user disable subtitles when tracks ARE present. id "-1" is the SubtitleSelection.NONE sentinel used by m.top.selectedSubtitleStreamIndex.

Parameters:
NameTypeDescription
streamsobject
Returns:
Type: 
object

(static) buildVideoDropdownItems(mediaSources) → {object}

buildVideoDropdownItems: Convert MediaSources into dropdown items. "Video" here is the MediaSource, not a stream — it's the user-facing alternate-version selector (e.g. "1080p H264" vs "4K HEVC HDR10").

Parameters:
NameTypeDescription
mediaSourcesobject
Returns:
Type: 
object

(static) createDividerNode(dividerId) → {object}

createDividerNode: Create a bullet divider node for separating info items

Parameters:
NameTypeDescription
dividerIdstring

Unique ID for the divider

Returns:

Configured divider node

Type: 
object

(static) createEndsAtNode() → {void}

createEndsAtNode: Build an "Ends at" time label with AM/PM support and store it on m.endsAtNode for dynamic clock updates. Used by types with runTimeTicks-based durations.

Returns:
Type: 
void

(static) createInfoLabel(labelId) → {object}

createInfoLabel: Create a bold label node for the info rows

Parameters:
NameTypeDescription
labelIdstring

Unique ID for the label

Returns:

Configured LabelPrimaryMedium node

Type: 
object

(static) createTimeLabel(labelId, timeText, periodText) → {object}

createTimeLabel: Creates a time label with an optional lowercase am/pm suffix. In 24h mode returns a single label; in 12h mode appends the period to the time text.

Parameters:
NameTypeDescription
labelIdstring
timeTextstring
periodTextstring
Returns:
Type: 
object

(static) deactivateExtras() → {void}

Returns:
Type: 
void

(static) displayDirectorGenreNode(node) → {void}

displayDirectorGenreNode: Add a node to the second info row, prepending a bullet divider if needed

Parameters:
NameTypeDescription
nodeobject
Returns:
Type: 
void

(static) displayInfoNode(node) → {void}

displayInfoNode: Add a node to the info group, prepending a bullet divider if needed

Parameters:
NameTypeDescription
nodeobject
Returns:
Type: 
void

(static) firstInteractiveDropdown() → {object}

firstInteractiveDropdown: Returns the first visible, interactive TrackDropdown in left-to-right order, or invalid if none exist.

Returns:
Type: 
object

(static) focusButtonGroupChild() → {void}

focusButtonGroupChild: Focus the button at the current buttonFocused index directly

Returns:
Type: 
void

(static) focusInteractiveDropdown(candidates) → {void}

focusInteractiveDropdown: Walks the given candidate list and focuses the first dropdown that is interactive AND visible. The candidate order encodes both direction and wrap behavior; the currently-focused dropdown is always last so the nav falls back to it if nothing else is interactive (effectively: stay put).

Parameters:
NameTypeDescription
candidatesobject
Returns:
Type: 
void

(static) getButtonIndex(buttonId) → {integer}

getButtonIndex: Find the index of a button by ID in the button group

Parameters:
NameTypeDescription
buttonIdstring

The id of the button to find

Returns:

The index of the button, or -1 if not found

Type: 
integer

(static) getHistory() → {string}

getHistory: Format the air schedule/status string for a Series item Example output: "ABC" or "Fridays at 9:30 PM on NBC"

Returns:
Type: 
string

(static) getResumeButtonText(item) → {string}

getResumeButtonText: Return "Resume S{n}E{n}" when season and episode numbers are known, otherwise fall back to plain "Resume".

Parameters:
NameTypeDescription
itemobject

nextUpEpisode JellyfinBaseItem node

Returns:

Localised button label

Type: 
string

(static) getRuntime() → {integer}

Returns:
Type: 
integer

(static) getStreamsForSelectedSource(mediaSources) → {object}

getStreamsForSelectedSource: Pull the MediaStreams array from whichever media source matches m.top.selectedVideoStreamId. Falls back to mediaSources[0] when the selected id isn't found (e.g. first load before selection).

Parameters:
NameTypeDescription
mediaSourcesobject
Returns:
Type: 
object

(static) init() → {void}

Returns:
Type: 
void

(static) manageResumeButton() → {void}

manageResumeButton: Add or remove Resume button based on playback position (non-Series types)

Returns:
Type: 
void

(static) onAudioDropdownFocusExit() → {void}

Returns:
Type: 
void

(static) onAudioDropdownSelection() → {void}

Audio dropdown selection: updates selectedAudioStreamIndex and re-seeds the subtitle auto-selection (Smart mode depends on which audio is playing). If the user has already manually overridden the subtitle, we leave it alone.

Returns:
Type: 
void

(static) onButtonGrpRendered() → {void}

onButtonGrpRendered: Fires after the render thread settles the button group layout. Re-anchors the date label and repositions the logo. The track dropdown cluster lives inside itemDetails LayoutGroup and is positioned automatically by the layout engine, so it doesn't need to be re-placed here.

Returns:
Type: 
void

(static) onClockMinuteChanged() → {void}

onClockMinuteChanged: Dynamically update "Ends At" time when overhang clock minute changes.

Returns:
Type: 
void

(static) onDestroy() → {void}

onDestroy: Full teardown releasing all resources before component removal Called automatically by SceneManager.popScene() / clearScenes()

Returns:
Type: 
void

(static) onDetailsLoaded() → {void}

Callback when initial item details metadata arrives from the task

Returns:
Type: 
void

(static) onDropdownRequestDown() → {void}

DOWN from any dropdown returns focus to the button group.

Returns:
Type: 
void

(static) onDropdownRequestUp() → {void}

Dropdown navigation: UP from any dropdown goes to description when in layout, else is consumed (no-op). parent-level UP handling reused so we don't have three identical handlers.

Returns:
Type: 
void

(static) onExtrasTargetTranslationYChanged() → {void}

onExtrasTargetTranslationYChanged: Animate the RowList translation to the new target. Fired early by onKeyEvent in ExtrasRowList (at key press) so the animation runs in parallel with the RowList's floatingFocus animation, and confirmed by onRowItemFocused after focus lands.

Returns:
Type: 
void

(static) onFirstEpisodeLoaded() → {void}

onFirstEpisodeLoaded: Start playback of first episode for Series Play button

Returns:
Type: 
void

(static) onItemContentChanged() → {void}

Returns:
Type: 
void

(static) onItemDetailsRendered() → {void}

Returns:
Type: 
void

(static) onItemIdChanged() → {void}

Triggered when CreateItemDetailsGroup sets itemId — kicks off async data load

Returns:
Type: 
void

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

Parameters:
NameTypeDescription
keystring
pressboolean
Returns:
Type: 
boolean

(static) onLogoLoadStatusChanged() → {void}

onLogoLoadStatusChanged: Position logo to the right, with its bottom just above the date label. When the date label is hidden, anchors to where the date label would be. Images smaller than LOGO_MIN_DISPLAY_HEIGHT are scaled up while preserving aspect ratio, unless the logo is very wide/flat, in which case LOGO_MAX_DISPLAY_WIDTH takes precedence.

Returns:
Type: 
void

(static) onLyricsLoaded() → {void}

onLyricsLoaded: Show lyrics in the description area once the async fetch completes (Audio only)

Returns:
Type: 
void

(static) onNextUpEpisodeChanged() → {void}

nextUpEpisodeChanged: For Series — create/remove Resume button based on nextUpEpisode. On first load, replaces the LoadingButton placeholder from setupButtons(). On refresh, inserts/updates/removes the Resume button directly.

Returns:
Type: 
void

(static) onPersonHasMediaChanged() → {void}

onPersonHasMediaChanged: Show or hide the Shuffle button once the person extras chain completes. On first load, replaces the LoadingButton placeholder from setupButtons(). On refresh, inserts/removes the Shuffle button directly. Fires via alwaysNotify so it triggers even when personHasMedia stays the same value (e.g. on refresh).

Returns:
Type: 
void

(static) onPlaylistContentKindChanged() → {void}

onPlaylistContentKindChanged: Drives the Watched button and item-count label based on the confirmed content kind of the playlist ("video" / "audio" / "mixed" / "unknown"). Fires via alwaysNotify so it triggers even when the kind is unchanged (e.g. on refresh).

Watched button: only shown for "video" (has at least one video-type item). Label: "Tracks" only when positively confirmed "audio" (all items are Audio type). All other kinds — including "unknown" (load failure) and "mixed" — stay "Items".

Returns:
Type: 
void

(static) onRefreshDetailsLoaded() → {void}

Callback when refreshed item details metadata arrives

Returns:
Type: 
void

(static) onRefreshExtrasData() → {void}

onRefreshExtrasData: Reload all extras rows when the user explicitly presses Refresh.

Returns:
Type: 
void

(static) onRefreshItemDetailsData() → {void}

Triggered by refreshItemDetailsData field toggle (return from playback, refresh button). Refreshes silently in the background — no spinner, no input blocking. The UI already has data from the initial load so the user can navigate freely.

Returns:
Type: 
void

(static) onRefreshResumeData() → {void}

Triggered by refreshResumeData field toggle (watched toggle on Series). Re-fetches ONLY the next-up/resume episode — no full rebuild, no setupButtons(). The existing onNextUpEpisodeChanged() handles adding/removing/updating the resume button.

Returns:
Type: 
void

(static) onScreenHidden() → {void}

Returns:
Type: 
void

(static) onScreenShown() → {void}

onScreenShown: Callback when view is presented on screen

Returns:
Type: 
void

(static) onSeasonSeriesDataLoaded() → {void}

onSeasonSeriesDataLoaded: Update Season info rows and logo with parent series metadata

Returns:
Type: 
void

(static) onSeriesResumeLoaded() → {void}

onSeriesResumeLoaded: Set nextUpEpisode from seriesResume task result to show/hide the Resume button

Returns:
Type: 
void

(static) onSubtitleDropdownFocusExit() → {void}

Returns:
Type: 
void

(static) onSubtitleDropdownSelection() → {void}

Subtitle dropdown selection: marks user override so subsequent audio changes don't clobber the pick, then stores the new index. Action "-1" = Off.

Returns:
Type: 
void

(static) onTrackDropdownFocusChanged() → {void}

onTrackDropdownFocusChanged: Observer wired to each TrackDropdown's focusedChild. Remembers the last dropdown that held focus so the UP-from-buttons handler can restore the previous slot on re-entry instead of always defaulting to video.

Returns:
Type: 
void

(static) onTrackDropdownMenuOpenChanged() → {void}

onTrackDropdownMenuOpenChanged: Observer wired to each TrackDropdown's menuOpen. Toggles the full-screen dimmer iff ANY dropdown's menu is currently open. The trackCluster (titles + triggers + the open menu itself) renders ABOVE the dimmer in XML sibling order, so only the screen content BEHIND the cluster dims — category titles and trigger labels stay full-brightness as the user's "you are here" cue while picking a track.

Returns:
Type: 
void

(static) onTrailerAvailableChanged() → {void}

Returns:
Type: 
void

(static) onTrailerCheckDone() → {void}

Callback when trailer availability check completes

Returns:
Type: 
void

(static) onVideoDropdownFocusExit() → {void}

LEFT/RIGHT between dropdowns — each dropdown has its own exit handler so we know which slot we came from and can target the correct neighbor, skipping non-interactive slots.

Returns:
Type: 
void

(static) onVideoDropdownSelection() → {void}

Video dropdown selection fires when the user picks a different MediaSource (alternate version). We swap in the new source's streams, re-run audio auto-select, and rebuild the audio/subtitle dropdowns against the new source. Focus stays on the video dropdown.

Returns:
Type: 
void

(static) pickTrackDropdownFromButtons() → {object}

pickTrackDropdownFromButtons: Chooses which TrackDropdown to focus when UP is pressed from the button group. Ignores m.lastFocusedDropdown by design — UP-from-buttons should ALWAYS land on the dropdown visually above the currently focused button, not on wherever the user was last time. Each slot spans 2 buttons: slot 1 sits above buttons [0,1], slot 2 above [2,3], slot 3 above [4,5,...]. Widens outward to the nearest interactive slot if the preferred one is static/hidden.

CRITICAL: guards on m.trackCluster.visible — when the item type has no media tracks (Series/Person/BoxSet/etc.), the cluster is hidden but the individual dropdown nodes may still carry stale visible=true / isInteractive=true from a previously-loaded item. Without this guard, focus would move to an invisible stale dropdown when the user presses UP on those item types.

Returns:
Type: 
object

(static) pickTrackDropdownFromDescription() → {object}

pickTrackDropdownFromDescription: Chooses which TrackDropdown to focus when DOWN is pressed from the description. Restores m.lastFocusedDropdown if still usable so the user returns to wherever they were before moving up. Falls back to the leftmost interactive dropdown (video → audio → subtitles) for the first-ever entry. Also guards on m.trackCluster.visible to match pickTrackDropdownFromButtons above.

Returns:
Type: 
object

(static) populateDescriptionGroup() → {void}

populateDescriptionGroup: Set FocusableOverview text with tagline and overview

Returns:
Type: 
void

(static) populateInfoGroup() → {void}

populateInfoGroup: Dispatch to type-specific info row builder

Returns:
Type: 
void

(static) populateInfoGroupAudio(item, userSettings) → {void}

populateInfoGroupAudio: Info rows for Audio (song) Row 1: Track N · Disc N (only when disc > 1) · Runtime · Ends At Row 2: Album name · Album artist

Parameters:
NameTypeDescription
itemobject
userSettingsobject
Returns:
Type: 
void

(static) populateInfoGroupBoxSet(item, userSettings) → {void}

populateInfoGroupBoxSet: Info rows for BoxSet (movie collection) Row 1: Year · Official Rating · Community Rating · N Movies Row 2: Genres · Studio

Parameters:
NameTypeDescription
itemobject
userSettingsobject
Returns:
Type: 
void

(static) populateInfoGroupEpisode(item, userSettings) → {void}

populateInfoGroupEpisode: Info rows for Episode Row 1: Air Date · Official Rating · Runtime · Ends At Row 2: Series name + "S{n}E{n}"

Parameters:
NameTypeDescription
itemobject
userSettingsobject
Returns:
Type: 
void

(static) populateInfoGroupMovie(item, userSettings) → {void}

populateInfoGroupMovie: Info rows for Movie, Video, Recording Row 1: Year · Official Rating · Community Rating · Critic Rating · Runtime · Ends At Row 2: Genres · Director(s)

Parameters:
NameTypeDescription
itemobject
userSettingsobject
Returns:
Type: 
void

(static) populateInfoGroupMusicAlbum(item, userSettings) → {void}

populateInfoGroupMusicAlbum: Info rows for MusicAlbum Row 1: Year · Runtime · Ends At Row 2: Album Artist · Genres · N Tracks

Parameters:
NameTypeDescription
itemobject
userSettingsobject
Returns:
Type: 
void

(static) populateInfoGroupMusicArtist(item) → {void}

populateInfoGroupMusicArtist: Info rows for MusicArtist Row 1: N Albums · N Songs · Year Row 2: Genres

Parameters:
NameTypeDescription
itemobject
Returns:
Type: 
void

(static) populateInfoGroupMusicVideo(item, userSettings) → {void}

populateInfoGroupMusicVideo: Info rows for MusicVideo Row 1: Year · Official Rating · Runtime · Ends At Row 2: Genres · Artist(s)

Parameters:
NameTypeDescription
itemobject
userSettingsobject
Returns:
Type: 
void

(static) populateInfoGroupPerson(item) → {void}

populateInfoGroupPerson: Info rows for Person Row 1: {birthDate} [- {deathDate}] · {n} years old Living: Jan 1, 1980 · 45 years old Deceased: Jan 1, 1920 - Dec 31, 1980 · 60 years old Row 2: {n} Movie(s) [· {n} Episode(s)] — omitted entirely if both counts are 0

Parameters:
NameTypeDescription
itemobject
Returns:
Type: 
void

(static) populateInfoGroupPhoto(item) → {void}

populateInfoGroupPhoto: Info rows for Photo Row 1: Resolution ("WxH") · Camera ("Make Model") · Production Year Row 2: Album name (if present)

Parameters:
NameTypeDescription
itemobject
Returns:
Type: 
void

(static) populateInfoGroupPhotoAlbum(item) → {void}

populateInfoGroupPhotoAlbum: Info rows for PhotoAlbum Row 1: Photo count

Parameters:
NameTypeDescription
itemobject
Returns:
Type: 
void

(static) populateInfoGroupPlaylist(item, userSettings) → {void}

populateInfoGroupPlaylist: Info rows for Playlist Row 1: N Items · Runtime · Ends At Row 2: Genres The item count label starts as "Items" and is swapped to "Tracks" by onPlaylistContentKindChanged() once the extras chain confirms the playlist is all-audio.

Parameters:
NameTypeDescription
itemobject
userSettingsobject
Returns:
Type: 
void

(static) populateInfoGroupProgram(item, userSettings) → {void}

populateInfoGroupProgram: Info rows for Program (Live TV EPG entry) Row 1: Year · CH X - ChanName · OfficialRating · CommunityRating · S#E# · Premiere/Repeat · Runtime · BroadcastTime · Ends At Row 2: Genres (or category flags)

Parameters:
NameTypeDescription
itemobject
userSettingsobject
Returns:
Type: 
void

(static) populateInfoGroupRecording(item, userSettings) → {void}

populateInfoGroupRecording: Info rows for Recording (Live TV recorded content) Row 1: PremiereYear · OfficialRating · CommunityRating · S#E# · Runtime · Ends At · CH X - ChanName · Recorded: Date Row 2: Genres

Parameters:
NameTypeDescription
itemobject
userSettingsobject
Returns:
Type: 
void

(static) populateInfoGroupSeason(item, userSettings) → {void}

populateInfoGroupSeason: Info rows for Season Row 1: Year · Official Rating (series) · Avg episode runtime (series) · Ends At Row 2: Series name · Episode count · Studio

Parameters:
NameTypeDescription
itemobject
userSettingsobject
Returns:
Type: 
void

(static) populateInfoGroupSeries(item, userSettings) → {void}

populateInfoGroupSeries: Info rows for Series Row 1: Year Range · Official Rating · Community Rating · Runtime · Ends At (only when avg episode runtime is available) Row 2: Genres · Air schedule/Status

Parameters:
NameTypeDescription
itemobject
userSettingsobject
Returns:
Type: 
void

(static) populateInfoGroupTvChannel(item, userSettings) → {void}

populateInfoGroupTvChannel: Info rows for TvChannel (Live TV) Displays metadata from the current program (the channel is a vessel for what's airing). Row 1: CH N · OfficialRating · CommunityRating · S#E# · Program Name · Runtime · BroadcastTime · Ends At Row 2: Genres (or category flags)

Parameters:
NameTypeDescription
itemobject
userSettingsobject
Returns:
Type: 
void

(static) populateTrackDropdowns(mediaSources, allStreams, itemType) → {void}

populateTrackDropdowns: Build the Video/Audio/Subtitle dropdown items from the current media source list and stream list for the given item type, then toggle the cluster + title row visibility. Seeds m.top.selectedSubtitleStreamIndex from findDefaultSubtitleStreamIndex() on first load so the initial trigger label reflects what playback will actually use.

Parameters:
NameTypeDescription
mediaSourcesobject

Array of MediaSource objects (may be empty)

allStreamsobject

MediaStreams from the selected source (video/audio/subs mixed)

itemTypestring

The item type string (drives which slots apply)

Returns:
Type: 
void

(static) removeResumeButtonWithFocus(resumeButton) → {void}

removeResumeButtonWithFocus: Remove resume button while preserving focus position

Parameters:
NameTypeDescription
resumeButtonobject
Returns:
Type: 
void

(static) removeResumeLoadingButton() → {void}

removeResumeLoadingButton: Remove the resume LoadingButton placeholder if still present. Called when async data confirms no resume episode exists (nextUpEpisode stays invalid).

Returns:
Type: 
void

(static) round(f) → {integer}

Parameters:
NameTypeDescription
ffloat
Returns:
Type: 
integer

(static) setDateAdded(item) → {void}

setDateAdded: Set date added label text and position at bottom right corner

Parameters:
NameTypeDescription
itemobject

JellyfinBaseItem node

Returns:
Type: 
void

(static) setDescriptionInLayout(shouldShow) → {void}

setDescriptionInLayout: Add or remove itemDescription from the itemDetails LayoutGroup. Invisible nodes still take up space in RSG LayoutGroups, so reparenting is required to truly eliminate spacing when there is no description text.

Parameters:
NameTypeDescription
shouldShowboolean
Returns:
Type: 
void

(static) setFieldText(field, value) → {void}

Parameters:
NameTypeDescription
fielddynamic
valuedynamic
Returns:
Type: 
void

setItemLogo: Set the item logo image URL if available. Fallback chains by type — every chain ends in a typed placeholder via getPlaceholderImagePath() so the logo slot never goes blank, matching the pattern Person and MusicArtist always used:

  • Movie/Series/BoxSet: Logo → primaryImageTag (poster, compact size) → placeholder
  • Episode/Season/Recording: primaryImageTag → parentLogoImageTag (series logo) → seriesPrimaryImageTag → placeholder
  • Video/MusicVideo: primaryImageTag → placeholder
  • MusicAlbum / Playlist / Photo / PhotoAlbum / TvChannel: primaryImageTag → placeholder
  • Program: primaryImageTag → channel logo → placeholder
  • Audio: primaryImageTag → album art → placeholder
  • Person / MusicArtist: primaryImageTag (portrait) → placeholder
Parameters:
NameTypeDescription
itemobject

JellyfinBaseItem node

Returns:
Type: 
void

(static) setTracksInLayout(shouldShow) → {void}

setTracksInLayout: Add or remove the 62px itemTracks spacer from the itemDetails LayoutGroup. When a track cluster is applicable to the current item, the spacer stays in the layout and pushes description bottom up to y=701 so the trackCluster sibling can sit at y=713 with 12px breathing pad above and 18px below between the description and the button group. For item types without any media tracks (Series/Person/etc.), the spacer is removed and description bottom drops back to y=775 (matching main's behavior — no cluster, no padding, no regression).

Parameters:
NameTypeDescription
shouldShowboolean
Returns:
Type: 
void

(static) setupButtons(item) → {void}

setupButtons: Build the complete button set for the given item type. Clears all existing buttons and adds the correct sync buttons in order. Loading placeholders are added for async buttons (Series Resume, Person Shuffle) so the button row renders at its final width immediately. The async handlers replace or remove the placeholders when data arrives. Called on every itemContentChanged — the button list is rebuilt from scratch each time.

Parameters:
NameTypeDescription
itemobject
Returns:
Type: 
void

(static) triggerTextForSelection(items, selectedId) → {string}

triggerTextForSelection: Look up the currently-selected item's display title.

Parameters:
NameTypeDescription
itemsobject
selectedIdstring
Returns:
Type: 
string

(static) updateFavoriteButton() → {void}

Returns:
Type: 
void

(static) updateItemDetailsAnimationTarget() → {void}

updateItemDetailsAnimationTarget: Slide itemDetails so the bottom of itemInfoRows sits just above the extras pane. boundingRect() on a child returns LOCAL coords relative to the parent's translation point, so we use translation[1] (not boundingRect().y) as the screen origin. Called just-in-time from the DOWN key handler to guarantee the layout is fully settled (text wrapping complete) before measuring. Eager calculation via renderTracking races with async text layout, producing stale targets — especially for long descriptions.

Returns:
Type: 
void

(static) updateTextGradient() → {void}

Returns:
Type: 
void

(static) updateWatchedButton() → {void}

Returns:
Type: 
void