diff --git a/app/src/main/java/com/github/damontecres/wholphin/data/LibraryDisplayInfoDao.kt b/app/src/main/java/com/github/damontecres/wholphin/data/LibraryDisplayInfoDao.kt index 8e1b1ef2..0124ac3f 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/data/LibraryDisplayInfoDao.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/data/LibraryDisplayInfoDao.kt @@ -6,6 +6,7 @@ import androidx.room.OnConflictStrategy import androidx.room.Query import com.github.damontecres.wholphin.data.model.JellyfinUser import com.github.damontecres.wholphin.data.model.LibraryDisplayInfo +import com.github.damontecres.wholphin.ui.toServerString import java.util.UUID @Dao @@ -13,12 +14,17 @@ interface LibraryDisplayInfoDao { fun getItem( user: JellyfinUser, itemId: UUID, + ): LibraryDisplayInfo? = getItem(user.rowId, itemId.toServerString()) + + fun getItem( + user: JellyfinUser, + itemId: String, ): LibraryDisplayInfo? = getItem(user.rowId, itemId) @Query("SELECT * from LibraryDisplayInfo WHERE userId=:userId AND itemId=:itemId") fun getItem( userId: Int, - itemId: UUID, + itemId: String, ): LibraryDisplayInfo? @Insert(onConflict = OnConflictStrategy.REPLACE) diff --git a/app/src/main/java/com/github/damontecres/wholphin/data/model/LibraryDisplayInfo.kt b/app/src/main/java/com/github/damontecres/wholphin/data/model/LibraryDisplayInfo.kt index d428f521..34390cc3 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/data/model/LibraryDisplayInfo.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/data/model/LibraryDisplayInfo.kt @@ -7,6 +7,7 @@ import androidx.room.ForeignKey import androidx.room.Ignore import androidx.room.Index import com.github.damontecres.wholphin.ui.data.SortAndDirection +import com.github.damontecres.wholphin.ui.toServerString import kotlinx.serialization.Serializable import kotlinx.serialization.Transient import kotlinx.serialization.UseSerializers @@ -31,10 +32,17 @@ import java.util.UUID @Serializable data class LibraryDisplayInfo( val userId: Int, - val itemId: UUID, + val itemId: String, val sort: ItemSortBy, val direction: SortOrder, ) { + constructor( + userId: Int, + itemId: UUID, + sort: ItemSortBy, + direction: SortOrder, + ) : this(userId, itemId.toServerString(), sort, direction) + @Ignore @Transient val sortAndDirection = SortAndDirection(sort, direction) } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderGrid.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderGrid.kt index 31bd0245..fa65dc3e 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderGrid.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderGrid.kt @@ -37,12 +37,10 @@ import com.github.damontecres.wholphin.data.model.LibraryDisplayInfo import com.github.damontecres.wholphin.preferences.UserPreferences import com.github.damontecres.wholphin.ui.OneTimeLaunchedEffect import com.github.damontecres.wholphin.ui.SlimItemFields -import com.github.damontecres.wholphin.ui.data.MovieSortOptions -import com.github.damontecres.wholphin.ui.data.SeriesSortOptions import com.github.damontecres.wholphin.ui.data.SortAndDirection -import com.github.damontecres.wholphin.ui.data.VideoSortOptions import com.github.damontecres.wholphin.ui.detail.CardGrid import com.github.damontecres.wholphin.ui.detail.ItemViewModel +import com.github.damontecres.wholphin.ui.toServerString import com.github.damontecres.wholphin.ui.tryRequestFocus import com.github.damontecres.wholphin.util.ApiRequestPager import com.github.damontecres.wholphin.util.GetItemsRequestHandler @@ -61,6 +59,7 @@ import org.jellyfin.sdk.model.api.ImageType import org.jellyfin.sdk.model.api.ItemSortBy import org.jellyfin.sdk.model.api.SortOrder import org.jellyfin.sdk.model.api.request.GetItemsRequest +import org.jellyfin.sdk.model.serializer.toUUIDOrNull import java.util.UUID import javax.inject.Inject @@ -79,8 +78,7 @@ class CollectionFolderViewModel val filter = MutableLiveData(GetItemsFilter()) fun init( - itemId: UUID?, - potential: BaseItem?, + itemId: String, initialSortAndDirection: SortAndDirection?, recursive: Boolean, filter: GetItemsFilter, @@ -91,19 +89,21 @@ class CollectionFolderViewModel context.getString(R.string.error_loading_collection, itemId), ) + Dispatchers.IO, ) { - if (itemId != null) { - fetchItem(itemId) - - val sortAndDirection = - if (initialSortAndDirection == null) { - serverRepository.currentUser?.let { user -> - libraryDisplayInfoDao.getItem(user, itemId)?.sortAndDirection - } ?: SortAndDirection.DEFAULT - } else { - SortAndDirection.DEFAULT - } - loadResults(sortAndDirection, recursive, filter) + this@CollectionFolderViewModel.itemId = itemId + itemId?.toUUIDOrNull()?.let { + fetchItem(it) } + + val sortAndDirection = + if (initialSortAndDirection == null) { + serverRepository.currentUser?.let { user -> + libraryDisplayInfoDao.getItem(user, itemId)?.sortAndDirection + } ?: SortAndDirection.DEFAULT + } else { + SortAndDirection.DEFAULT + } + + loadResults(sortAndDirection, recursive, filter) } fun onSortChange( @@ -238,11 +238,36 @@ class CollectionFolderViewModel @Composable fun CollectionFolderGrid( preferences: UserPreferences, - itemId: UUID?, - item: BaseItem?, + itemId: UUID, initialFilter: GetItemsFilter, recursive: Boolean, onClickItem: (BaseItem) -> Unit, + sortOptions: List, + modifier: Modifier = Modifier, + initialSortAndDirection: SortAndDirection? = null, + showTitle: Boolean = true, + positionCallback: ((columns: Int, position: Int) -> Unit)? = null, +) = CollectionFolderGrid( + preferences, + itemId.toServerString(), + initialFilter, + recursive, + onClickItem, + sortOptions, + modifier, + initialSortAndDirection = initialSortAndDirection, + showTitle = showTitle, + positionCallback = positionCallback, +) + +@Composable +fun CollectionFolderGrid( + preferences: UserPreferences, + itemId: String, + initialFilter: GetItemsFilter, + recursive: Boolean, + onClickItem: (BaseItem) -> Unit, + sortOptions: List, modifier: Modifier = Modifier, viewModel: CollectionFolderViewModel = hiltViewModel(), initialSortAndDirection: SortAndDirection? = null, @@ -250,7 +275,7 @@ fun CollectionFolderGrid( positionCallback: ((columns: Int, position: Int) -> Unit)? = null, ) { OneTimeLaunchedEffect { - viewModel.init(itemId, item, initialSortAndDirection, recursive, initialFilter) + viewModel.init(itemId, initialSortAndDirection, recursive, initialFilter) } val sortAndDirection by viewModel.sortAndDirection.observeAsState() val filter by viewModel.filter.observeAsState(initialFilter) @@ -276,6 +301,7 @@ fun CollectionFolderGrid( viewModel.onSortChange(it, recursive, filter) }, showTitle = showTitle, + sortOptions = sortOptions, positionCallback = positionCallback, letterPosition = { viewModel.positionOfLetter(it) ?: -1 }, ) @@ -293,18 +319,12 @@ fun CollectionFolderGridContent( onClickItem: (BaseItem) -> Unit, onSortChange: (SortAndDirection) -> Unit, letterPosition: suspend (Char) -> Int, + sortOptions: List, modifier: Modifier = Modifier, showTitle: Boolean = true, positionCallback: ((columns: Int, position: Int) -> Unit)? = null, ) { val title = item?.name ?: item?.data?.collectionType?.name ?: stringResource(R.string.collection) - val sortOptions = - when (item?.data?.collectionType) { - CollectionType.MOVIES -> MovieSortOptions - CollectionType.TVSHOWS -> SeriesSortOptions - CollectionType.HOMEVIDEOS -> VideoSortOptions - else -> listOf(ItemSortBy.SORT_NAME, ItemSortBy.DATE_CREATED, ItemSortBy.RANDOM) - } var showHeader by rememberSaveable { mutableStateOf(true) } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/data/SortAndDirection.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/data/SortAndDirection.kt index ac0808a5..3cb6635b 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/data/SortAndDirection.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/data/SortAndDirection.kt @@ -45,6 +45,15 @@ val SeriesSortOptions = ItemSortBy.RANDOM, ) +val EpisodeSortOptions = + listOf( + ItemSortBy.SORT_NAME, + ItemSortBy.DATE_CREATED, + ItemSortBy.DATE_PLAYED, + ItemSortBy.AIRED_EPISODE_ORDER, + ItemSortBy.RANDOM, + ) + val VideoSortOptions = listOf( ItemSortBy.SORT_NAME, @@ -56,14 +65,19 @@ val VideoSortOptions = @StringRes fun getStringRes(sort: ItemSortBy): Int = when (sort) { - ItemSortBy.SORT_NAME -> R.string.sort_by_name + ItemSortBy.SORT_NAME, + ItemSortBy.SERIES_SORT_NAME, + -> 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 -> R.string.sort_by_date_played + ItemSortBy.DATE_PLAYED, + ItemSortBy.SERIES_DATE_PLAYED, + -> 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.PLAY_COUNT -> R.string.play_count + ItemSortBy.AIRED_EPISODE_ORDER -> R.string.aired_episode_order else -> throw IllegalArgumentException("Unsupported sort option: $sort") } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderGeneric.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderGeneric.kt index cbf0f3ee..06d49e1d 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderGeneric.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderGeneric.kt @@ -13,6 +13,7 @@ import com.github.damontecres.wholphin.data.model.BaseItem import com.github.damontecres.wholphin.data.model.GetItemsFilter import com.github.damontecres.wholphin.preferences.UserPreferences import com.github.damontecres.wholphin.ui.components.CollectionFolderGrid +import com.github.damontecres.wholphin.ui.data.VideoSortOptions import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel import java.util.UUID @@ -31,10 +32,10 @@ fun CollectionFolderGeneric( preferences = preferences, onClickItem = { preferencesViewModel.navigationManager.navigateTo(it.destination()) }, itemId = itemId, - item = item, initialFilter = filter, showTitle = showHeader, recursive = recursive, + sortOptions = VideoSortOptions, modifier = modifier .padding(start = 16.dp), diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderLiveTv.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderLiveTv.kt index 1716a926..76794b73 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderLiveTv.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderLiveTv.kt @@ -41,6 +41,7 @@ import com.github.damontecres.wholphin.data.model.GetItemsFilter import com.github.damontecres.wholphin.preferences.UserPreferences import com.github.damontecres.wholphin.ui.components.CollectionFolderGrid import com.github.damontecres.wholphin.ui.components.ErrorMessage +import com.github.damontecres.wholphin.ui.data.VideoSortOptions import com.github.damontecres.wholphin.ui.detail.livetv.DvrSchedule import com.github.damontecres.wholphin.ui.detail.livetv.TvGuideGrid import com.github.damontecres.wholphin.ui.ifElse @@ -204,10 +205,10 @@ fun CollectionFolderLiveTv( preferences = preferences, onClickItem = onClickItem, itemId = folders[folderIndex].id, - item = null, initialFilter = GetItemsFilter(), showTitle = showHeader, recursive = false, + sortOptions = VideoSortOptions, modifier = Modifier .padding(start = 16.dp), diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderMovie.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderMovie.kt index c9cc3e59..8fddd0bc 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderMovie.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderMovie.kt @@ -38,6 +38,8 @@ import com.github.damontecres.wholphin.ui.components.CollectionFolderGrid import com.github.damontecres.wholphin.ui.components.ErrorMessage import com.github.damontecres.wholphin.ui.components.GenreCardGrid import com.github.damontecres.wholphin.ui.components.RecommendedMovie +import com.github.damontecres.wholphin.ui.data.MovieSortOptions +import com.github.damontecres.wholphin.ui.data.VideoSortOptions import com.github.damontecres.wholphin.ui.ifElse import com.github.damontecres.wholphin.ui.nav.Destination import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel @@ -160,13 +162,13 @@ fun CollectionFolderMovie( preferences = preferences, onClickItem = onClickItem, itemId = destination.itemId, - item = destination.item, initialFilter = GetItemsFilter( includeItemTypes = listOf(BaseItemKind.MOVIE), ), showTitle = false, recursive = true, + sortOptions = MovieSortOptions, modifier = Modifier .padding(start = 16.dp) @@ -182,13 +184,13 @@ fun CollectionFolderMovie( preferences = preferences, onClickItem = onClickItem, itemId = destination.itemId, - item = destination.item, initialFilter = GetItemsFilter( includeItemTypes = listOf(BaseItemKind.BOX_SET), ), showTitle = false, recursive = true, + sortOptions = VideoSortOptions, modifier = Modifier .padding(start = 16.dp) diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderTv.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderTv.kt index bb659e96..8b63fe27 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderTv.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderTv.kt @@ -38,6 +38,7 @@ import com.github.damontecres.wholphin.ui.components.CollectionFolderGrid import com.github.damontecres.wholphin.ui.components.ErrorMessage import com.github.damontecres.wholphin.ui.components.GenreCardGrid import com.github.damontecres.wholphin.ui.components.RecommendedTvShow +import com.github.damontecres.wholphin.ui.data.SeriesSortOptions import com.github.damontecres.wholphin.ui.ifElse import com.github.damontecres.wholphin.ui.nav.Destination import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel @@ -158,13 +159,13 @@ fun CollectionFolderTv( CollectionFolderGrid( preferences = preferences, itemId = destination.itemId, - item = destination.item, initialFilter = GetItemsFilter( includeItemTypes = listOf(BaseItemKind.SERIES), ), showTitle = false, recursive = true, + sortOptions = SeriesSortOptions, modifier = Modifier .padding(start = 16.dp) diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/FavoritesPage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/FavoritesPage.kt index 7365452e..3546c8de 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/FavoritesPage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/FavoritesPage.kt @@ -36,6 +36,9 @@ import com.github.damontecres.wholphin.data.model.GetItemsFilter import com.github.damontecres.wholphin.preferences.UserPreferences import com.github.damontecres.wholphin.ui.components.CollectionFolderGrid import com.github.damontecres.wholphin.ui.components.ErrorMessage +import com.github.damontecres.wholphin.ui.data.EpisodeSortOptions +import com.github.damontecres.wholphin.ui.data.MovieSortOptions +import com.github.damontecres.wholphin.ui.data.SeriesSortOptions import com.github.damontecres.wholphin.ui.nav.NavDrawerItem import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel import com.github.damontecres.wholphin.ui.tryRequestFocus @@ -147,8 +150,7 @@ fun FavoritesPage( CollectionFolderGrid( preferences = preferences, onClickItem = onClickItem, - itemId = null, - item = null, + itemId = "${NavDrawerItem.Favorites.id}_movies", initialFilter = GetItemsFilter( favorite = true, @@ -156,6 +158,7 @@ fun FavoritesPage( ), showTitle = false, recursive = true, + sortOptions = MovieSortOptions, modifier = Modifier .padding(start = 16.dp) @@ -170,8 +173,7 @@ fun FavoritesPage( CollectionFolderGrid( preferences = preferences, onClickItem = onClickItem, - itemId = null, - item = null, + itemId = "${NavDrawerItem.Favorites.id}_series", initialFilter = GetItemsFilter( favorite = true, @@ -179,6 +181,7 @@ fun FavoritesPage( ), showTitle = false, recursive = true, + sortOptions = SeriesSortOptions, modifier = Modifier .padding(start = 16.dp) @@ -193,8 +196,7 @@ fun FavoritesPage( CollectionFolderGrid( preferences = preferences, onClickItem = onClickItem, - itemId = null, - item = null, + itemId = "${NavDrawerItem.Favorites.id}_episodes", initialFilter = GetItemsFilter( favorite = true, @@ -202,6 +204,7 @@ fun FavoritesPage( ), showTitle = false, recursive = true, + sortOptions = EpisodeSortOptions, modifier = Modifier .padding(start = 16.dp) diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/ItemViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/ItemViewModel.kt index fec6162a..d917b47a 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/ItemViewModel.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/ItemViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.github.damontecres.wholphin.data.model.BaseItem import com.github.damontecres.wholphin.ui.setValueOnMain +import com.github.damontecres.wholphin.ui.toServerString import com.github.damontecres.wholphin.util.LoadingExceptionHandler import com.github.damontecres.wholphin.util.LoadingState import kotlinx.coroutines.Deferred @@ -25,11 +26,13 @@ abstract class ItemViewModel( val api: ApiClient, ) : ViewModel() { val item = MutableLiveData(null) - lateinit var itemId: UUID + lateinit var itemId: String + lateinit var itemUuid: UUID suspend fun fetchItem(itemId: UUID): BaseItem = withContext(Dispatchers.IO) { - this@ItemViewModel.itemId = itemId + this@ItemViewModel.itemId = itemId.toServerString() + this@ItemViewModel.itemUuid = itemId val it = api.userLibraryApi.getItem(itemId).content val fetchedItem = BaseItem.from(it, api) return@withContext fetchedItem.let { diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/movie/MovieViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/movie/MovieViewModel.kt index 7284ba51..a384e016 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/movie/MovieViewModel.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/movie/MovieViewModel.kt @@ -129,21 +129,21 @@ class MovieViewModel fun setWatched(played: Boolean) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) { if (played) { - api.playStateApi.markPlayedItem(itemId) + api.playStateApi.markPlayedItem(itemUuid) } else { - api.playStateApi.markUnplayedItem(itemId) + api.playStateApi.markUnplayedItem(itemUuid) } - fetchAndSetItem(itemId) + fetchAndSetItem(itemUuid) } fun setFavorite(favorite: Boolean) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) { if (favorite) { - api.userLibraryApi.markFavoriteItem(itemId) + api.userLibraryApi.markFavoriteItem(itemUuid) } else { - api.userLibraryApi.unmarkFavoriteItem(itemId) + api.userLibraryApi.unmarkFavoriteItem(itemUuid) } - fetchAndSetItem(itemId) + fetchAndSetItem(itemUuid) } fun savePlayVersion( diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f93ff923..1075cfb5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -138,6 +138,7 @@ Watch live %1$d years old Play with transcoding + Aired Episode Order %d downloads