mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Merge branch 'main' into fea/live-tv
This commit is contained in:
commit
0002dece8c
4 changed files with 96 additions and 1 deletions
|
|
@ -33,6 +33,7 @@ import androidx.compose.ui.focus.onFocusChanged
|
|||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
|
|
@ -100,6 +101,7 @@ fun SeriesDetails(
|
|||
val item by viewModel.item.observeAsState()
|
||||
val seasons by viewModel.seasons.observeAsState(ItemListAndMapping.empty())
|
||||
val people by viewModel.people.observeAsState(listOf())
|
||||
val similar by viewModel.similar.observeAsState(listOf())
|
||||
|
||||
var overviewDialog by remember { mutableStateOf<ItemDetailsDialogInfo?>(null) }
|
||||
var showWatchConfirmation by remember { mutableStateOf(false) }
|
||||
|
|
@ -118,6 +120,7 @@ fun SeriesDetails(
|
|||
series = item,
|
||||
seasons = seasons,
|
||||
people = people,
|
||||
similar = similar,
|
||||
played = played,
|
||||
modifier = modifier,
|
||||
onClickItem = { viewModel.navigateTo(it.destination()) },
|
||||
|
|
@ -180,6 +183,7 @@ fun SeriesDetailsContent(
|
|||
preferences: UserPreferences,
|
||||
series: BaseItem,
|
||||
seasons: ItemListAndMapping,
|
||||
similar: List<BaseItem>,
|
||||
people: List<Person>,
|
||||
played: Boolean,
|
||||
onClickItem: (BaseItem) -> Unit,
|
||||
|
|
@ -302,6 +306,28 @@ fun SeriesDetailsContent(
|
|||
)
|
||||
}
|
||||
}
|
||||
if (similar.isNotEmpty()) {
|
||||
item {
|
||||
ItemRow(
|
||||
title = stringResource(R.string.more_like_this),
|
||||
items = similar,
|
||||
onClickItem = onClickItem,
|
||||
onLongClickItem = {},
|
||||
cardContent = { index, item, mod, onClick, onLongClick ->
|
||||
SeasonCard(
|
||||
item = item,
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
modifier = mod,
|
||||
showImageOverlay = true,
|
||||
imageHeight = Cards.height2x3,
|
||||
imageWidth = Dp.Unspecified,
|
||||
)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,13 @@ import androidx.lifecycle.viewModelScope
|
|||
import androidx.media3.common.util.UnstableApi
|
||||
import com.github.damontecres.wholphin.data.ChosenStreams
|
||||
import com.github.damontecres.wholphin.data.ItemPlaybackRepository
|
||||
import com.github.damontecres.wholphin.data.ServerRepository
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.data.model.ItemPlayback
|
||||
import com.github.damontecres.wholphin.data.model.Person
|
||||
import com.github.damontecres.wholphin.preferences.ThemeSongVolume
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
import com.github.damontecres.wholphin.ui.letNotEmpty
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
|
|
@ -47,6 +49,7 @@ import org.jellyfin.sdk.model.api.MediaStreamType
|
|||
import org.jellyfin.sdk.model.api.SortOrder
|
||||
import org.jellyfin.sdk.model.api.request.GetEpisodesRequest
|
||||
import org.jellyfin.sdk.model.api.request.GetItemsRequest
|
||||
import org.jellyfin.sdk.model.api.request.GetSimilarItemsRequest
|
||||
import timber.log.Timber
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
|
|
@ -57,6 +60,7 @@ class SeriesViewModel
|
|||
constructor(
|
||||
api: ApiClient,
|
||||
@param:ApplicationContext val context: Context,
|
||||
private val serverRepository: ServerRepository,
|
||||
private val navigationManager: NavigationManager,
|
||||
private val itemPlaybackRepository: ItemPlaybackRepository,
|
||||
private val themeSongPlayer: ThemeSongPlayer,
|
||||
|
|
@ -67,6 +71,7 @@ class SeriesViewModel
|
|||
val seasons = MutableLiveData<ItemListAndMapping>(ItemListAndMapping.empty())
|
||||
val episodes = MutableLiveData<EpisodeList>(EpisodeList.Loading)
|
||||
val people = MutableLiveData<List<Person>>(listOf())
|
||||
val similar = MutableLiveData<List<BaseItem>>(listOf())
|
||||
|
||||
fun init(
|
||||
prefs: UserPreferences,
|
||||
|
|
@ -102,6 +107,18 @@ class SeriesViewModel
|
|||
people.map { Person.fromDto(it, api) }
|
||||
}.orEmpty()
|
||||
}
|
||||
val similar =
|
||||
api.libraryApi
|
||||
.getSimilarItems(
|
||||
GetSimilarItemsRequest(
|
||||
userId = serverRepository.currentUser?.id,
|
||||
itemId = itemId,
|
||||
fields = SlimItemFields,
|
||||
limit = 25,
|
||||
),
|
||||
).content.items
|
||||
.map { BaseItem.from(it, api, true) }
|
||||
this@SeriesViewModel.similar.setValueOnMain(similar)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ import coil3.compose.AsyncImage
|
|||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.ChosenStreams
|
||||
import com.github.damontecres.wholphin.data.ItemPlaybackRepository
|
||||
import com.github.damontecres.wholphin.data.ServerRepository
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.data.model.Chapter
|
||||
import com.github.damontecres.wholphin.data.model.ItemPlayback
|
||||
|
|
@ -54,7 +55,9 @@ import com.github.damontecres.wholphin.data.model.Person
|
|||
import com.github.damontecres.wholphin.data.model.chooseSource
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.ui.Cards
|
||||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||
import com.github.damontecres.wholphin.ui.cards.ChapterRow
|
||||
import com.github.damontecres.wholphin.ui.cards.ItemRow
|
||||
import com.github.damontecres.wholphin.ui.cards.PersonRow
|
||||
import com.github.damontecres.wholphin.ui.cards.SeasonCard
|
||||
import com.github.damontecres.wholphin.ui.components.DialogParams
|
||||
|
|
@ -76,6 +79,7 @@ import com.github.damontecres.wholphin.ui.launchIO
|
|||
import com.github.damontecres.wholphin.ui.letNotEmpty
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import com.github.damontecres.wholphin.ui.nav.NavigationManager
|
||||
import com.github.damontecres.wholphin.ui.setValueOnMain
|
||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||
import com.github.damontecres.wholphin.util.LoadingState
|
||||
|
|
@ -85,9 +89,11 @@ import kotlinx.coroutines.Job
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
import org.jellyfin.sdk.api.client.extensions.libraryApi
|
||||
import org.jellyfin.sdk.api.client.extensions.playStateApi
|
||||
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
|
||||
import org.jellyfin.sdk.model.api.MediaStreamType
|
||||
import org.jellyfin.sdk.model.api.request.GetSimilarItemsRequest
|
||||
import org.jellyfin.sdk.model.extensions.ticks
|
||||
import org.jellyfin.sdk.model.serializer.toUUID
|
||||
import java.util.UUID
|
||||
|
|
@ -100,13 +106,16 @@ class MovieViewModel
|
|||
constructor(
|
||||
api: ApiClient,
|
||||
val navigationManager: NavigationManager,
|
||||
val serverRepository: ServerRepository,
|
||||
val itemPlaybackRepository: ItemPlaybackRepository,
|
||||
) : LoadingItemViewModel(api) {
|
||||
private lateinit var itemId: UUID
|
||||
|
||||
val trailers = MutableLiveData<List<Trailer>>(listOf())
|
||||
val people = MutableLiveData<List<Person>>(listOf())
|
||||
val chapters = MutableLiveData<List<Chapter>>(listOf())
|
||||
val similar = MutableLiveData<List<BaseItem>>(listOf())
|
||||
val chosenStreams = MutableLiveData<ChosenStreams?>(null)
|
||||
val trailers = MutableLiveData<List<Trailer>>(listOf())
|
||||
|
||||
override fun init(
|
||||
itemId: UUID,
|
||||
|
|
@ -156,6 +165,19 @@ class MovieViewModel
|
|||
}.orEmpty()
|
||||
chapters.value = Chapter.fromDto(item.data, api)
|
||||
}
|
||||
|
||||
val similar =
|
||||
api.libraryApi
|
||||
.getSimilarItems(
|
||||
GetSimilarItemsRequest(
|
||||
userId = serverRepository.currentUser?.id,
|
||||
itemId = itemId,
|
||||
fields = SlimItemFields,
|
||||
limit = 25,
|
||||
),
|
||||
).content.items
|
||||
.map { BaseItem.from(it, api) }
|
||||
this@MovieViewModel.similar.setValueOnMain(similar)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -226,6 +248,7 @@ fun MovieDetails(
|
|||
val people by viewModel.people.observeAsState(listOf())
|
||||
val chapters by viewModel.chapters.observeAsState(listOf())
|
||||
val trailers by viewModel.trailers.observeAsState(listOf())
|
||||
val similar by viewModel.similar.observeAsState(listOf())
|
||||
val loading by viewModel.loading.observeAsState(LoadingState.Loading)
|
||||
val chosenStreams by viewModel.chosenStreams.observeAsState(null)
|
||||
|
||||
|
|
@ -247,6 +270,10 @@ fun MovieDetails(
|
|||
people = people,
|
||||
chapters = chapters,
|
||||
trailers = trailers,
|
||||
similar = similar,
|
||||
onClickItem = {
|
||||
viewModel.navigationManager.navigateTo(it.destination())
|
||||
},
|
||||
playOnClick = {
|
||||
viewModel.navigationManager.navigateTo(
|
||||
Destination.Playback(
|
||||
|
|
@ -375,11 +402,13 @@ fun MovieDetailsContent(
|
|||
people: List<Person>,
|
||||
chapters: List<Chapter>,
|
||||
trailers: List<Trailer>,
|
||||
similar: List<BaseItem>,
|
||||
playOnClick: (Duration) -> Unit,
|
||||
trailerOnClick: (Trailer) -> Unit,
|
||||
overviewOnClick: () -> Unit,
|
||||
watchOnClick: () -> Unit,
|
||||
moreOnClick: () -> Unit,
|
||||
onClickItem: (BaseItem) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
|
@ -492,6 +521,28 @@ fun MovieDetailsContent(
|
|||
)
|
||||
}
|
||||
}
|
||||
if (similar.isNotEmpty()) {
|
||||
item {
|
||||
ItemRow(
|
||||
title = stringResource(R.string.more_like_this),
|
||||
items = similar,
|
||||
onClickItem = onClickItem,
|
||||
onLongClickItem = {},
|
||||
cardContent = { index, item, mod, onClick, onLongClick ->
|
||||
SeasonCard(
|
||||
item = item,
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
modifier = mod,
|
||||
showImageOverlay = true,
|
||||
imageHeight = Cards.height2x3,
|
||||
imageWidth = Dp.Unspecified,
|
||||
)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,5 +84,6 @@
|
|||
<string name="direct_play_pgs">Direct play PGS subtitles</string>
|
||||
<string name="trailers">Trailers</string>
|
||||
<string name="pass_out_protection">Passout Protection</string>
|
||||
<string name="more_like_this">More like this</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue