mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Update style for ktlint 1.8 (#390)
Updated `ktlint`, so lots of code style changes, no user facing changes
This commit is contained in:
parent
e9c54adaba
commit
9e7742034a
54 changed files with 577 additions and 196 deletions
|
|
@ -199,7 +199,10 @@ class MainActivity : AppCompatActivity() {
|
|||
val initialDestination =
|
||||
when {
|
||||
current != null -> Destination.Home()
|
||||
!appPreferences.signInAutomatically -> Destination.ServerList // TODO user list?
|
||||
|
||||
!appPreferences.signInAutomatically -> Destination.ServerList
|
||||
|
||||
// TODO user list?
|
||||
else -> Destination.ServerList
|
||||
}
|
||||
val backStack = rememberNavBackStack(initialDestination)
|
||||
|
|
|
|||
|
|
@ -81,15 +81,18 @@ data class BaseItem(
|
|||
} ?: Destination.MediaItem(id, type, this)
|
||||
}
|
||||
|
||||
BaseItemKind.SEASON ->
|
||||
BaseItemKind.SEASON -> {
|
||||
Destination.SeriesOverview(
|
||||
data.seriesId!!,
|
||||
BaseItemKind.SERIES,
|
||||
this,
|
||||
SeasonEpisodeIds(id, indexNumber, null, null),
|
||||
)
|
||||
}
|
||||
|
||||
else -> Destination.MediaItem(id, type, this)
|
||||
else -> {
|
||||
Destination.MediaItem(id, type, this)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ data class GetItemsFilter(
|
|||
-> null
|
||||
|
||||
FilterVideoType.BLU_RAY -> VideoType.BLU_RAY
|
||||
|
||||
FilterVideoType.DVD -> VideoType.DVD
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,12 +136,13 @@ fun chooseSubtitleStream(
|
|||
}
|
||||
}
|
||||
|
||||
SubtitlePlaybackMode.ONLY_FORCED ->
|
||||
SubtitlePlaybackMode.ONLY_FORCED -> {
|
||||
if (subtitleLanguage != null) {
|
||||
candidates.firstOrNull { it.language == subtitleLanguage && it.isForced }
|
||||
} else {
|
||||
candidates.firstOrNull { it.isForced }
|
||||
}
|
||||
}
|
||||
|
||||
SubtitlePlaybackMode.SMART -> {
|
||||
val audioLanguage = prefs.userConfig.audioLanguagePreference
|
||||
|
|
@ -161,7 +162,9 @@ fun chooseSubtitleStream(
|
|||
)
|
||||
}
|
||||
|
||||
SubtitlePlaybackMode.NONE -> null
|
||||
SubtitlePlaybackMode.NONE -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,13 +76,14 @@ class ImageUrlService
|
|||
}
|
||||
}
|
||||
|
||||
else ->
|
||||
else -> {
|
||||
getItemImageUrl(
|
||||
itemId = itemId,
|
||||
imageType = imageType,
|
||||
fillWidth = fillWidth,
|
||||
fillHeight = fillHeight,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getItemImageUrl(
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ class PlaylistCreator
|
|||
BaseItemKind.BOX_SET,
|
||||
BaseItemKind.COLLECTION_FOLDER,
|
||||
BaseItemKind.USER_VIEW,
|
||||
->
|
||||
-> {
|
||||
PlaylistCreationResult.Success(
|
||||
createFromCollection(
|
||||
item = item,
|
||||
|
|
@ -152,6 +152,7 @@ class PlaylistCreator
|
|||
filter = filter,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
BaseItemKind.EPISODE -> {
|
||||
val seriesId = item.seriesId
|
||||
|
|
@ -185,7 +186,7 @@ class PlaylistCreator
|
|||
}
|
||||
}
|
||||
|
||||
BaseItemKind.SERIES ->
|
||||
BaseItemKind.SERIES -> {
|
||||
PlaylistCreationResult.Success(
|
||||
createFromEpisode(
|
||||
seriesId = item.id,
|
||||
|
|
@ -194,8 +195,9 @@ class PlaylistCreator
|
|||
shuffled = shuffled,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
BaseItemKind.PLAYLIST ->
|
||||
BaseItemKind.PLAYLIST -> {
|
||||
PlaylistCreationResult.Success(
|
||||
createFromPlaylistId(
|
||||
item.id,
|
||||
|
|
@ -203,6 +205,7 @@ class PlaylistCreator
|
|||
shuffled,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// Not support yet
|
||||
// BaseItemKind.AGGREGATE_FOLDER -> TODO()
|
||||
|
|
@ -212,7 +215,9 @@ class PlaylistCreator
|
|||
// BaseItemKind.MUSIC_ALBUM -> TODO()
|
||||
// BaseItemKind.MUSIC_ARTIST -> TODO()
|
||||
|
||||
else -> PlaylistCreationResult.Error(null, "Unsupported type: ${item.type}")
|
||||
else -> {
|
||||
PlaylistCreationResult.Error(null, "Unsupported type: ${item.type}")
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getServerPlaylists(
|
||||
|
|
|
|||
|
|
@ -85,9 +85,13 @@ class ThemeSongPlayer
|
|||
-> return
|
||||
|
||||
ThemeSongVolume.LOWEST -> .05f
|
||||
|
||||
ThemeSongVolume.LOW -> .1f
|
||||
|
||||
ThemeSongVolume.MEDIUM -> .25f
|
||||
|
||||
ThemeSongVolume.HIGH -> .5f
|
||||
|
||||
ThemeSongVolume.HIGHEST -> 75f
|
||||
}
|
||||
player.apply {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class TrailerService
|
|||
navigateTo: (Destination) -> Unit,
|
||||
) {
|
||||
when (trailer) {
|
||||
is LocalTrailer ->
|
||||
is LocalTrailer -> {
|
||||
navigateTo.invoke(
|
||||
Destination.Playback(
|
||||
itemId = trailer.baseItem.id,
|
||||
|
|
@ -70,6 +70,7 @@ class TrailerService
|
|||
positionMs = 0L,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
is RemoteTrailer -> {
|
||||
val intent = Intent(Intent.ACTION_VIEW, trailer.url.toUri())
|
||||
|
|
|
|||
|
|
@ -299,14 +299,16 @@ class UpdateChecker
|
|||
|
||||
fun hasPermissions(): Boolean =
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ||
|
||||
ContextCompat.checkSelfPermission(
|
||||
context,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
) == PackageManager.PERMISSION_GRANTED &&
|
||||
ContextCompat.checkSelfPermission(
|
||||
context,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
(
|
||||
ContextCompat.checkSelfPermission(
|
||||
context,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
) == PackageManager.PERMISSION_GRANTED &&
|
||||
ContextCompat.checkSelfPermission(
|
||||
context,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
)
|
||||
|
||||
/**
|
||||
* Delete previously downloaded APKs
|
||||
|
|
|
|||
|
|
@ -352,11 +352,12 @@ class CollectionFolderViewModel
|
|||
|
||||
FavoriteFilter,
|
||||
PlayedFilter,
|
||||
->
|
||||
-> {
|
||||
listOf(
|
||||
FilterValueOption("True", null),
|
||||
FilterValueOption("False", null),
|
||||
)
|
||||
}
|
||||
|
||||
OfficialRatingFilter -> {
|
||||
api.localizationApi.getParentalRatings().content.map {
|
||||
|
|
@ -364,10 +365,11 @@ class CollectionFolderViewModel
|
|||
}
|
||||
}
|
||||
|
||||
VideoTypeFilter ->
|
||||
VideoTypeFilter -> {
|
||||
FilterVideoType.entries.map {
|
||||
FilterValueOption(it.readable, it)
|
||||
}
|
||||
}
|
||||
|
||||
YearFilter -> {
|
||||
api.yearsApi
|
||||
|
|
@ -400,10 +402,11 @@ class CollectionFolderViewModel
|
|||
items.toList().sorted().map { FilterValueOption("$it's", it) }
|
||||
}
|
||||
|
||||
CommunityRatingFilter ->
|
||||
CommunityRatingFilter -> {
|
||||
(1..10).map {
|
||||
FilterValueOption("$it", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Exception get filter value options for $filterOption")
|
||||
|
|
@ -418,7 +421,6 @@ class CollectionFolderViewModel
|
|||
CollectionType.MOVIES -> listOf(BaseItemKind.MOVIE)
|
||||
CollectionType.TVSHOWS -> listOf(BaseItemKind.SERIES)
|
||||
CollectionType.HOMEVIDEOS -> listOf(BaseItemKind.VIDEO)
|
||||
|
||||
else -> listOf()
|
||||
}
|
||||
val request =
|
||||
|
|
@ -535,10 +537,16 @@ fun CollectionFolderGrid(
|
|||
val playlistState by playlistViewModel.playlistState.observeAsState(PlaylistLoadingState.Pending)
|
||||
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(state)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage()
|
||||
-> {
|
||||
LoadingPage()
|
||||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
pager?.let { pager ->
|
||||
Box(modifier = modifier) {
|
||||
|
|
@ -920,18 +928,35 @@ data class CollectionFolderGridParameters(
|
|||
val CollectionType.baseItemKinds: List<BaseItemKind>
|
||||
get() =
|
||||
when (this) {
|
||||
CollectionType.MOVIES -> listOf(BaseItemKind.MOVIE)
|
||||
CollectionType.TVSHOWS -> listOf(BaseItemKind.SERIES)
|
||||
CollectionType.HOMEVIDEOS -> listOf(BaseItemKind.VIDEO)
|
||||
CollectionType.MUSIC ->
|
||||
CollectionType.MOVIES -> {
|
||||
listOf(BaseItemKind.MOVIE)
|
||||
}
|
||||
|
||||
CollectionType.TVSHOWS -> {
|
||||
listOf(BaseItemKind.SERIES)
|
||||
}
|
||||
|
||||
CollectionType.HOMEVIDEOS -> {
|
||||
listOf(BaseItemKind.VIDEO)
|
||||
}
|
||||
|
||||
CollectionType.MUSIC -> {
|
||||
listOf(
|
||||
BaseItemKind.AUDIO,
|
||||
BaseItemKind.MUSIC_ARTIST,
|
||||
BaseItemKind.MUSIC_ALBUM,
|
||||
)
|
||||
}
|
||||
|
||||
CollectionType.BOXSETS -> listOf(BaseItemKind.BOX_SET)
|
||||
CollectionType.PLAYLISTS -> listOf(BaseItemKind.PLAYLIST)
|
||||
CollectionType.BOXSETS -> {
|
||||
listOf(BaseItemKind.BOX_SET)
|
||||
}
|
||||
|
||||
else -> listOf()
|
||||
CollectionType.PLAYLISTS -> {
|
||||
listOf(BaseItemKind.PLAYLIST)
|
||||
}
|
||||
|
||||
else -> {
|
||||
listOf()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,9 +259,11 @@ fun DialogPopupContent(
|
|||
}
|
||||
items(dialogItems) {
|
||||
when (it) {
|
||||
is DialogItemDivider -> HorizontalDivider(Modifier.height(16.dp))
|
||||
is DialogItemDivider -> {
|
||||
HorizontalDivider(Modifier.height(16.dp))
|
||||
}
|
||||
|
||||
is DialogItem ->
|
||||
is DialogItem -> {
|
||||
ListItem(
|
||||
selected = false,
|
||||
enabled = !waiting && it.enabled,
|
||||
|
|
@ -278,6 +280,7 @@ fun DialogPopupContent(
|
|||
trailingContent = it.trailingContent,
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,7 +206,9 @@ fun FilterByButton(
|
|||
|
||||
FavoriteFilter,
|
||||
PlayedFilter,
|
||||
-> (currentValue as? Boolean) == value.name.toBoolean()
|
||||
-> {
|
||||
(currentValue as? Boolean) == value.name.toBoolean()
|
||||
}
|
||||
|
||||
OfficialRatingFilter -> {
|
||||
(currentValue as? List<String>)
|
||||
|
|
@ -214,19 +216,23 @@ fun FilterByButton(
|
|||
.contains(value.name)
|
||||
}
|
||||
|
||||
VideoTypeFilter ->
|
||||
VideoTypeFilter -> {
|
||||
(currentValue as? List<FilterVideoType>)
|
||||
.orEmpty()
|
||||
.contains(value.value)
|
||||
}
|
||||
|
||||
YearFilter,
|
||||
DecadeFilter,
|
||||
->
|
||||
-> {
|
||||
(currentValue as? List<Int>)
|
||||
.orEmpty()
|
||||
.contains(value.value)
|
||||
}
|
||||
|
||||
CommunityRatingFilter -> (currentValue as? Int) == value.value
|
||||
CommunityRatingFilter -> {
|
||||
(currentValue as? Int) == value.value
|
||||
}
|
||||
}
|
||||
}
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
|
|
@ -328,11 +334,12 @@ fun FilterByButton(
|
|||
filterOption.set(newValue, current)
|
||||
}
|
||||
|
||||
CommunityRatingFilter ->
|
||||
CommunityRatingFilter -> {
|
||||
filterOption.set(
|
||||
value.value as? Int,
|
||||
current,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
onFilterChange.invoke(newFilter)
|
||||
|
|
|
|||
|
|
@ -94,11 +94,15 @@ fun GenreCardGrid(
|
|||
when (val st = loading) {
|
||||
LoadingState.Pending,
|
||||
LoadingState.Loading,
|
||||
-> LoadingPage(modifier.focusable())
|
||||
-> {
|
||||
LoadingPage(modifier.focusable())
|
||||
}
|
||||
|
||||
is LoadingState.Error -> ErrorMessage(st, modifier.focusable())
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(st, modifier.focusable())
|
||||
}
|
||||
|
||||
LoadingState.Success ->
|
||||
LoadingState.Success -> {
|
||||
Box(modifier = modifier) {
|
||||
LaunchedEffect(Unit) { gridFocusRequester.tryRequestFocus() }
|
||||
CardGrid(
|
||||
|
|
@ -132,5 +136,6 @@ fun GenreCardGrid(
|
|||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,10 +94,15 @@ fun ItemGrid(
|
|||
val loading by viewModel.loading.observeAsState(LoadingState.Loading)
|
||||
val items by viewModel.items.observeAsState(listOf())
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(state)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage()
|
||||
-> {
|
||||
LoadingPage()
|
||||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
|
|
|
|||
|
|
@ -59,22 +59,24 @@ fun LoadingRow(
|
|||
},
|
||||
) {
|
||||
when (val r = state) {
|
||||
is RowLoadingState.Error ->
|
||||
is RowLoadingState.Error -> {
|
||||
LoadingRowPlaceholder(
|
||||
title = title,
|
||||
message = r.localizedMessage,
|
||||
messageColor = MaterialTheme.colorScheme.error,
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
|
||||
RowLoadingState.Pending,
|
||||
RowLoadingState.Loading,
|
||||
->
|
||||
-> {
|
||||
LoadingRowPlaceholder(
|
||||
title = title,
|
||||
message = stringResource(R.string.loading),
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is RowLoadingState.Success -> {
|
||||
if (r.items.isNotEmpty()) {
|
||||
|
|
|
|||
|
|
@ -256,8 +256,9 @@ fun StarRating(
|
|||
if (playSoundOnFocus) playOnClickSound(context)
|
||||
val newRating100 =
|
||||
when (precision) {
|
||||
StarRatingPrecision.FULL ->
|
||||
StarRatingPrecision.FULL -> {
|
||||
if (i == 1 && rating100 > 0 && rating100 <= 20) 0 else i * 20
|
||||
}
|
||||
|
||||
StarRatingPrecision.HALF -> {
|
||||
if (rating100 > i * 20) {
|
||||
|
|
|
|||
|
|
@ -127,13 +127,17 @@ fun RecommendedContent(
|
|||
val rows by viewModel.rows.collectAsState()
|
||||
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(state)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage()
|
||||
-> {
|
||||
LoadingPage()
|
||||
}
|
||||
|
||||
LoadingState.Success ->
|
||||
LoadingState.Success -> {
|
||||
HomePageContent(
|
||||
homeRows = rows,
|
||||
onClickItem = { _, item ->
|
||||
|
|
@ -146,6 +150,7 @@ fun RecommendedContent(
|
|||
showClock = preferences.appPreferences.interfacePreferences.showClock,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
moreDialog.compose { (position, item) ->
|
||||
DialogPopup(
|
||||
|
|
|
|||
|
|
@ -128,21 +128,25 @@ fun SliderActiveColor(focused: Boolean): Color {
|
|||
AppThemeColors.BLUE,
|
||||
AppThemeColors.GREEN,
|
||||
AppThemeColors.ORANGE,
|
||||
-> MaterialTheme.colorScheme.border
|
||||
-> {
|
||||
MaterialTheme.colorScheme.border
|
||||
}
|
||||
|
||||
AppThemeColors.BOLD_BLUE ->
|
||||
AppThemeColors.BOLD_BLUE -> {
|
||||
if (focused) {
|
||||
MaterialTheme.colorScheme.border
|
||||
} else {
|
||||
MaterialTheme.colorScheme.border
|
||||
}
|
||||
}
|
||||
|
||||
AppThemeColors.OLED_BLACK ->
|
||||
AppThemeColors.OLED_BLACK -> {
|
||||
if (focused) {
|
||||
MaterialTheme.colorScheme.primaryContainer
|
||||
} else {
|
||||
MaterialTheme.colorScheme.border
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -152,23 +156,27 @@ fun SliderInactiveColor(focused: Boolean): Color {
|
|||
return when (theme) {
|
||||
AppThemeColors.UNRECOGNIZED,
|
||||
AppThemeColors.PURPLE,
|
||||
->
|
||||
-> {
|
||||
MaterialTheme.colorScheme.border
|
||||
.copy(alpha = .25f)
|
||||
.compositeOver(MaterialTheme.colorScheme.surfaceVariant)
|
||||
.copy(alpha = .66f)
|
||||
}
|
||||
|
||||
AppThemeColors.BLUE,
|
||||
AppThemeColors.GREEN,
|
||||
AppThemeColors.ORANGE,
|
||||
AppThemeColors.BOLD_BLUE,
|
||||
-> MaterialTheme.colorScheme.secondaryContainer.copy(alpha = .66f)
|
||||
-> {
|
||||
MaterialTheme.colorScheme.secondaryContainer.copy(alpha = .66f)
|
||||
}
|
||||
|
||||
AppThemeColors.OLED_BLACK ->
|
||||
AppThemeColors.OLED_BLACK -> {
|
||||
if (focused) {
|
||||
MaterialTheme.colorScheme.tertiaryContainer
|
||||
} else {
|
||||
MaterialTheme.colorScheme.primaryContainer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -260,9 +260,11 @@ fun formatVideoRange(
|
|||
when (videoRange) {
|
||||
VideoRange.UNKNOWN,
|
||||
VideoRange.SDR, null,
|
||||
-> null
|
||||
-> {
|
||||
null
|
||||
}
|
||||
|
||||
VideoRange.HDR ->
|
||||
VideoRange.HDR -> {
|
||||
when (type) {
|
||||
VideoRangeType.UNKNOWN,
|
||||
VideoRangeType.SDR,
|
||||
|
|
@ -270,7 +272,9 @@ fun formatVideoRange(
|
|||
-> null
|
||||
|
||||
VideoRangeType.HDR10 -> "HDR10"
|
||||
|
||||
VideoRangeType.HDR10_PLUS -> "HDR10+"
|
||||
|
||||
VideoRangeType.HLG -> "HLG"
|
||||
|
||||
VideoRangeType.DOVI,
|
||||
|
|
@ -279,6 +283,7 @@ fun formatVideoRange(
|
|||
VideoRangeType.DOVI_WITH_SDR,
|
||||
-> context.getString(R.string.dolby_vision)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun formatAudioCodec(
|
||||
|
|
@ -287,20 +292,32 @@ fun formatAudioCodec(
|
|||
profile: String?,
|
||||
): String? =
|
||||
when {
|
||||
profile?.contains("Dolby Atmos", true) == true -> context.getString(R.string.dolby_atmos)
|
||||
profile?.contains("DTS:X", true) == true -> "DTS:X"
|
||||
profile?.contains("DTS:HD", true) == true -> "DTS:HD"
|
||||
else ->
|
||||
profile?.contains("Dolby Atmos", true) == true -> {
|
||||
context.getString(R.string.dolby_atmos)
|
||||
}
|
||||
|
||||
profile?.contains("DTS:X", true) == true -> {
|
||||
"DTS:X"
|
||||
}
|
||||
|
||||
profile?.contains("DTS:HD", true) == true -> {
|
||||
"DTS:HD"
|
||||
}
|
||||
|
||||
else -> {
|
||||
when (codec?.lowercase()) {
|
||||
Codec.Audio.TRUEHD -> "TrueHD"
|
||||
|
||||
Codec.Audio.OGG,
|
||||
Codec.Audio.OPUS,
|
||||
Codec.Audio.VORBIS,
|
||||
-> codec.replaceFirstChar { it.uppercase() }
|
||||
|
||||
null -> null
|
||||
|
||||
else -> codec.uppercase()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun formatSubtitleCodec(codec: String?): String? =
|
||||
|
|
|
|||
|
|
@ -107,7 +107,9 @@ fun getStringRes(sort: ItemSortBy): Int =
|
|||
-> R.string.sort_by_name
|
||||
|
||||
ItemSortBy.PREMIERE_DATE -> R.string.sort_by_date_released
|
||||
|
||||
ItemSortBy.DATE_CREATED -> R.string.sort_by_date_added
|
||||
|
||||
ItemSortBy.DATE_LAST_CONTENT_ADDED -> R.string.sort_by_date_episode_added
|
||||
|
||||
ItemSortBy.DATE_PLAYED,
|
||||
|
|
@ -115,12 +117,20 @@ fun getStringRes(sort: ItemSortBy): Int =
|
|||
-> R.string.sort_by_date_played
|
||||
|
||||
ItemSortBy.RANDOM -> R.string.sort_by_random
|
||||
|
||||
ItemSortBy.COMMUNITY_RATING -> R.string.community_rating
|
||||
|
||||
ItemSortBy.CRITIC_RATING -> R.string.critic_rating
|
||||
|
||||
ItemSortBy.OFFICIAL_RATING -> R.string.official_rating
|
||||
|
||||
ItemSortBy.PLAY_COUNT -> R.string.play_count
|
||||
|
||||
ItemSortBy.AIRED_EPISODE_ORDER -> R.string.aired_episode_order
|
||||
|
||||
ItemSortBy.RUNTIME -> R.string.runtime_sort
|
||||
|
||||
ItemSortBy.DEFAULT -> R.string.default_track
|
||||
|
||||
else -> throw IllegalArgumentException("Unsupported sort option: $sort")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ fun CollectionFolderLiveTv(
|
|||
.focusRequester(focusRequester),
|
||||
)
|
||||
}
|
||||
|
||||
1 -> {
|
||||
DvrSchedule(
|
||||
true,
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ fun CollectionFolderMovie(
|
|||
.focusRequester(focusRequester),
|
||||
)
|
||||
}
|
||||
|
||||
// Library
|
||||
1 -> {
|
||||
CollectionFolderGrid(
|
||||
|
|
@ -131,6 +132,7 @@ fun CollectionFolderMovie(
|
|||
playEnabled = true,
|
||||
)
|
||||
}
|
||||
|
||||
// Collections
|
||||
2 -> {
|
||||
CollectionFolderGrid(
|
||||
|
|
@ -158,6 +160,7 @@ fun CollectionFolderMovie(
|
|||
playEnabled = false,
|
||||
)
|
||||
}
|
||||
|
||||
// Genres
|
||||
3 -> {
|
||||
GenreCardGrid(
|
||||
|
|
@ -169,7 +172,10 @@ fun CollectionFolderMovie(
|
|||
.focusRequester(focusRequester),
|
||||
)
|
||||
}
|
||||
else -> ErrorMessage("Invalid tab index $selectedTabIndex", null)
|
||||
|
||||
else -> {
|
||||
ErrorMessage("Invalid tab index $selectedTabIndex", null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ fun CollectionFolderTv(
|
|||
.focusRequester(focusRequester),
|
||||
)
|
||||
}
|
||||
|
||||
// Library
|
||||
1 -> {
|
||||
CollectionFolderGrid(
|
||||
|
|
@ -134,6 +135,7 @@ fun CollectionFolderTv(
|
|||
playEnabled = false,
|
||||
)
|
||||
}
|
||||
|
||||
// Genres
|
||||
2 -> {
|
||||
GenreCardGrid(
|
||||
|
|
@ -145,7 +147,10 @@ fun CollectionFolderTv(
|
|||
.focusRequester(focusRequester),
|
||||
)
|
||||
}
|
||||
else -> ErrorMessage("Invalid tab index $selectedTabIndex", null)
|
||||
|
||||
else -> {
|
||||
ErrorMessage("Invalid tab index $selectedTabIndex", null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ fun FavoritesPage(
|
|||
filterOptions = DefaultForFavoritesFilterOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// TV
|
||||
1 -> {
|
||||
CollectionFolderGrid(
|
||||
|
|
@ -163,6 +164,7 @@ fun FavoritesPage(
|
|||
filterOptions = DefaultForFavoritesFilterOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Episodes
|
||||
2 -> {
|
||||
CollectionFolderGrid(
|
||||
|
|
@ -191,6 +193,7 @@ fun FavoritesPage(
|
|||
filterOptions = DefaultForFavoritesFilterOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Videos
|
||||
3 -> {
|
||||
CollectionFolderGrid(
|
||||
|
|
@ -218,6 +221,7 @@ fun FavoritesPage(
|
|||
filterOptions = DefaultForFavoritesFilterOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Playlists
|
||||
4 -> {
|
||||
CollectionFolderGrid(
|
||||
|
|
@ -245,6 +249,7 @@ fun FavoritesPage(
|
|||
filterOptions = DefaultForFavoritesFilterOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// People
|
||||
5 -> {
|
||||
CollectionFolderGrid(
|
||||
|
|
@ -277,7 +282,10 @@ fun FavoritesPage(
|
|||
filterOptions = listOf(),
|
||||
)
|
||||
}
|
||||
else -> ErrorMessage("Invalid tab index $selectedTabIndex", null)
|
||||
|
||||
else -> {
|
||||
ErrorMessage("Invalid tab index $selectedTabIndex", null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,10 +178,15 @@ fun PersonPage(
|
|||
|
||||
val loading by viewModel.loading.observeAsState(LoadingState.Loading)
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state, modifier)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(state, modifier)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage(modifier)
|
||||
-> {
|
||||
LoadingPage(modifier)
|
||||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
person?.let { person ->
|
||||
|
|
|
|||
|
|
@ -130,9 +130,15 @@ fun PlaylistDetails(
|
|||
var longClickDialog by remember { mutableStateOf<DialogParams?>(null) }
|
||||
|
||||
when (val st = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(st, modifier)
|
||||
LoadingState.Pending, LoadingState.Loading -> LoadingPage(modifier)
|
||||
LoadingState.Success ->
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(st, modifier)
|
||||
}
|
||||
|
||||
LoadingState.Pending, LoadingState.Loading -> {
|
||||
LoadingPage(modifier)
|
||||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
playlist?.let {
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
LaunchedEffect(Unit) { focusRequester.tryRequestFocus() }
|
||||
|
|
@ -189,6 +195,7 @@ fun PlaylistDetails(
|
|||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
longClickDialog?.let { params ->
|
||||
DialogPopup(
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ fun PlaylistDialog(
|
|||
when (val s = state) {
|
||||
PlaylistLoadingState.Pending,
|
||||
PlaylistLoadingState.Loading,
|
||||
->
|
||||
-> {
|
||||
CircularProgressIndicator(
|
||||
color = MaterialTheme.colorScheme.border,
|
||||
modifier =
|
||||
|
|
@ -224,9 +224,11 @@ fun PlaylistDialog(
|
|||
.align(Alignment.CenterHorizontally)
|
||||
.size(48.dp),
|
||||
)
|
||||
}
|
||||
|
||||
is PlaylistLoadingState.Error ->
|
||||
is PlaylistLoadingState.Error -> {
|
||||
ErrorMessage(s.message, s.exception)
|
||||
}
|
||||
|
||||
is PlaylistLoadingState.Success -> {
|
||||
LaunchedEffect(Unit) { focusRequester.tryRequestFocus() }
|
||||
|
|
|
|||
|
|
@ -102,10 +102,15 @@ fun EpisodeDetails(
|
|||
)
|
||||
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(state)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage()
|
||||
-> {
|
||||
LoadingPage()
|
||||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
item?.let { ep ->
|
||||
|
|
|
|||
|
|
@ -124,11 +124,15 @@ fun DvrSchedule(
|
|||
val active by viewModel.active.observeAsState(listOf())
|
||||
val recordings by viewModel.scheduled.observeAsState(mapOf())
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state, modifier)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(state, modifier)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage(modifier)
|
||||
-> {
|
||||
LoadingPage(modifier)
|
||||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
var showDialog by remember { mutableStateOf<BaseItem?>(null) }
|
||||
|
|
|
|||
|
|
@ -76,17 +76,21 @@ fun ProgramDialog(
|
|||
.padding(16.dp),
|
||||
) {
|
||||
when (val st = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(st)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(st)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
->
|
||||
-> {
|
||||
CircularProgress(
|
||||
Modifier
|
||||
.padding(8.dp)
|
||||
.size(48.dp),
|
||||
)
|
||||
}
|
||||
|
||||
LoadingState.Success ->
|
||||
LoadingState.Success -> {
|
||||
item?.let { item ->
|
||||
val now = LocalDateTime.now()
|
||||
val dto = item.data
|
||||
|
|
@ -272,6 +276,7 @@ fun ProgramDialog(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,9 +77,14 @@ fun TvGuideGrid(
|
|||
// val programsByChannel by viewModel.programsByChannel.observeAsState(mapOf())
|
||||
// val fetchedRange by viewModel.fetchedRange.observeAsState(0..0)
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state, modifier)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(state, modifier)
|
||||
}
|
||||
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage(modifier)
|
||||
-> {
|
||||
LoadingPage(modifier)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Success,
|
||||
|
|
|
|||
|
|
@ -133,10 +133,16 @@ fun MovieDetails(
|
|||
)
|
||||
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(state)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage()
|
||||
-> {
|
||||
LoadingPage()
|
||||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
item?.let { movie ->
|
||||
LifecycleStartEffect(destination.itemId) {
|
||||
|
|
@ -565,7 +571,7 @@ fun TrailerRow(
|
|||
Modifier
|
||||
}
|
||||
when (item) {
|
||||
is LocalTrailer ->
|
||||
is LocalTrailer -> {
|
||||
SeasonCard(
|
||||
item = item.baseItem,
|
||||
onClick = { onClickTrailer.invoke(item) },
|
||||
|
|
@ -575,6 +581,7 @@ fun TrailerRow(
|
|||
showImageOverlay = false,
|
||||
modifier = cardModifier,
|
||||
)
|
||||
}
|
||||
|
||||
is RemoteTrailer -> {
|
||||
val subtitle =
|
||||
|
|
|
|||
|
|
@ -112,10 +112,16 @@ fun SeriesDetails(
|
|||
val playlistState by playlistViewModel.playlistState.observeAsState(PlaylistLoadingState.Pending)
|
||||
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(state)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage()
|
||||
-> {
|
||||
LoadingPage()
|
||||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
item?.let { item ->
|
||||
LifecycleStartEffect(destination.itemId) {
|
||||
|
|
|
|||
|
|
@ -175,11 +175,15 @@ fun SeriesOverview(
|
|||
val chosenStreams by viewModel.chosenStreams.observeAsState(null)
|
||||
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(state)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage()
|
||||
-> {
|
||||
LoadingPage()
|
||||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
series?.let { series ->
|
||||
|
|
|
|||
|
|
@ -172,8 +172,14 @@ fun SeriesOverviewContent(
|
|||
|
||||
key(position.seasonTabIndex) {
|
||||
when (val eps = episodes) {
|
||||
EpisodeList.Loading -> LoadingPage()
|
||||
is EpisodeList.Error -> ErrorMessage(eps.message, eps.exception)
|
||||
EpisodeList.Loading -> {
|
||||
LoadingPage()
|
||||
}
|
||||
|
||||
is EpisodeList.Error -> {
|
||||
ErrorMessage(eps.message, eps.exception)
|
||||
}
|
||||
|
||||
is EpisodeList.Success -> {
|
||||
val state = rememberLazyListState()
|
||||
OneTimeLaunchedEffect {
|
||||
|
|
|
|||
|
|
@ -107,11 +107,15 @@ fun HomePage(
|
|||
}
|
||||
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(state)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage()
|
||||
-> {
|
||||
LoadingPage()
|
||||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
var dialog by remember { mutableStateOf<DialogParams?>(null) }
|
||||
|
|
@ -391,7 +395,7 @@ fun HomePageContent(
|
|||
when (loadingState) {
|
||||
LoadingState.Pending,
|
||||
LoadingState.Loading,
|
||||
->
|
||||
-> {
|
||||
Box(
|
||||
modifier =
|
||||
Modifier
|
||||
|
|
@ -401,6 +405,7 @@ fun HomePageContent(
|
|||
) {
|
||||
CircularProgress(Modifier.fillMaxSize())
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -325,24 +325,26 @@ fun LazyListScope.searchResultRow(
|
|||
) {
|
||||
item {
|
||||
when (val r = result) {
|
||||
is SearchResult.Error ->
|
||||
is SearchResult.Error -> {
|
||||
SearchResultPlaceholder(
|
||||
title = title,
|
||||
message = r.ex.localizedMessage ?: "Error occurred during search",
|
||||
messageColor = MaterialTheme.colorScheme.error,
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
|
||||
SearchResult.NoQuery -> {
|
||||
// no-op
|
||||
}
|
||||
|
||||
SearchResult.Searching ->
|
||||
SearchResult.Searching -> {
|
||||
SearchResultPlaceholder(
|
||||
title = title,
|
||||
message = stringResource(R.string.searching),
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is SearchResult.Success -> {
|
||||
if (r.items.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -44,70 +44,84 @@ fun DestinationContent(
|
|||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
when (destination) {
|
||||
is Destination.Home ->
|
||||
is Destination.Home -> {
|
||||
HomePage(
|
||||
preferences = preferences,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is Destination.PlaybackList,
|
||||
is Destination.Playback,
|
||||
->
|
||||
-> {
|
||||
PlaybackPage(
|
||||
preferences = preferences,
|
||||
destination = destination,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
Destination.ServerList -> SwitchServerContent(modifier)
|
||||
is Destination.UserList -> SwitchUserContent(destination.server, modifier)
|
||||
Destination.ServerList -> {
|
||||
SwitchServerContent(modifier)
|
||||
}
|
||||
|
||||
is Destination.Settings ->
|
||||
is Destination.UserList -> {
|
||||
SwitchUserContent(destination.server, modifier)
|
||||
}
|
||||
|
||||
is Destination.Settings -> {
|
||||
PreferencesPage(
|
||||
preferences.appPreferences,
|
||||
destination.screen,
|
||||
modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is Destination.SeriesOverview ->
|
||||
is Destination.SeriesOverview -> {
|
||||
SeriesOverview(
|
||||
preferences,
|
||||
destination,
|
||||
modifier,
|
||||
initialSeasonEpisode = destination.seasonEpisode,
|
||||
)
|
||||
}
|
||||
|
||||
is Destination.MediaItem ->
|
||||
is Destination.MediaItem -> {
|
||||
when (destination.type) {
|
||||
BaseItemKind.SERIES ->
|
||||
BaseItemKind.SERIES -> {
|
||||
SeriesDetails(
|
||||
preferences,
|
||||
destination,
|
||||
modifier,
|
||||
)
|
||||
}
|
||||
|
||||
BaseItemKind.MOVIE ->
|
||||
BaseItemKind.MOVIE -> {
|
||||
MovieDetails(
|
||||
preferences,
|
||||
destination,
|
||||
modifier,
|
||||
)
|
||||
}
|
||||
|
||||
BaseItemKind.VIDEO ->
|
||||
BaseItemKind.VIDEO -> {
|
||||
// TODO Use VideoDetails
|
||||
MovieDetails(
|
||||
preferences,
|
||||
destination,
|
||||
modifier,
|
||||
)
|
||||
}
|
||||
|
||||
BaseItemKind.EPISODE ->
|
||||
BaseItemKind.EPISODE -> {
|
||||
EpisodeDetails(
|
||||
preferences,
|
||||
destination,
|
||||
modifier,
|
||||
)
|
||||
}
|
||||
|
||||
BaseItemKind.BOX_SET ->
|
||||
BaseItemKind.BOX_SET -> {
|
||||
CollectionFolderBoxSet(
|
||||
preferences = preferences,
|
||||
itemId = destination.itemId,
|
||||
|
|
@ -116,14 +130,16 @@ fun DestinationContent(
|
|||
playEnabled = true,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
BaseItemKind.PLAYLIST ->
|
||||
BaseItemKind.PLAYLIST -> {
|
||||
PlaylistDetails(
|
||||
destination = destination,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
BaseItemKind.COLLECTION_FOLDER ->
|
||||
BaseItemKind.COLLECTION_FOLDER -> {
|
||||
CollectionFolder(
|
||||
preferences = preferences,
|
||||
destination = destination,
|
||||
|
|
@ -132,8 +148,9 @@ fun DestinationContent(
|
|||
recursiveOverride = null,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
BaseItemKind.FOLDER ->
|
||||
BaseItemKind.FOLDER -> {
|
||||
CollectionFolder(
|
||||
preferences = preferences,
|
||||
destination = destination,
|
||||
|
|
@ -142,8 +159,9 @@ fun DestinationContent(
|
|||
recursiveOverride = null,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
BaseItemKind.USER_VIEW ->
|
||||
BaseItemKind.USER_VIEW -> {
|
||||
CollectionFolder(
|
||||
preferences = preferences,
|
||||
destination = destination,
|
||||
|
|
@ -152,21 +170,24 @@ fun DestinationContent(
|
|||
recursiveOverride = true,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
BaseItemKind.PERSON ->
|
||||
BaseItemKind.PERSON -> {
|
||||
PersonPage(
|
||||
preferences,
|
||||
destination,
|
||||
modifier,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
Timber.w("Unsupported item type: ${destination.type}")
|
||||
Text("Unsupported item type: ${destination.type}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is Destination.FilteredCollection ->
|
||||
is Destination.FilteredCollection -> {
|
||||
CollectionFolderGeneric(
|
||||
preferences = preferences,
|
||||
itemId = destination.itemId,
|
||||
|
|
@ -177,38 +198,49 @@ fun DestinationContent(
|
|||
filterOptions = DefaultForGenresFilterOptions,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is Destination.Recordings ->
|
||||
is Destination.Recordings -> {
|
||||
CollectionFolderRecordings(
|
||||
preferences,
|
||||
destination.itemId,
|
||||
false,
|
||||
modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is Destination.ItemGrid ->
|
||||
is Destination.ItemGrid -> {
|
||||
ItemGrid(
|
||||
destination,
|
||||
modifier,
|
||||
)
|
||||
}
|
||||
|
||||
Destination.Favorites ->
|
||||
Destination.Favorites -> {
|
||||
FavoritesPage(
|
||||
preferences = preferences,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
Destination.UpdateApp -> InstallUpdatePage(preferences, modifier)
|
||||
Destination.UpdateApp -> {
|
||||
InstallUpdatePage(preferences, modifier)
|
||||
}
|
||||
|
||||
Destination.License -> LicenseInfo(modifier)
|
||||
Destination.License -> {
|
||||
LicenseInfo(modifier)
|
||||
}
|
||||
|
||||
Destination.Search ->
|
||||
Destination.Search -> {
|
||||
SearchPage(
|
||||
userPreferences = preferences,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
Destination.Debug -> DebugPage(preferences, modifier)
|
||||
Destination.Debug -> {
|
||||
DebugPage(preferences, modifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -222,21 +254,23 @@ fun CollectionFolder(
|
|||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
when (collectionType) {
|
||||
CollectionType.TVSHOWS ->
|
||||
CollectionType.TVSHOWS -> {
|
||||
CollectionFolderTv(
|
||||
preferences,
|
||||
destination,
|
||||
modifier,
|
||||
)
|
||||
}
|
||||
|
||||
CollectionType.MOVIES ->
|
||||
CollectionType.MOVIES -> {
|
||||
CollectionFolderMovie(
|
||||
preferences,
|
||||
destination,
|
||||
modifier,
|
||||
)
|
||||
}
|
||||
|
||||
CollectionType.BOXSETS ->
|
||||
CollectionType.BOXSETS -> {
|
||||
CollectionFolderGeneric(
|
||||
preferences = preferences,
|
||||
itemId = destination.itemId,
|
||||
|
|
@ -246,8 +280,9 @@ fun CollectionFolder(
|
|||
modifier = modifier,
|
||||
sortOptions = MovieSortOptions,
|
||||
)
|
||||
}
|
||||
|
||||
CollectionType.PLAYLISTS ->
|
||||
CollectionType.PLAYLISTS -> {
|
||||
CollectionFolderPlaylist(
|
||||
preferences,
|
||||
destination.itemId,
|
||||
|
|
@ -255,20 +290,22 @@ fun CollectionFolder(
|
|||
true,
|
||||
modifier,
|
||||
)
|
||||
}
|
||||
|
||||
CollectionType.LIVETV ->
|
||||
CollectionType.LIVETV -> {
|
||||
CollectionFolderLiveTv(
|
||||
preferences = preferences,
|
||||
destination = destination,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
CollectionType.HOMEVIDEOS,
|
||||
CollectionType.MUSICVIDEOS,
|
||||
CollectionType.MUSIC,
|
||||
CollectionType.BOOKS,
|
||||
CollectionType.PHOTOS,
|
||||
->
|
||||
-> {
|
||||
CollectionFolderGeneric(
|
||||
preferences,
|
||||
destination.itemId,
|
||||
|
|
@ -277,12 +314,13 @@ fun CollectionFolder(
|
|||
playEnabled = true,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
CollectionType.FOLDERS,
|
||||
CollectionType.TRAILERS,
|
||||
CollectionType.UNKNOWN,
|
||||
null,
|
||||
->
|
||||
-> {
|
||||
CollectionFolderGeneric(
|
||||
preferences,
|
||||
destination.itemId,
|
||||
|
|
@ -291,5 +329,6 @@ fun CollectionFolder(
|
|||
playEnabled = false,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -598,10 +598,15 @@ fun NavigationDrawerScope.NavItem(
|
|||
val useFont = library !is ServerNavDrawerItem || library.type != CollectionType.LIVETV
|
||||
val icon =
|
||||
when (library) {
|
||||
NavDrawerItem.Favorites -> R.string.fa_heart
|
||||
NavDrawerItem.More -> R.string.fa_ellipsis
|
||||
NavDrawerItem.Favorites -> {
|
||||
R.string.fa_heart
|
||||
}
|
||||
|
||||
is ServerNavDrawerItem ->
|
||||
NavDrawerItem.More -> {
|
||||
R.string.fa_ellipsis
|
||||
}
|
||||
|
||||
is ServerNavDrawerItem -> {
|
||||
when (library.type) {
|
||||
CollectionType.MOVIES -> R.string.fa_film
|
||||
CollectionType.TVSHOWS -> R.string.fa_tv
|
||||
|
|
@ -612,6 +617,7 @@ fun NavigationDrawerScope.NavItem(
|
|||
CollectionType.PLAYLISTS -> R.string.fa_list_ul
|
||||
else -> R.string.fa_film
|
||||
}
|
||||
}
|
||||
}
|
||||
val focused by interactionSource.collectIsFocusedAsState()
|
||||
NavigationDrawerItem(
|
||||
|
|
@ -686,7 +692,7 @@ fun navItemColor(
|
|||
else -> .2f
|
||||
}
|
||||
return when {
|
||||
selected && focused ->
|
||||
selected && focused -> {
|
||||
when (theme) {
|
||||
AppThemeColors.UNRECOGNIZED,
|
||||
AppThemeColors.PURPLE,
|
||||
|
|
@ -699,10 +705,19 @@ fun navItemColor(
|
|||
AppThemeColors.OLED_BLACK,
|
||||
-> MaterialTheme.colorScheme.primary
|
||||
}
|
||||
}
|
||||
|
||||
selected -> MaterialTheme.colorScheme.border
|
||||
focused -> LocalContentColor.current
|
||||
else -> MaterialTheme.colorScheme.onSurface
|
||||
selected -> {
|
||||
MaterialTheme.colorScheme.border
|
||||
}
|
||||
|
||||
focused -> {
|
||||
LocalContentColor.current
|
||||
}
|
||||
|
||||
else -> {
|
||||
MaterialTheme.colorScheme.onSurface
|
||||
}
|
||||
}.copy(alpha = alpha)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,9 @@ fun DownloadSubtitlesContent(
|
|||
}
|
||||
}
|
||||
|
||||
is SubtitleSearch.Error -> Wrapper { ErrorMessage(null, s.ex, modifier) }
|
||||
is SubtitleSearch.Error -> {
|
||||
Wrapper { ErrorMessage(null, s.ex, modifier) }
|
||||
}
|
||||
|
||||
is SubtitleSearch.Success -> {
|
||||
val dialogItems = convertRemoteSubtitles(s.options, onClickDownload)
|
||||
|
|
@ -133,9 +135,11 @@ fun DownloadSubtitlesContent(
|
|||
) {
|
||||
itemsIndexed(dialogItems) { index, item ->
|
||||
when (item) {
|
||||
is DialogItemDivider -> HorizontalDivider(Modifier.height(16.dp))
|
||||
is DialogItemDivider -> {
|
||||
HorizontalDivider(Modifier.height(16.dp))
|
||||
}
|
||||
|
||||
is DialogItem ->
|
||||
is DialogItem -> {
|
||||
ListItem(
|
||||
selected = false,
|
||||
enabled = item.enabled,
|
||||
|
|
@ -153,6 +157,7 @@ fun DownloadSubtitlesContent(
|
|||
Modifier.focusRequester(focusRequester),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ fun PlaybackDialog(
|
|||
)
|
||||
}
|
||||
|
||||
PlaybackDialogType.AUDIO ->
|
||||
PlaybackDialogType.AUDIO -> {
|
||||
BottomDialog(
|
||||
choices = settings.audioStreams.map { it.displayName },
|
||||
currentChoice = settings.audioStreams.indexOfFirstOrNull { it.index == settings.audioIndex },
|
||||
|
|
@ -134,8 +134,9 @@ fun PlaybackDialog(
|
|||
},
|
||||
gravity = Gravity.END,
|
||||
)
|
||||
}
|
||||
|
||||
PlaybackDialogType.PLAYBACK_SPEED ->
|
||||
PlaybackDialogType.PLAYBACK_SPEED -> {
|
||||
BottomDialog(
|
||||
choices = playbackSpeedOptions,
|
||||
currentChoice = playbackSpeedOptions.indexOf(settings.playbackSpeed.toString()),
|
||||
|
|
@ -152,8 +153,9 @@ fun PlaybackDialog(
|
|||
},
|
||||
gravity = Gravity.END,
|
||||
)
|
||||
}
|
||||
|
||||
PlaybackDialogType.VIDEO_SCALE ->
|
||||
PlaybackDialogType.VIDEO_SCALE -> {
|
||||
BottomDialog(
|
||||
choices = playbackScaleOptions.values.toList(),
|
||||
currentChoice = playbackScaleOptions.keys.toList().indexOf(settings.contentScale),
|
||||
|
|
@ -170,5 +172,6 @@ fun PlaybackDialog(
|
|||
},
|
||||
gravity = Gravity.END,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,14 +94,29 @@ class PlaybackKeyHandler(
|
|||
updateSkipIndicator(-seekBack.inWholeMilliseconds)
|
||||
}
|
||||
|
||||
Key.MediaNext -> if (player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT)) player.seekToNext()
|
||||
Key.MediaPrevious -> if (player.isCommandAvailable(Player.COMMAND_SEEK_TO_PREVIOUS)) player.seekToPrevious()
|
||||
Key.MediaNext -> {
|
||||
if (player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT)) player.seekToNext()
|
||||
}
|
||||
|
||||
Key.Captions -> onPlaybackDialogTypeClick.invoke(PlaybackDialogType.CAPTIONS)
|
||||
Key.MediaAudioTrack -> onPlaybackDialogTypeClick.invoke(PlaybackDialogType.AUDIO)
|
||||
Key.MediaStop -> onStop.invoke()
|
||||
Key.MediaPrevious -> {
|
||||
if (player.isCommandAvailable(Player.COMMAND_SEEK_TO_PREVIOUS)) player.seekToPrevious()
|
||||
}
|
||||
|
||||
else -> result = false
|
||||
Key.Captions -> {
|
||||
onPlaybackDialogTypeClick.invoke(PlaybackDialogType.CAPTIONS)
|
||||
}
|
||||
|
||||
Key.MediaAudioTrack -> {
|
||||
onPlaybackDialogTypeClick.invoke(PlaybackDialogType.AUDIO)
|
||||
}
|
||||
|
||||
Key.MediaStop -> {
|
||||
onStop.invoke()
|
||||
}
|
||||
|
||||
else -> {
|
||||
result = false
|
||||
}
|
||||
}
|
||||
} else if (isEnterKey(it) && !controllerViewState.controlsVisible) {
|
||||
controllerViewState.showControls()
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ fun PlaybackOverlay(
|
|||
// Don't use key events because this control has vertical items so up/down is tough to manage
|
||||
)
|
||||
when (nextState) {
|
||||
OverlayViewState.CHAPTERS ->
|
||||
OverlayViewState.CHAPTERS -> {
|
||||
Text(
|
||||
text = stringResource(R.string.chapters),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
|
|
@ -194,8 +194,9 @@ fun PlaybackOverlay(
|
|||
if (it.isFocused) state = nextState
|
||||
}.focusable(),
|
||||
)
|
||||
}
|
||||
|
||||
OverlayViewState.QUEUE ->
|
||||
OverlayViewState.QUEUE -> {
|
||||
Text(
|
||||
text = stringResource(R.string.queue),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
|
|
@ -206,8 +207,11 @@ fun PlaybackOverlay(
|
|||
if (it.isFocused) state = nextState
|
||||
}.focusable(),
|
||||
)
|
||||
}
|
||||
|
||||
else -> Spacer(Modifier.height(32.dp))
|
||||
else -> {
|
||||
Spacer(Modifier.height(32.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,10 +109,15 @@ fun PlaybackPage(
|
|||
|
||||
val loading by viewModel.loading.observeAsState(LoadingState.Loading)
|
||||
when (val st = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(st, modifier)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(st, modifier)
|
||||
}
|
||||
|
||||
LoadingState.Pending,
|
||||
LoadingState.Loading,
|
||||
-> LoadingPage(modifier.background(Color.Black))
|
||||
-> {
|
||||
LoadingPage(modifier.background(Color.Black))
|
||||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
val prefs = preferences.appPreferences.playbackPreferences
|
||||
|
|
@ -177,7 +182,7 @@ fun PlaybackPage(
|
|||
}
|
||||
var skipPosition by remember { mutableLongStateOf(0L) }
|
||||
val updateSkipIndicator = { delta: Long ->
|
||||
if (skipIndicatorDuration > 0 && delta < 0 || skipIndicatorDuration < 0 && delta > 0) {
|
||||
if ((skipIndicatorDuration > 0 && delta < 0) || (skipIndicatorDuration < 0 && delta > 0)) {
|
||||
skipIndicatorDuration = 0
|
||||
}
|
||||
skipIndicatorDuration += delta
|
||||
|
|
@ -216,8 +221,14 @@ fun PlaybackPage(
|
|||
showDebugInfo = !showDebugInfo
|
||||
}
|
||||
|
||||
PlaybackAction.ShowPlaylist -> TODO()
|
||||
PlaybackAction.ShowVideoFilterDialog -> TODO()
|
||||
PlaybackAction.ShowPlaylist -> {
|
||||
TODO()
|
||||
}
|
||||
|
||||
PlaybackAction.ShowVideoFilterDialog -> {
|
||||
TODO()
|
||||
}
|
||||
|
||||
is PlaybackAction.ToggleAudio -> {
|
||||
viewModel.changeAudioStream(it.index)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,7 +213,9 @@ class PlaybackViewModel
|
|||
d.itemId
|
||||
}
|
||||
|
||||
else -> throw IllegalArgumentException("Destination not supported: $destination")
|
||||
else -> {
|
||||
throw IllegalArgumentException("Destination not supported: $destination")
|
||||
}
|
||||
}
|
||||
this.itemId = itemId
|
||||
viewModelScope.launch(
|
||||
|
|
@ -554,8 +556,11 @@ class PlaybackViewModel
|
|||
when {
|
||||
// playerBackend == PlayerBackend.MPV -> PlayMethod.DIRECT_PLAY
|
||||
source.supportsDirectPlay -> PlayMethod.DIRECT_PLAY
|
||||
|
||||
source.supportsDirectStream -> PlayMethod.DIRECT_STREAM
|
||||
|
||||
source.supportsTranscoding -> PlayMethod.TRANSCODE
|
||||
|
||||
else -> throw Exception("No supported playback method")
|
||||
}
|
||||
Timber.v("Playback decision: $transcodeType")
|
||||
|
|
@ -921,13 +926,14 @@ class PlaybackViewModel
|
|||
viewModelScope.launch(Dispatchers.Main + ExceptionHandler()) {
|
||||
currentPlayback.value?.let {
|
||||
when (it.playMethod) {
|
||||
PlayMethod.TRANSCODE ->
|
||||
PlayMethod.TRANSCODE -> {
|
||||
loading.setValueOnMain(
|
||||
LoadingState.Error(
|
||||
"Error during playback",
|
||||
error,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
PlayMethod.DIRECT_STREAM, PlayMethod.DIRECT_PLAY -> {
|
||||
Timber.w("Playback error during ${it.playMethod}, falling back to transcoding")
|
||||
|
|
@ -968,28 +974,45 @@ class PlaybackViewModel
|
|||
navigationManager.goBack()
|
||||
}
|
||||
|
||||
PlaystateCommand.PAUSE -> player.pause()
|
||||
PlaystateCommand.UNPAUSE -> player.play()
|
||||
PlaystateCommand.NEXT_TRACK -> playNextUp()
|
||||
PlaystateCommand.PREVIOUS_TRACK -> playPrevious()
|
||||
PlaystateCommand.SEEK ->
|
||||
PlaystateCommand.PAUSE -> {
|
||||
player.pause()
|
||||
}
|
||||
|
||||
PlaystateCommand.UNPAUSE -> {
|
||||
player.play()
|
||||
}
|
||||
|
||||
PlaystateCommand.NEXT_TRACK -> {
|
||||
playNextUp()
|
||||
}
|
||||
|
||||
PlaystateCommand.PREVIOUS_TRACK -> {
|
||||
playPrevious()
|
||||
}
|
||||
|
||||
PlaystateCommand.SEEK -> {
|
||||
it.seekPositionTicks?.ticks?.let {
|
||||
player.seekTo(
|
||||
it.inWholeMilliseconds,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
PlaystateCommand.REWIND ->
|
||||
PlaystateCommand.REWIND -> {
|
||||
player.seekBack(
|
||||
preferences.appPreferences.playbackPreferences.skipBackMs.milliseconds,
|
||||
)
|
||||
}
|
||||
|
||||
PlaystateCommand.FAST_FORWARD ->
|
||||
PlaystateCommand.FAST_FORWARD -> {
|
||||
player.seekForward(
|
||||
preferences.appPreferences.playbackPreferences.skipForwardMs.milliseconds,
|
||||
)
|
||||
}
|
||||
|
||||
PlaystateCommand.PLAY_PAUSE -> if (player.isPlaying) player.pause() else player.play()
|
||||
PlaystateCommand.PLAY_PAUSE -> {
|
||||
if (player.isPlaying) player.pause() else player.play()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,8 +153,14 @@ object TrackSelectionUtils {
|
|||
// TODO MPV could use literal indexes because they are stored in the track format ID
|
||||
PlayerBackend.MPV -> {
|
||||
when (type) {
|
||||
MediaStreamType.VIDEO -> serverIndex - externalSubtitleCount + 1
|
||||
MediaStreamType.AUDIO -> serverIndex - externalSubtitleCount - videoStreamCount + 1
|
||||
MediaStreamType.VIDEO -> {
|
||||
serverIndex - externalSubtitleCount + 1
|
||||
}
|
||||
|
||||
MediaStreamType.AUDIO -> {
|
||||
serverIndex - externalSubtitleCount - videoStreamCount + 1
|
||||
}
|
||||
|
||||
MediaStreamType.SUBTITLE -> {
|
||||
if (subtitleIsExternal) {
|
||||
serverIndex + embeddedSubtitleCount + 1
|
||||
|
|
@ -162,7 +168,10 @@ object TrackSelectionUtils {
|
|||
serverIndex - externalSubtitleCount - videoStreamCount - audioStreamCount + 1
|
||||
}
|
||||
}
|
||||
else -> throw UnsupportedOperationException("Cannot calculate index for $type")
|
||||
|
||||
else -> {
|
||||
throw UnsupportedOperationException("Cannot calculate index for $type")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ fun <T> ComposablePreference(
|
|||
)
|
||||
}
|
||||
|
||||
is AppDestinationPreference ->
|
||||
is AppDestinationPreference -> {
|
||||
ClickPreference(
|
||||
title = title,
|
||||
onClick = {
|
||||
|
|
@ -112,8 +112,9 @@ fun <T> ComposablePreference(
|
|||
interactionSource = interactionSource,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is AppClickablePreference ->
|
||||
is AppClickablePreference -> {
|
||||
ClickPreference(
|
||||
title = title,
|
||||
onClick = { onClickPreference.invoke(preference) },
|
||||
|
|
@ -122,8 +123,9 @@ fun <T> ComposablePreference(
|
|||
interactionSource = interactionSource,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is AppSwitchPreference ->
|
||||
is AppSwitchPreference -> {
|
||||
SwitchPreference(
|
||||
title = title,
|
||||
value = value as Boolean,
|
||||
|
|
@ -132,8 +134,9 @@ fun <T> ComposablePreference(
|
|||
interactionSource = interactionSource,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is AppStringPreference ->
|
||||
is AppStringPreference -> {
|
||||
ClickPreference(
|
||||
title = title,
|
||||
onClick = {
|
||||
|
|
@ -164,6 +167,7 @@ fun <T> ComposablePreference(
|
|||
interactionSource = interactionSource,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is AppChoicePreference -> {
|
||||
val values = stringArrayResource(preference.displayValues).toList()
|
||||
|
|
|
|||
|
|
@ -456,7 +456,7 @@ fun PreferencesPage(
|
|||
PreferenceScreenOption.BASIC,
|
||||
PreferenceScreenOption.ADVANCED,
|
||||
PreferenceScreenOption.USER_INTERFACE,
|
||||
->
|
||||
-> {
|
||||
PreferencesContent(
|
||||
initialPreferences,
|
||||
preferenceScreenOption,
|
||||
|
|
@ -465,11 +465,13 @@ fun PreferencesPage(
|
|||
.fillMaxHeight()
|
||||
.align(Alignment.TopEnd),
|
||||
)
|
||||
}
|
||||
|
||||
PreferenceScreenOption.SUBTITLES ->
|
||||
PreferenceScreenOption.SUBTITLES -> {
|
||||
SubtitleStylePage(
|
||||
initialPreferences,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,17 +71,19 @@ fun SwitchColors(): SwitchColors {
|
|||
AppThemeColors.UNRECOGNIZED,
|
||||
AppThemeColors.PURPLE,
|
||||
AppThemeColors.BLUE,
|
||||
->
|
||||
-> {
|
||||
SwitchDefaults.colors()
|
||||
}
|
||||
|
||||
AppThemeColors.GREEN,
|
||||
AppThemeColors.ORANGE,
|
||||
AppThemeColors.BOLD_BLUE,
|
||||
AppThemeColors.OLED_BLACK,
|
||||
->
|
||||
-> {
|
||||
SwitchDefaults.colors(
|
||||
checkedThumbColor = MaterialTheme.colorScheme.onPrimary,
|
||||
uncheckedThumbColor = MaterialTheme.colorScheme.onPrimary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ object SubtitleSettings {
|
|||
val bg = combine(backgroundColor, backgroundOpacity)
|
||||
return CaptionStyleCompat(
|
||||
combine(fontColor, fontOpacity),
|
||||
if (backgroundStyle == BackgroundStyle.BG_WRAP)bg else 0,
|
||||
if (backgroundStyle == BackgroundStyle.BG_WRAP) bg else 0,
|
||||
if (backgroundStyle == BackgroundStyle.BG_BOXED) bg else 0,
|
||||
when (edgeStyle) {
|
||||
EdgeStyle.EDGE_NONE, EdgeStyle.UNRECOGNIZED -> CaptionStyleCompat.EDGE_TYPE_NONE
|
||||
|
|
@ -355,6 +355,7 @@ object SubtitleSettings {
|
|||
-> "outline-and-shadow"
|
||||
|
||||
BackgroundStyle.BG_WRAP -> "opaque-box"
|
||||
|
||||
BackgroundStyle.BG_BOXED -> "background-box"
|
||||
}
|
||||
MPVLib.setPropertyString("sub-border-style", borderStyle)
|
||||
|
|
|
|||
|
|
@ -174,10 +174,15 @@ fun InstallUpdatePage(
|
|||
}
|
||||
}
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state, modifier)
|
||||
is LoadingState.Error -> {
|
||||
ErrorMessage(state, modifier)
|
||||
}
|
||||
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage(modifier)
|
||||
-> {
|
||||
LoadingPage(modifier)
|
||||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
release?.let {
|
||||
|
|
|
|||
|
|
@ -72,11 +72,13 @@ fun ServerList(
|
|||
leadingContent = {
|
||||
when (status) {
|
||||
is ServerConnectionStatus.Success -> {}
|
||||
|
||||
ServerConnectionStatus.Pending -> {
|
||||
CircularProgress(
|
||||
Modifier.size(IconButtonDefaults.MediumIconSize),
|
||||
)
|
||||
}
|
||||
|
||||
is ServerConnectionStatus.Error -> {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Warning,
|
||||
|
|
@ -88,9 +90,15 @@ fun ServerList(
|
|||
},
|
||||
onClick = {
|
||||
when (status) {
|
||||
is ServerConnectionStatus.Success -> onSwitchServer.invoke(server)
|
||||
is ServerConnectionStatus.Success -> {
|
||||
onSwitchServer.invoke(server)
|
||||
}
|
||||
|
||||
ServerConnectionStatus.Pending -> {}
|
||||
is ServerConnectionStatus.Error -> onTestServer.invoke(server)
|
||||
|
||||
is ServerConnectionStatus.Error -> {
|
||||
onTestServer.invoke(server)
|
||||
}
|
||||
}
|
||||
},
|
||||
onLongClick = {
|
||||
|
|
|
|||
|
|
@ -30,15 +30,42 @@ data class TrackSupport(
|
|||
} else {
|
||||
val type =
|
||||
when (codecs) {
|
||||
MimeTypes.TEXT_VTT -> "vtt"
|
||||
MimeTypes.APPLICATION_VOBSUB -> "vobsub"
|
||||
MimeTypes.APPLICATION_SUBRIP -> "srt"
|
||||
MimeTypes.TEXT_SSA -> "ssa"
|
||||
MimeTypes.APPLICATION_PGS -> "pgs"
|
||||
MimeTypes.APPLICATION_DVBSUBS -> "dvd"
|
||||
MimeTypes.APPLICATION_TTML -> "ttml"
|
||||
MimeTypes.TEXT_UNKNOWN -> "unknown"
|
||||
null -> "unknown"
|
||||
MimeTypes.TEXT_VTT -> {
|
||||
"vtt"
|
||||
}
|
||||
|
||||
MimeTypes.APPLICATION_VOBSUB -> {
|
||||
"vobsub"
|
||||
}
|
||||
|
||||
MimeTypes.APPLICATION_SUBRIP -> {
|
||||
"srt"
|
||||
}
|
||||
|
||||
MimeTypes.TEXT_SSA -> {
|
||||
"ssa"
|
||||
}
|
||||
|
||||
MimeTypes.APPLICATION_PGS -> {
|
||||
"pgs"
|
||||
}
|
||||
|
||||
MimeTypes.APPLICATION_DVBSUBS -> {
|
||||
"dvd"
|
||||
}
|
||||
|
||||
MimeTypes.APPLICATION_TTML -> {
|
||||
"ttml"
|
||||
}
|
||||
|
||||
MimeTypes.TEXT_UNKNOWN -> {
|
||||
"unknown"
|
||||
}
|
||||
|
||||
null -> {
|
||||
"unknown"
|
||||
}
|
||||
|
||||
else -> {
|
||||
val split = codecs.split("/")
|
||||
if (split.size > 1) split[1] else codecs
|
||||
|
|
|
|||
|
|
@ -70,13 +70,19 @@ fun createDeviceProfile(
|
|||
) = buildDeviceProfile {
|
||||
val allowedAudioCodecs =
|
||||
when {
|
||||
downMixAudio -> downmixSupportedAudioCodecs
|
||||
!isAC3Enabled ->
|
||||
downMixAudio -> {
|
||||
downmixSupportedAudioCodecs
|
||||
}
|
||||
|
||||
!isAC3Enabled -> {
|
||||
supportedAudioCodecs
|
||||
.filterNot { it == Codec.Audio.EAC3 || it == Codec.Audio.AC3 }
|
||||
.toTypedArray()
|
||||
}
|
||||
|
||||
else -> supportedAudioCodecs
|
||||
else -> {
|
||||
supportedAudioCodecs
|
||||
}
|
||||
}
|
||||
|
||||
val supportsHevc = mediaTest.supportsHevc()
|
||||
|
|
@ -193,8 +199,11 @@ fun createDeviceProfile(
|
|||
|
||||
conditions {
|
||||
when {
|
||||
!supportsAVC -> ProfileConditionValue.VIDEO_PROFILE equals "none"
|
||||
else ->
|
||||
!supportsAVC -> {
|
||||
ProfileConditionValue.VIDEO_PROFILE equals "none"
|
||||
}
|
||||
|
||||
else -> {
|
||||
ProfileConditionValue.VIDEO_PROFILE inCollection
|
||||
listOfNotNull(
|
||||
"high",
|
||||
|
|
@ -203,6 +212,7 @@ fun createDeviceProfile(
|
|||
"constrained baseline",
|
||||
if (supportsAVCHigh10) "main 10" else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -276,13 +286,17 @@ fun createDeviceProfile(
|
|||
|
||||
conditions {
|
||||
when {
|
||||
!supportsHevc -> ProfileConditionValue.VIDEO_PROFILE equals "none"
|
||||
else ->
|
||||
!supportsHevc -> {
|
||||
ProfileConditionValue.VIDEO_PROFILE equals "none"
|
||||
}
|
||||
|
||||
else -> {
|
||||
ProfileConditionValue.VIDEO_PROFILE inCollection
|
||||
listOfNotNull(
|
||||
"main",
|
||||
if (supportsHevcMain10) "main 10" else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue