package link.roadio.riff.ui import link.roadio.riff.indexer.core.media.MediaId data class BrowserItem( val id: String, val label: String, val kind: BrowserKind, val icon: String? = null, val playable: Boolean = false, val enabled: Boolean = true, val mediaId: MediaId? = null, val artist: String = "", val album: String = "", /** Exact SAF provider filename; never inferred from title or parsed for numbers. */ val sourceFileName: String = "", val fragment: Boolean = false, val discNumber: Long? = null, val trackNumber: Long? = null, /** Stable reaction identity; folder occurrences may have distinct row IDs. */ val reactionKey: String = id, val sourceBindingId: Long? = null, val playbackSource: PlaybackSourceRef? = null, val playlistId: Long? = null, val playlistRevisionId: Long? = null, val playlistOccurrenceId: Long? = null, val bookmarks: Boolean = false, val bookmarkMarkId: Long? = null, val bookmarkOrdinal: Int? = null, val bookmarkPositionUs: Long? = null, /** Effective Book classification after profile overrides and AlbumGroup propagation. */ val audiobook: Boolean = false, /** Automatic MDIA Q106833 result before profile overrides. */ val automaticAudiobook: Boolean = false, /** True only when Ban/Dislike/Like may affect every media member represented by this row. */ val aiReactionEligible: Boolean = true, val albumGroupId: Long? = null, val tocMarkersMs: List = emptyList(), val children: List = emptyList(), val ignoreLeadingArticles: Boolean = false, val genreId: Long? = null, /** Catalog display decoration must not replace the original search/sort input. */ val comparisonNameOverride: String? = null, val catalog: BrowserCatalog? = null, ) { internal val comparisonName: String get() = comparisonNameOverride ?: label internal val comparisonLabel: String = browseComparisonName(comparisonName, ignoreLeadingArticles) } // AI-INTENT: Playlist containers and frozen Bookmarks share the body-and-More row regardless of // member classification; eligible Music track occurrences still use the reaction tier. // Authority: https://wiki.271.pics/Riff/LATEST/hierarchy-screen-scope-and-shared-implementation#rows-and-actions internal val BrowserItem.hierarchyUsesActionTier: Boolean get() = !bookmarks && kind != BrowserKind.PLAYLIST && aiReactionEligible enum class PlaylistNameOperation { CREATE, RENAME }