mirror of
https://github.com/oxyroid/M3UAndroid.git
synced 2025-08-06 14:59:48 +08:00
fix: xtream cannot be parse.
This commit is contained in:
@ -87,65 +87,63 @@ data class XtreamLive(
|
||||
@Serializable
|
||||
data class XtreamVod(
|
||||
@SerialName("added")
|
||||
val added: String?,
|
||||
val added: String? = null,
|
||||
@SerialName("category_id")
|
||||
val categoryId: Int?,
|
||||
val categoryId: Int? = null,
|
||||
@SerialName("container_extension")
|
||||
val containerExtension: String?,
|
||||
val containerExtension: String? = null,
|
||||
@SerialName("custom_sid")
|
||||
val customSid: String?,
|
||||
val customSid: String? = null,
|
||||
@SerialName("direct_source")
|
||||
val directSource: String?,
|
||||
val directSource: String? = null,
|
||||
@SerialName("name")
|
||||
val name: String?,
|
||||
val name: String? = null,
|
||||
@SerialName("num")
|
||||
val num: Int?,
|
||||
val num: String? = null,
|
||||
@SerialName("rating")
|
||||
val rating: String?,
|
||||
val rating: String? = null,
|
||||
@SerialName("rating_5based")
|
||||
val rating5based: Double?,
|
||||
val rating5based: String? = null,
|
||||
@SerialName("stream_icon")
|
||||
val streamIcon: String?,
|
||||
val streamIcon: String? = null,
|
||||
@SerialName("stream_id")
|
||||
val streamId: Int?,
|
||||
val streamId: Int? = null,
|
||||
@SerialName("stream_type")
|
||||
val streamType: String?
|
||||
val streamType: String? = null
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class XtreamSerial(
|
||||
@SerialName("backdrop_path")
|
||||
val backdropPath: List<String>,
|
||||
@SerialName("cast")
|
||||
val cast: String?,
|
||||
val cast: String? = null,
|
||||
@SerialName("category_id")
|
||||
val categoryId: Int?,
|
||||
val categoryId: Int? = null,
|
||||
@SerialName("cover")
|
||||
val cover: String?,
|
||||
val cover: String? = null,
|
||||
@SerialName("director")
|
||||
val director: String?,
|
||||
val director: String? = null,
|
||||
@SerialName("episode_run_time")
|
||||
val episodeRunTime: String?,
|
||||
val episodeRunTime: String? = null,
|
||||
@SerialName("genre")
|
||||
val genre: String?,
|
||||
val genre: String? = null,
|
||||
@SerialName("last_modified")
|
||||
val lastModified: String?,
|
||||
val lastModified: String? = null,
|
||||
@SerialName("name")
|
||||
val name: String?,
|
||||
val name: String? = null,
|
||||
@SerialName("num")
|
||||
val num: Int?,
|
||||
val num: String? = null,
|
||||
@SerialName("plot")
|
||||
val plot: String?,
|
||||
val plot: String? = null,
|
||||
@SerialName("rating")
|
||||
val rating: String?,
|
||||
val rating: String? = null,
|
||||
@SerialName("rating_5based")
|
||||
val rating5based: Int?,
|
||||
val rating5based: String? = null,
|
||||
@SerialName("releaseDate")
|
||||
val releaseDate: String?,
|
||||
val releaseDate: String? = null,
|
||||
@SerialName("series_id")
|
||||
val seriesId: Int?,
|
||||
val seriesId: Int? = null,
|
||||
@SerialName("youtube_trailer")
|
||||
val youtubeTrailer: String?
|
||||
val youtubeTrailer: String? = null
|
||||
)
|
||||
|
||||
fun XtreamLive.toStream(
|
||||
|
@ -6,11 +6,11 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
data class XtreamStreamInfo(
|
||||
@SerialName("episodes")
|
||||
val episodes: Map<Int, List<Episode>> = emptyMap(),
|
||||
val episodes: Map<String, List<Episode>> = emptyMap(),
|
||||
@SerialName("info")
|
||||
val info: Info?,
|
||||
@SerialName("seasons")
|
||||
val seasons: List<String> = emptyList()
|
||||
// @SerialName("seasons")
|
||||
// val seasons: List<String?> = emptyList()
|
||||
) {
|
||||
@Serializable
|
||||
data class Episode(
|
||||
@ -23,13 +23,13 @@ data class XtreamStreamInfo(
|
||||
@SerialName("direct_source")
|
||||
val directSource: String?,
|
||||
@SerialName("episode_num")
|
||||
val episodeNum: Int?,
|
||||
val episodeNum: String?,
|
||||
@SerialName("id")
|
||||
val id: String?,
|
||||
@SerialName("info")
|
||||
val info: Info?,
|
||||
@SerialName("season")
|
||||
val season: Int?,
|
||||
val season: String?,
|
||||
@SerialName("title")
|
||||
val title: String?
|
||||
) {
|
||||
@ -38,11 +38,11 @@ data class XtreamStreamInfo(
|
||||
@SerialName("audio")
|
||||
val audio: Audio?,
|
||||
@SerialName("bitrate")
|
||||
val bitrate: Int?,
|
||||
val bitrate: String?,
|
||||
@SerialName("duration")
|
||||
val duration: String?,
|
||||
@SerialName("duration_secs")
|
||||
val durationSecs: Int?,
|
||||
val durationSecs: String?,
|
||||
@SerialName("video")
|
||||
val video: Video?
|
||||
) {
|
||||
@ -51,9 +51,9 @@ data class XtreamStreamInfo(
|
||||
@SerialName("avg_frame_rate")
|
||||
val avgFrameRate: String?,
|
||||
@SerialName("bits_per_sample")
|
||||
val bitsPerSample: Int?,
|
||||
val bitsPerSample: String?,
|
||||
@SerialName("channels")
|
||||
val channels: Int?,
|
||||
val channels: String?,
|
||||
@SerialName("codec_long_name")
|
||||
val codecLongName: String?,
|
||||
@SerialName("codec_name")
|
||||
@ -71,7 +71,7 @@ data class XtreamStreamInfo(
|
||||
@SerialName("dmix_mode")
|
||||
val dmixMode: String?,
|
||||
@SerialName("index")
|
||||
val index: Int?,
|
||||
val index: String?,
|
||||
@SerialName("loro_cmixlev")
|
||||
val loroCmixlev: String?,
|
||||
@SerialName("loro_surmixlev")
|
||||
@ -87,7 +87,7 @@ data class XtreamStreamInfo(
|
||||
@SerialName("sample_rate")
|
||||
val sampleRate: String?,
|
||||
@SerialName("start_pts")
|
||||
val startPts: Int?,
|
||||
val startPts: String?,
|
||||
@SerialName("start_time")
|
||||
val startTime: String?,
|
||||
@SerialName("tags")
|
||||
@ -117,9 +117,9 @@ data class XtreamStreamInfo(
|
||||
@SerialName("codec_type")
|
||||
val codecType: String?,
|
||||
@SerialName("coded_height")
|
||||
val codedHeight: Int?,
|
||||
val codedHeight: String?,
|
||||
@SerialName("coded_width")
|
||||
val codedWidth: Int?,
|
||||
val codedWidth: String?,
|
||||
@SerialName("display_aspect_ratio")
|
||||
val displayAspectRatio: String?,
|
||||
@SerialName("disposition")
|
||||
@ -127,15 +127,15 @@ data class XtreamStreamInfo(
|
||||
@SerialName("field_order")
|
||||
val fieldOrder: String?,
|
||||
@SerialName("has_b_frames")
|
||||
val hasBFrames: Int?,
|
||||
val hasBFrames: String?,
|
||||
@SerialName("height")
|
||||
val height: Int?,
|
||||
val height: String?,
|
||||
@SerialName("index")
|
||||
val index: Int?,
|
||||
val index: String?,
|
||||
@SerialName("is_avc")
|
||||
val isAvc: Boolean = false,
|
||||
@SerialName("level")
|
||||
val level: Int?,
|
||||
val level: String?,
|
||||
@SerialName("nal_length_size")
|
||||
val nalLengthSize: String?,
|
||||
@SerialName("pix_fmt")
|
||||
@ -145,11 +145,11 @@ data class XtreamStreamInfo(
|
||||
@SerialName("r_frame_rate")
|
||||
val rFrameRate: String?,
|
||||
@SerialName("refs")
|
||||
val refs: Int?,
|
||||
val refs: String?,
|
||||
@SerialName("sample_aspect_ratio")
|
||||
val sampleAspectRatio: String?,
|
||||
@SerialName("start_pts")
|
||||
val startPts: Int?,
|
||||
val startPts: String?,
|
||||
@SerialName("start_time")
|
||||
val startTime: String?,
|
||||
@SerialName("tags")
|
||||
@ -157,35 +157,35 @@ data class XtreamStreamInfo(
|
||||
@SerialName("time_base")
|
||||
val timeBase: String?,
|
||||
@SerialName("width")
|
||||
val width: Int?
|
||||
val width: String?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Disposition(
|
||||
@SerialName("attached_pic")
|
||||
val attachedPic: Int?,
|
||||
val attachedPic: String?,
|
||||
@SerialName("clean_effects")
|
||||
val cleanEffects: Int?,
|
||||
val cleanEffects: String?,
|
||||
@SerialName("comment")
|
||||
val comment: Int?,
|
||||
val comment: String?,
|
||||
@SerialName("default")
|
||||
val default: Int?,
|
||||
val default: String?,
|
||||
@SerialName("dub")
|
||||
val dub: Int?,
|
||||
val dub: String?,
|
||||
@SerialName("forced")
|
||||
val forced: Int?,
|
||||
val forced: String?,
|
||||
@SerialName("hearing_impaired")
|
||||
val hearingImpaired: Int?,
|
||||
val hearingImpaired: String?,
|
||||
@SerialName("karaoke")
|
||||
val karaoke: Int?,
|
||||
val karaoke: String?,
|
||||
@SerialName("lyrics")
|
||||
val lyrics: Int?,
|
||||
val lyrics: String?,
|
||||
@SerialName("original")
|
||||
val original: Int?,
|
||||
val original: String?,
|
||||
@SerialName("timed_thumbnails")
|
||||
val timedThumbnails: Int?,
|
||||
val timedThumbnails: String?,
|
||||
@SerialName("visual_impaired")
|
||||
val visualImpaired: Int?
|
||||
val visualImpaired: String?
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -215,7 +215,7 @@ data class XtreamStreamInfo(
|
||||
@SerialName("rating")
|
||||
val rating: String?,
|
||||
@SerialName("rating_5based")
|
||||
val rating5based: Int?,
|
||||
val rating5based: String?,
|
||||
@SerialName("releaseDate")
|
||||
val releaseDate: String?,
|
||||
@SerialName("youtube_trailer")
|
||||
|
@ -13,6 +13,9 @@ import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface StreamDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertOrReplace(stream: Stream)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertOrReplaceAll(vararg streams: Stream)
|
||||
|
||||
|
@ -32,6 +32,7 @@ internal class XtreamParserImpl @Inject constructor(
|
||||
private val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
explicitNulls = false
|
||||
isLenient = true
|
||||
}
|
||||
|
||||
override suspend fun execute(
|
||||
@ -87,19 +88,25 @@ internal class XtreamParserImpl @Inject constructor(
|
||||
val port = info.serverInfo.port?.toIntOrNull()
|
||||
val httpsPort = info.serverInfo.httpsPort?.toIntOrNull()
|
||||
|
||||
val lives: List<XtreamLive> = if (requiredLives) newCall(liveStreamsUrl) ?: emptyList() else emptyList()
|
||||
val lives: List<XtreamLive> =
|
||||
if (requiredLives) newCall(liveStreamsUrl) ?: emptyList() else emptyList()
|
||||
currentCount += lives.size
|
||||
callback(currentCount, -1)
|
||||
val vods: List<XtreamVod> = if (requiredVods) newCall(vodStreamsUrl) ?: emptyList() else emptyList()
|
||||
val vods: List<XtreamVod> =
|
||||
if (requiredVods) newCall(vodStreamsUrl) ?: emptyList() else emptyList()
|
||||
currentCount += vods.size
|
||||
callback(currentCount, -1)
|
||||
val series: List<XtreamSerial> = if (requiredSeries) newCall(seriesStreamsUrl) ?: emptyList() else emptyList()
|
||||
val series: List<XtreamSerial> =
|
||||
if (requiredSeries) newCall(seriesStreamsUrl) ?: emptyList() else emptyList()
|
||||
currentCount += series.size
|
||||
callback(currentCount, -1)
|
||||
|
||||
val liveCategories: List<XtreamCategory> = if (requiredLives) newCall(liveCategoriesUrl) ?: emptyList() else emptyList()
|
||||
val vodCategories: List<XtreamCategory> = if (requiredVods) newCall(vodCategoriesUrl) ?: emptyList() else emptyList()
|
||||
val serialCategories: List<XtreamCategory> = if (requiredSeries) newCall(serialCategoriesUrl) ?: emptyList() else emptyList()
|
||||
val liveCategories: List<XtreamCategory> =
|
||||
if (requiredLives) newCall(liveCategoriesUrl) ?: emptyList() else emptyList()
|
||||
val vodCategories: List<XtreamCategory> =
|
||||
if (requiredVods) newCall(vodCategoriesUrl) ?: emptyList() else emptyList()
|
||||
val serialCategories: List<XtreamCategory> =
|
||||
if (requiredSeries) newCall(serialCategoriesUrl) ?: emptyList() else emptyList()
|
||||
|
||||
return XtreamOutput(
|
||||
lives = lives,
|
||||
|
@ -169,7 +169,7 @@ class PlaylistRepositoryImpl @Inject constructor(
|
||||
source = DataSource.Xtream
|
||||
)
|
||||
playlistDao.insertOrReplace(playlist)
|
||||
val streams = lives.map { current ->
|
||||
lives.forEach { current ->
|
||||
current.toStream(
|
||||
basicUrl = basicUrl,
|
||||
username = username,
|
||||
@ -177,17 +177,13 @@ class PlaylistRepositoryImpl @Inject constructor(
|
||||
playlistUrl = playlist.url,
|
||||
category = liveCategories.find { it.categoryId == current.categoryId }?.categoryName.orEmpty(),
|
||||
containerExtension = allowedOutputFormats.first()
|
||||
).also {
|
||||
).also { stream ->
|
||||
currentCount += 1
|
||||
callback(currentCount, total)
|
||||
streamDao.insertOrReplace(stream)
|
||||
}
|
||||
}
|
||||
streamDao.compareAndUpdate(
|
||||
strategy = pref.playlistStrategy,
|
||||
url = playlist.url,
|
||||
update = streams
|
||||
)
|
||||
logger.log("xtream: lives +[${streams.size}]")
|
||||
logger.log("xtream: lives +[${lives.size}]")
|
||||
}
|
||||
if (requiredVods) {
|
||||
val playlist = Playlist(
|
||||
@ -200,23 +196,19 @@ class PlaylistRepositoryImpl @Inject constructor(
|
||||
source = DataSource.Xtream
|
||||
)
|
||||
playlistDao.insertOrReplace(playlist)
|
||||
val streams = vods.map { current ->
|
||||
vods.forEach { current ->
|
||||
current.toStream(
|
||||
basicUrl = basicUrl,
|
||||
username = username,
|
||||
password = password,
|
||||
playlistUrl = playlist.url,
|
||||
category = vodCategories.find { it.categoryId == current.categoryId }?.categoryName.orEmpty()
|
||||
).also {
|
||||
).also { stream ->
|
||||
currentCount += 1
|
||||
callback(currentCount, total)
|
||||
streamDao.insertOrReplace(stream)
|
||||
}
|
||||
}
|
||||
streamDao.compareAndUpdate(
|
||||
strategy = pref.playlistStrategy,
|
||||
url = playlist.url,
|
||||
update = streams
|
||||
)
|
||||
logger.log("xtream: vods +[${vods.size}]")
|
||||
}
|
||||
|
||||
@ -231,12 +223,12 @@ class PlaylistRepositoryImpl @Inject constructor(
|
||||
source = DataSource.Xtream
|
||||
)
|
||||
playlistDao.insertOrReplace(playlist)
|
||||
val streams = series.flatMap { current ->
|
||||
series.forEach { current ->
|
||||
ensureActive()
|
||||
val seriesInfo = xtreamParser.getSeriesInfo(
|
||||
input = input.copy(type = DataSource.Xtream.TYPE_SERIES),
|
||||
seriesId = current.seriesId ?: return@flatMap emptyList()
|
||||
) ?: return@flatMap emptyList()
|
||||
seriesId = current.seriesId ?: return@forEach
|
||||
) ?: return@forEach
|
||||
seriesInfo.episodes.flatMap { (_, episodes) ->
|
||||
episodes.map { episode ->
|
||||
Stream(
|
||||
@ -245,19 +237,15 @@ class PlaylistRepositoryImpl @Inject constructor(
|
||||
title = current.name.orEmpty() + " " + episode.title.orEmpty(),
|
||||
cover = current.cover,
|
||||
playlistUrl = playlist.url,
|
||||
)
|
||||
).also { stream ->
|
||||
currentCount += 1
|
||||
callback(currentCount, total)
|
||||
streamDao.insertOrReplace(stream)
|
||||
}
|
||||
}
|
||||
}.also {
|
||||
currentCount += 1
|
||||
callback(currentCount, total)
|
||||
}
|
||||
}
|
||||
streamDao.compareAndUpdate(
|
||||
strategy = pref.playlistStrategy,
|
||||
url = playlist.url,
|
||||
update = streams
|
||||
)
|
||||
logger.log("xtream: series +[${streams.size}]")
|
||||
logger.log("xtream: series +[${series.size}]")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.InternalComposeApi
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@ -45,6 +46,7 @@ import com.google.accompanist.permissions.shouldShowRationale
|
||||
import com.m3u.core.architecture.pref.LocalPref
|
||||
import com.m3u.core.util.basic.title
|
||||
import com.m3u.core.wrapper.Event
|
||||
import com.m3u.data.database.model.DataSource
|
||||
import com.m3u.data.database.model.Stream
|
||||
import com.m3u.features.playlist.internal.PlaylistScreenImpl
|
||||
import com.m3u.features.playlist.internal.TvPlaylistScreenImpl
|
||||
@ -87,6 +89,14 @@ internal fun PlaylistRoute(
|
||||
val pinnedCategories by viewModel.pinnedCategories.collectAsStateWithLifecycle()
|
||||
val refreshing by viewModel.subscribingOrRefreshing.collectAsStateWithLifecycle()
|
||||
|
||||
val singleLineTitle by remember {
|
||||
derivedStateOf {
|
||||
when (playlist?.type) {
|
||||
DataSource.Xtream.TYPE_SERIES -> false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
}
|
||||
val sorts = viewModel.sorts
|
||||
val sort by viewModel.sort.collectAsStateWithLifecycle()
|
||||
|
||||
@ -179,6 +189,7 @@ internal fun PlaylistRoute(
|
||||
viewModel.onEvent(PlaylistEvent.SavePicture(it))
|
||||
},
|
||||
createShortcut = { viewModel.onEvent(PlaylistEvent.CreateShortcut(context, it)) },
|
||||
singleLineTitle = singleLineTitle,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.thenIf(!tv && pref.godMode) {
|
||||
@ -219,6 +230,7 @@ private fun PlaylistScreen(
|
||||
savePicture: (streamId: Int) -> Unit,
|
||||
createShortcut: (streamId: Int) -> Unit,
|
||||
contentPadding: PaddingValues,
|
||||
singleLineTitle: Boolean,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val helper = LocalHelper.current
|
||||
@ -270,6 +282,7 @@ private fun PlaylistScreen(
|
||||
hide = hide,
|
||||
onSavePicture = savePicture,
|
||||
createShortcut = createShortcut,
|
||||
singleLineTitle = singleLineTitle,
|
||||
modifier = modifier
|
||||
)
|
||||
} else {
|
||||
|
@ -25,6 +25,7 @@ internal fun StreamGallery(
|
||||
streams: ImmutableList<Stream>,
|
||||
zapping: Stream?,
|
||||
recently: Boolean,
|
||||
singleLineTitle: Boolean,
|
||||
onClick: (Stream) -> Unit,
|
||||
onMenu: (Stream) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
@ -41,7 +42,8 @@ internal fun StreamGallery(
|
||||
onClick = onClick,
|
||||
onMenu = onMenu,
|
||||
modifier = modifier,
|
||||
contentPadding = contentPadding
|
||||
contentPadding = contentPadding,
|
||||
singleLineTitle = singleLineTitle
|
||||
)
|
||||
}
|
||||
|
||||
@ -70,6 +72,7 @@ private fun StreamGalleryImpl(
|
||||
streams: ImmutableList<Stream>,
|
||||
zapping: Stream?,
|
||||
recently: Boolean,
|
||||
singleLineTitle: Boolean,
|
||||
onClick: (Stream) -> Unit,
|
||||
onMenu: (Stream) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
@ -97,6 +100,7 @@ private fun StreamGalleryImpl(
|
||||
onClick = { onClick(stream) },
|
||||
onLongClick = { onMenu(stream) },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
singleLineTitle = singleLineTitle
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,8 @@ internal fun StreamItem(
|
||||
zapping: Boolean,
|
||||
onClick: () -> Unit,
|
||||
onLongClick: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
modifier: Modifier = Modifier,
|
||||
singleLineTitle: Boolean = true
|
||||
) {
|
||||
when (currentUiMode()) {
|
||||
UiMode.Default -> {
|
||||
@ -65,7 +66,8 @@ internal fun StreamItem(
|
||||
zapping = zapping,
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
modifier = modifier
|
||||
modifier = modifier,
|
||||
singleLineTitle = singleLineTitle
|
||||
)
|
||||
}
|
||||
|
||||
@ -76,7 +78,8 @@ internal fun StreamItem(
|
||||
zapping = zapping,
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
modifier = modifier
|
||||
modifier = modifier,
|
||||
singleLineTitle = singleLineTitle
|
||||
)
|
||||
}
|
||||
|
||||
@ -92,6 +95,7 @@ private fun StreamItemImpl(
|
||||
onLongClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
zapping: Boolean = false,
|
||||
singleLineTitle: Boolean = true
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val spacing = LocalSpacing.current
|
||||
@ -153,7 +157,7 @@ private fun StreamItemImpl(
|
||||
text = stream.title.trim(),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
maxLines = if (singleLineTitle) 1 else Int.MAX_VALUE,
|
||||
fontWeight = FontWeight.Bold,
|
||||
)
|
||||
if (recently) {
|
||||
@ -218,6 +222,7 @@ private fun CompactStreamItem(
|
||||
onClick: () -> Unit,
|
||||
onLongClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
singleLineTitle: Boolean = true
|
||||
) {
|
||||
val spacing = LocalSpacing.current
|
||||
val favourite = stream.favourite
|
||||
@ -242,7 +247,7 @@ private fun CompactStreamItem(
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
fontSize = MaterialTheme.typography.titleSmall.fontSize,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
maxLines = if (singleLineTitle) 1 else Int.MAX_VALUE,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
},
|
||||
|
@ -95,6 +95,7 @@ internal fun PlaylistScreenImpl(
|
||||
onSavePicture: (streamId: Int) -> Unit,
|
||||
createShortcut: (streamId: Int) -> Unit,
|
||||
isAtTopState: MutableState<Boolean>,
|
||||
singleLineTitle: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
contentPadding: PaddingValues = PaddingValues()
|
||||
) {
|
||||
@ -219,6 +220,7 @@ internal fun PlaylistScreenImpl(
|
||||
streams = categories[currentPage].streams,
|
||||
zapping = zapping,
|
||||
recently = sort == Sort.RECENTLY,
|
||||
singleLineTitle = singleLineTitle,
|
||||
onClick = onStream,
|
||||
contentPadding = inner,
|
||||
onMenu = { dialogStatus = DialogStatus.Selections(it) },
|
||||
|
Reference in New Issue
Block a user