Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement My media (small) home section #4011

Merged
merged 1 commit into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import org.jellyfin.androidtv.constant.QueryType;
import org.jellyfin.androidtv.data.querying.GetSeriesTimersRequest;
import org.jellyfin.androidtv.data.querying.GetSpecialsRequest;
import org.jellyfin.androidtv.data.querying.GetUserViewsRequest;
import org.jellyfin.sdk.model.api.request.GetAlbumArtistsRequest;
import org.jellyfin.sdk.model.api.request.GetArtistsRequest;
import org.jellyfin.sdk.model.api.request.GetItemsRequest;
Expand Down Expand Up @@ -138,12 +137,6 @@ public BrowseRowDef(String header, GetSimilarItemsRequest query, QueryType type)
this.queryType = type;
}

public BrowseRowDef(String header, GetUserViewsRequest query) {
headerText = header;
this.staticHeight = true;
this.queryType = QueryType.Views;
}

public BrowseRowDef(String header, GetResumeItemsRequest query, int chunkSize, boolean preferParentThumb, boolean staticHeight, ChangeTriggerType[] changeTriggers) {
headerText = header;
this.resumeQuery = query;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.content.Context
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.auth.repository.UserRepository
import org.jellyfin.androidtv.constant.ChangeTriggerType
import org.jellyfin.androidtv.data.querying.GetUserViewsRequest
import org.jellyfin.androidtv.data.repository.UserViewsRepository
import org.jellyfin.androidtv.ui.browsing.BrowseRowDef
import org.jellyfin.sdk.model.api.BaseItemKind
Expand All @@ -25,10 +24,6 @@ class HomeFragmentHelper(
return HomeFragmentLatestRow(userRepository, userViewsRepository)
}

fun loadLibraryTiles(): HomeFragmentRow {
return HomeFragmentBrowseRowDefRow(BrowseRowDef(context.getString(R.string.lbl_my_media), GetUserViewsRequest))
}

fun loadResume(title: String, includeMediaTypes: Collection<MediaType>): HomeFragmentRow {
val query = GetResumeItemsRequest(
limit = ITEM_LIMIT_RESUME,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.jellyfin.androidtv.ui.home

import android.content.Context
import androidx.leanback.widget.HeaderItem
import androidx.leanback.widget.ListRow
import androidx.leanback.widget.Row
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.data.querying.GetUserViewsRequest
import org.jellyfin.androidtv.ui.itemhandling.ItemRowAdapter
import org.jellyfin.androidtv.ui.presentation.CardPresenter
import org.jellyfin.androidtv.ui.presentation.MutableObjectAdapter
import org.jellyfin.androidtv.ui.presentation.UserViewCardPresenter

class HomeFragmentViewsRow(
val small: Boolean,
) : HomeFragmentRow {
private companion object {
val smallCardPresenter = UserViewCardPresenter(true)
val largeCardPresenter = UserViewCardPresenter(false)
}

override fun addToRowsAdapter(context: Context, cardPresenter: CardPresenter, rowsAdapter: MutableObjectAdapter<Row>) {
val presenter = if (small) smallCardPresenter else largeCardPresenter
val rowAdapter = ItemRowAdapter(context, GetUserViewsRequest, presenter, rowsAdapter)

val header = HeaderItem(context.getString(R.string.lbl_my_media))
val row = ListRow(header, rowAdapter)
rowAdapter.setRow(row)
rowAdapter.Retrieve()
rowsAdapter.add(row)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import org.jellyfin.androidtv.data.repository.CustomMessageRepository
import org.jellyfin.androidtv.data.repository.NotificationsRepository
import org.jellyfin.androidtv.data.repository.UserViewsRepository
import org.jellyfin.androidtv.data.service.BackgroundService
import org.jellyfin.androidtv.preference.UserPreferences
import org.jellyfin.androidtv.preference.UserSettingPreferences
import org.jellyfin.androidtv.ui.browsing.CompositeClickedListener
import org.jellyfin.androidtv.ui.browsing.CompositeSelectedListener
Expand Down Expand Up @@ -62,7 +61,6 @@ class HomeRowsFragment : RowsSupportFragment(), AudioEventListener, View.OnKeyLi
private val mediaManager by inject<MediaManager>()
private val notificationsRepository by inject<NotificationsRepository>()
private val userRepository by inject<UserRepository>()
private val userPreferences by inject<UserPreferences>()
private val userSettingPreferences by inject<UserSettingPreferences>()
private val userViewsRepository by inject<UserViewsRepository>()
private val dataRefreshService by inject<DataRefreshService>()
Expand Down Expand Up @@ -119,8 +117,8 @@ class HomeRowsFragment : RowsSupportFragment(), AudioEventListener, View.OnKeyLi
// Actually add the sections
for (section in homesections) when (section) {
HomeSectionType.LATEST_MEDIA -> rows.add(helper.loadRecentlyAdded())
HomeSectionType.LIBRARY_TILES_SMALL -> rows.add(helper.loadLibraryTiles())
HomeSectionType.LIBRARY_BUTTONS -> rows.add(helper.loadLibraryTiles())
HomeSectionType.LIBRARY_TILES_SMALL -> rows.add(HomeFragmentViewsRow(small = false))
HomeSectionType.LIBRARY_BUTTONS -> rows.add(HomeFragmentViewsRow(small = true))
HomeSectionType.RESUME -> rows.add(helper.loadResumeVideo())
HomeSectionType.RESUME_AUDIO -> rows.add(helper.loadResumeAudio())
HomeSectionType.RESUME_BOOK -> Unit // Books are not (yet) supported
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.jellyfin.androidtv.ui.presentation

import android.util.TypedValue
import android.view.ViewGroup
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import androidx.leanback.widget.Presenter
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.ui.card.LegacyImageCardView
import org.jellyfin.androidtv.ui.itemhandling.BaseRowItem
import org.jellyfin.androidtv.util.ImageHelper
import org.jellyfin.sdk.model.api.ImageType
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject

class UserViewCardPresenter(
val small: Boolean,
) : Presenter(), KoinComponent {
private val imageHelper by inject<ImageHelper>()

inner class ViewHolder(
private val cardView: LegacyImageCardView,
) : Presenter.ViewHolder(cardView) {
fun setItem(rowItem: BaseRowItem?) {
val baseItem = rowItem?.baseItem

// Load image
val imageTag = baseItem?.imageTags?.get(ImageType.PRIMARY)
val imageBlurhash = imageTag?.let { baseItem.imageBlurHashes?.get(ImageType.PRIMARY)?.get(it) }
val imageUrl = imageTag?.let { imageHelper.getImageUrl(baseItem.id, ImageType.PRIMARY, it) }
cardView.mainImageView.load(
url = imageUrl,
blurHash = imageBlurhash,
placeholder = ContextCompat.getDrawable(cardView.context, R.drawable.tile_land_folder),
aspectRatio = ImageHelper.ASPECT_RATIO_16_9,
blurHashResolution = 32,
)

// Set title
cardView.setTitleText(rowItem?.getName(cardView.context))

// Set size
if (small) {
cardView.setMainImageDimensions(133, 75)

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.
} else {
cardView.setMainImageDimensions(224, 126)

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.
}
}
}

override fun onCreateViewHolder(parent: ViewGroup): ViewHolder {
val cardView = LegacyImageCardView(parent.context, true)
cardView.isFocusable = true
cardView.isFocusableInTouchMode = true

val typedValue = TypedValue()
val theme = parent.context.theme
theme.resolveAttribute(R.attr.cardViewBackground, typedValue, true)
@ColorInt val color = typedValue.data
cardView.setBackgroundColor(color)

return ViewHolder(cardView)
}

override fun onBindViewHolder(viewHolder: Presenter.ViewHolder, item: Any) {
if (item !is BaseRowItem) return

(viewHolder as? ViewHolder)?.setItem(item)
}

override fun onUnbindViewHolder(viewHolder: Presenter.ViewHolder?) {
(viewHolder as? ViewHolder)?.setItem(null)
}
}
Loading