Remove ImageUtils

This commit is contained in:
Niels van Velzen
2024-05-18 21:54:07 +02:00
committed by Niels van Velzen
parent 53f2c6681d
commit 0971d8918e
16 changed files with 70 additions and 125 deletions

View File

@@ -25,7 +25,7 @@ import org.jellyfin.androidtv.data.repository.UserViewsRepository
import org.jellyfin.androidtv.integration.provider.ImageProvider
import org.jellyfin.androidtv.preference.UserPreferences
import org.jellyfin.androidtv.ui.startup.StartupActivity
import org.jellyfin.androidtv.util.ImageUtils
import org.jellyfin.androidtv.util.ImageHelper
import org.jellyfin.androidtv.util.dp
import org.jellyfin.androidtv.util.sdk.isUsable
import org.jellyfin.sdk.api.client.ApiClient
@@ -68,6 +68,7 @@ class LeanbackChannelWorker(
private val api by inject<ApiClient>()
private val userPreferences by inject<UserPreferences>()
private val userViewsRepository by inject<UserViewsRepository>()
private val imageHelper by inject<ImageHelper>()
/**
* Check if the app can use Leanback features and is API level 26 or higher.
@@ -257,7 +258,7 @@ class LeanbackChannelWorker(
tag = imageTags?.get(ImageType.PRIMARY),
)
else -> ImageUtils.getResourceUrl(context, R.drawable.tile_land_tv)
else -> imageHelper.getResourceUrl(context, R.drawable.tile_land_tv)
}.let(ImageProvider::getImageUri)
/**

View File

@@ -13,7 +13,7 @@ import kotlinx.coroutines.runBlocking
import org.jellyfin.androidtv.BuildConfig
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.integration.provider.ImageProvider
import org.jellyfin.androidtv.util.ImageUtils
import org.jellyfin.androidtv.util.ImageHelper
import org.jellyfin.androidtv.util.sdk.isUsable
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.exception.ApiClientException
@@ -41,6 +41,7 @@ class MediaContentProvider : ContentProvider(), KoinComponent {
}
private val api by inject<ApiClient>()
private val imageHelper by inject<ImageHelper>()
override fun onCreate(): Boolean = api.isUsable
@@ -106,7 +107,7 @@ class MediaContentProvider : ContentProvider(), KoinComponent {
val imageUri = if (item.imageTags?.contains(ImageType.PRIMARY) == true)
ImageProvider.getImageUri(api.imageApi.getItemImageUrl(item.id, ImageType.PRIMARY))
else
ImageUtils.getResourceUrl(context, R.drawable.tile_land_tv)
imageHelper.getResourceUrl(context!!, R.drawable.tile_land_tv)
cursor.newRow().apply {
add(BaseColumns._ID, item.id)

View File

@@ -13,7 +13,7 @@ import org.jellyfin.androidtv.preference.UserPreferences
import org.jellyfin.androidtv.preference.constant.ClockBehavior
import org.jellyfin.androidtv.ui.navigation.Destinations
import org.jellyfin.androidtv.ui.navigation.NavigationRepository
import org.jellyfin.androidtv.util.ImageUtils
import org.jellyfin.androidtv.util.ImageHelper
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
@@ -27,6 +27,7 @@ class ClockUserView @JvmOverloads constructor(
private val userPreferences by inject<UserPreferences>()
private val userRepository by inject<UserRepository>()
private val navigationRepository by inject<NavigationRepository>()
private val imageHelper by inject<ImageHelper>()
var isVideoPlayer = false
set(value) {
@@ -42,7 +43,7 @@ class ClockUserView @JvmOverloads constructor(
val currentUser = userRepository.currentUser.value
binding.clockUserImage.load(
url = currentUser?.let(ImageUtils::getPrimaryImageUrl),
url = currentUser?.let(imageHelper::getPrimaryImageUrl),
placeholder = ContextCompat.getDrawable(context, R.drawable.ic_user)
)

View File

@@ -14,9 +14,11 @@ import androidx.core.content.ContextCompat;
import org.jellyfin.androidtv.R;
import org.jellyfin.androidtv.ui.livetv.LiveTvGuide;
import org.jellyfin.androidtv.ui.livetv.LiveTvGuideFragment;
import org.jellyfin.androidtv.util.ImageUtils;
import org.jellyfin.androidtv.util.ImageHelper;
import org.jellyfin.androidtv.util.Utils;
import org.jellyfin.androidtv.util.sdk.compat.ModelCompat;
import org.jellyfin.apiclient.model.livetv.ChannelInfoDto;
import org.koin.java.KoinJavaComponent;
public class GuideChannelHeader extends RelativeLayout {
private AsyncImageView mChannelImage;
@@ -53,8 +55,9 @@ public class GuideChannelHeader extends RelativeLayout {
}
public void loadImage() {
ImageHelper imageHelper = KoinJavaComponent.<ImageHelper>get(ImageHelper.class);
mChannelImage.load(
ImageUtils.getPrimaryImageUrl(mChannel),
imageHelper.getPrimaryImageUrl(ModelCompat.asSdk(mChannel),null, ImageHelper.MAX_PRIMARY_IMAGE_HEIGHT),
null,
null,
0.0,

View File

@@ -14,7 +14,7 @@ import org.jellyfin.androidtv.ui.navigation.NavigationRepository
import org.jellyfin.androidtv.ui.playback.AudioEventListener
import org.jellyfin.androidtv.ui.playback.MediaManager
import org.jellyfin.androidtv.ui.playback.PlaybackController
import org.jellyfin.androidtv.util.ImageUtils
import org.jellyfin.androidtv.util.ImageHelper
import org.jellyfin.androidtv.util.TimeUtils
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
@@ -29,6 +29,7 @@ class NowPlayingView @JvmOverloads constructor(
private val mediaManager by inject<MediaManager>()
private val navigationRepository by inject<NavigationRepository>()
private val imageHelper by inject<ImageHelper>()
private var currentDuration: String = ""
init {
@@ -63,7 +64,7 @@ class NowPlayingView @JvmOverloads constructor(
private fun setInfo(item: org.jellyfin.sdk.model.api.BaseItemDto) {
val placeholder = ContextCompat.getDrawable(context, R.drawable.ic_album)
val blurHash = item.imageBlurHashes?.get(org.jellyfin.sdk.model.api.ImageType.PRIMARY)?.get(item.imageTags?.get(org.jellyfin.sdk.model.api.ImageType.PRIMARY))
binding.npIcon.load(ImageUtils.getPrimaryImageUrl(item), blurHash, placeholder, item.primaryImageAspectRatio ?: 1.0)
binding.npIcon.load(imageHelper.getPrimaryImageUrl(item), blurHash, placeholder, item.primaryImageAspectRatio ?: 1.0)
currentDuration = TimeUtils.formatMillis(if (item.runTimeTicks != null) item.runTimeTicks!! / 10_000 else 0)
binding.npDesc.text = if (item.albumArtist != null) item.albumArtist else item.name

View File

@@ -132,7 +132,6 @@ public class BrowseGridFragment extends Fragment implements View.OnKeyListener {
private final int MIN_NUM_CARDS = 5; // minimum number of visible cards we allow, this results in more empty space
private final double CARD_SPACING_PCT = 1.0; // 100% expressed as relative to the padding_left/top, which depends on the mCardFocusScale and AspectRatio
private final double CARD_SPACING_HORIZONTAL_BANNER_PCT = 0.5; // 50% allow horizontal card overlapping for banners, otherwise spacing is too large
private final int MIN_GRIDSIZE_CHANGE_DELTA = 4; // minimum pixel size changes, to trigger a recreate of the grid via onGridSizeMeasurements
private final int VIEW_SELECT_UPDATE_DELAY = 250; // delay in ms until we update the top-row info for a selected item
private boolean mDirty = true; // CardHeight, RowDef or GridSize changed
@@ -374,7 +373,7 @@ public class BrowseGridFragment extends Fragment implements View.OnKeyListener {
case THUMB:
return cardHeight * ImageHelper.ASPECT_RATIO_16_9;
case BANNER:
return cardHeight * CardPresenter.ASPECT_RATIO_BANNER;
return cardHeight * ImageHelper.ASPECT_RATIO_BANNER;
default:
throw new IllegalStateException("Unexpected value: " + imageType);
}
@@ -395,7 +394,7 @@ public class BrowseGridFragment extends Fragment implements View.OnKeyListener {
case THUMB:
return cardWidth / ImageHelper.ASPECT_RATIO_16_9;
case BANNER:
return cardWidth / CardPresenter.ASPECT_RATIO_BANNER;
return cardWidth / ImageHelper.ASPECT_RATIO_BANNER;
default:
throw new IllegalArgumentException("Unexpected value: " + imageType);
}

View File

@@ -20,7 +20,7 @@ import org.jellyfin.androidtv.ui.navigation.Destinations
import org.jellyfin.androidtv.ui.navigation.NavigationRepository
import org.jellyfin.androidtv.ui.playback.MediaManager
import org.jellyfin.androidtv.ui.startup.StartupActivity
import org.jellyfin.androidtv.util.ImageUtils
import org.jellyfin.androidtv.util.ImageHelper
import org.koin.android.ext.android.inject
class HomeFragment : Fragment() {
@@ -31,6 +31,7 @@ class HomeFragment : Fragment() {
private val userRepository by inject<UserRepository>()
private val navigationRepository by inject<NavigationRepository>()
private val mediaManager by inject<MediaManager>()
private val imageHelper by inject<ImageHelper>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
@@ -58,7 +59,7 @@ class HomeFragment : Fragment() {
.onEach { user ->
if (user != null) {
binding.switchUsersImage.load(
url = ImageUtils.getPrimaryImageUrl(user),
url = imageHelper.getPrimaryImageUrl(user),
placeholder = ContextCompat.getDrawable(requireContext(), R.drawable.ic_user)
)
}

View File

@@ -73,7 +73,7 @@ import org.jellyfin.androidtv.ui.presentation.InfoCardPresenter;
import org.jellyfin.androidtv.ui.presentation.MutableObjectAdapter;
import org.jellyfin.androidtv.ui.presentation.MyDetailsOverviewRowPresenter;
import org.jellyfin.androidtv.util.CoroutineUtils;
import org.jellyfin.androidtv.util.ImageUtils;
import org.jellyfin.androidtv.util.ImageHelper;
import org.jellyfin.androidtv.util.KeyProcessor;
import org.jellyfin.androidtv.util.MarkdownRenderer;
import org.jellyfin.androidtv.util.PlaybackHelper;
@@ -174,6 +174,7 @@ public class FullDetailsFragment extends Fragment implements RecordingIndicatorV
private final Lazy<ItemLauncher> itemLauncher = inject(ItemLauncher.class);
private final Lazy<KeyProcessor> keyProcessor = inject(KeyProcessor.class);
final Lazy<PlaybackHelper> playbackHelper = inject(PlaybackHelper.class);
private final Lazy<ImageHelper> imageHelper = inject(ImageHelper.class);
@Nullable
@Override
@@ -457,14 +458,14 @@ public class FullDetailsFragment extends Fragment implements RecordingIndicatorV
BaseItemDto item = params[0];
// Figure image size
Double aspect = ImageUtils.getImageAspectRatio(ModelCompat.asSdk(item), false);
Double aspect = imageHelper.getValue().getImageAspectRatio(ModelCompat.asSdk(item), false);
posterHeight = aspect > 1 ? Utils.convertDpToPixel(requireContext(), 160) : Utils.convertDpToPixel(requireContext(), ModelCompat.asSdk(item).getType() == BaseItemKind.PERSON || ModelCompat.asSdk(item).getType() == BaseItemKind.MUSIC_ARTIST ? 300 : 200);
mDetailsOverviewRow = new MyDetailsOverviewRow(ModelCompat.asSdk(item));
String primaryImageUrl = ImageUtils.getLogoImageUrl(ModelCompat.asSdk(mBaseItem), 600, true);
String primaryImageUrl = imageHelper.getValue().getLogoImageUrl(ModelCompat.asSdk(mBaseItem), 600, true);
if (primaryImageUrl == null) {
primaryImageUrl = ImageUtils.getPrimaryImageUrl(ModelCompat.asSdk(mBaseItem), false, null, posterHeight);
primaryImageUrl = imageHelper.getValue().getPrimaryImageUrl(ModelCompat.asSdk(mBaseItem), false, null, posterHeight);
if (item.getRunTimeTicks() != null && item.getRunTimeTicks() > 0 && item.getUserData() != null && item.getUserData().getPlaybackPositionTicks() > 0)
mDetailsOverviewRow.setProgress(((int) (item.getUserData().getPlaybackPositionTicks() * 100.0 / item.getRunTimeTicks())));
}

View File

@@ -44,7 +44,7 @@ import org.jellyfin.androidtv.ui.playback.MediaManager;
import org.jellyfin.androidtv.ui.playback.PlaybackController;
import org.jellyfin.androidtv.ui.playback.PlaybackLauncher;
import org.jellyfin.androidtv.ui.playback.VideoQueueManager;
import org.jellyfin.androidtv.util.ImageUtils;
import org.jellyfin.androidtv.util.ImageHelper;
import org.jellyfin.androidtv.util.InfoLayoutHelper;
import org.jellyfin.androidtv.util.PlaybackHelper;
import org.jellyfin.androidtv.util.Utils;
@@ -91,12 +91,13 @@ public class ItemListFragment extends Fragment implements View.OnKeyListener {
private Instant lastUpdated = Instant.now();
private final Lazy<DataRefreshService> dataRefreshService = inject(DataRefreshService.class);
private Lazy<BackgroundService> backgroundService = inject(BackgroundService.class);
private Lazy<MediaManager> mediaManager = inject(MediaManager.class);
private Lazy<VideoQueueManager> videoQueueManager = inject(VideoQueueManager.class);
private Lazy<NavigationRepository> navigationRepository = inject(NavigationRepository.class);
private final Lazy<BackgroundService> backgroundService = inject(BackgroundService.class);
private final Lazy<MediaManager> mediaManager = inject(MediaManager.class);
private final Lazy<VideoQueueManager> videoQueueManager = inject(VideoQueueManager.class);
private final Lazy<NavigationRepository> navigationRepository = inject(NavigationRepository.class);
private final Lazy<ItemLauncher> itemLauncher = inject(ItemLauncher.class);
private final Lazy<PlaybackHelper> playbackHelper = inject(PlaybackHelper.class);
private final Lazy<ImageHelper> imageHelper = inject(ImageHelper.class);
@Nullable
@Override
@@ -321,8 +322,8 @@ public class ItemListFragment extends Fragment implements View.OnKeyListener {
addButtons(BUTTON_SIZE);
mSummary.setText(mBaseItem.getOverview());
Double aspect = ImageUtils.getImageAspectRatio(item, false);
String primaryImageUrl = ImageUtils.getPrimaryImageUrl(item);
Double aspect = imageHelper.getValue().getImageAspectRatio(item, false);
String primaryImageUrl = imageHelper.getValue().getPrimaryImageUrl(item, null, ImageHelper.MAX_PRIMARY_IMAGE_HEIGHT);
mPoster.setPadding(0, 0, 0, 0);
mPoster.load(primaryImageUrl, null, ContextCompat.getDrawable(requireContext(), R.drawable.ic_album), aspect, 0);

View File

@@ -14,7 +14,7 @@ import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.constant.ImageType
import org.jellyfin.androidtv.data.model.ChapterItemInfo
import org.jellyfin.androidtv.ui.GridButton
import org.jellyfin.androidtv.util.ImageUtils
import org.jellyfin.androidtv.util.ImageHelper
import org.jellyfin.androidtv.util.TimeUtils
import org.jellyfin.androidtv.util.apiclient.LifecycleAwareResponse
import org.jellyfin.androidtv.util.apiclient.getSeriesOverview
@@ -33,9 +33,9 @@ import org.jellyfin.sdk.model.extensions.ticks
import org.jellyfin.sdk.model.serializer.toUUID
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
import org.koin.core.component.inject
import timber.log.Timber
import java.text.SimpleDateFormat
import org.jellyfin.apiclient.interaction.ApiClient as LegacyApiClient
open class BaseRowItem protected constructor(
val baseRowType: BaseRowType,
@@ -51,6 +51,8 @@ open class BaseRowItem protected constructor(
val gridButton: GridButton? = null,
var preferSeriesPoster: Boolean = false,
) : KoinComponent {
val imageHelper by inject<ImageHelper>()
// Start of constructor hell
@JvmOverloads
constructor(
@@ -159,17 +161,16 @@ open class BaseRowItem protected constructor(
BaseRowType.BaseItem,
BaseRowType.LiveTvProgram,
BaseRowType.LiveTvRecording -> {
val apiClient = get<LegacyApiClient>()
val seriesId = baseItem?.seriesId
val seriesPrimaryImageTag = baseItem?.seriesPrimaryImageTag
when {
preferSeriesPoster && seriesId != null && seriesPrimaryImageTag != null -> {
ImageUtils.getImageUrl(seriesId, org.jellyfin.apiclient.model.entities.ImageType.Primary, seriesPrimaryImageTag)
imageHelper.getImageUrl(seriesId, org.jellyfin.sdk.model.api.ImageType.PRIMARY, seriesPrimaryImageTag)
}
imageType == ImageType.BANNER -> ImageUtils.getBannerImageUrl(baseItem, fillWidth, fillHeight)
imageType == ImageType.THUMB -> ImageUtils.getThumbImageUrl(baseItem, fillWidth, fillHeight)
imageType == ImageType.BANNER -> imageHelper.getBannerImageUrl(requireNotNull(baseItem), fillWidth, fillHeight)
imageType == ImageType.THUMB -> imageHelper.getThumbImageUrl(requireNotNull(baseItem), fillWidth, fillHeight)
else -> getPrimaryImageUrl(context, fillHeight)
}
}
@@ -180,13 +181,13 @@ open class BaseRowItem protected constructor(
fun getPrimaryImageUrl(context: Context, fillHeight: Int) = when (baseRowType) {
BaseRowType.BaseItem,
BaseRowType.LiveTvProgram,
BaseRowType.LiveTvRecording -> ImageUtils.getPrimaryImageUrl(baseItem!!, preferParentThumb, null, fillHeight)
BaseRowType.LiveTvRecording -> imageHelper.getPrimaryImageUrl(baseItem!!, preferParentThumb, null, fillHeight)
BaseRowType.Person -> ImageUtils.getPrimaryImageUrl(basePerson!!, fillHeight)
BaseRowType.Person -> imageHelper.getPrimaryImageUrl(basePerson!!, fillHeight)
BaseRowType.Chapter -> chapterInfo?.imagePath
BaseRowType.LiveTvChannel -> ImageUtils.getPrimaryImageUrl(baseItem!!)
BaseRowType.GridButton -> gridButton?.imageRes?.let { ImageUtils.getResourceUrl(context, it) }
BaseRowType.SeriesTimer -> ImageUtils.getResourceUrl(context, R.drawable.tile_land_series_timer)
BaseRowType.LiveTvChannel -> imageHelper.getPrimaryImageUrl(baseItem!!)
BaseRowType.GridButton -> gridButton?.imageRes?.let { imageHelper.getResourceUrl(context, it) }
BaseRowType.SeriesTimer -> imageHelper.getResourceUrl(context, R.drawable.tile_land_series_timer)
}
fun getBaseItemType() = baseItem?.type

View File

@@ -44,7 +44,7 @@ import org.jellyfin.androidtv.ui.ScrollViewListener;
import org.jellyfin.androidtv.ui.navigation.Destinations;
import org.jellyfin.androidtv.ui.navigation.NavigationRepository;
import org.jellyfin.androidtv.util.CoroutineUtils;
import org.jellyfin.androidtv.util.ImageUtils;
import org.jellyfin.androidtv.util.ImageHelper;
import org.jellyfin.androidtv.util.InfoLayoutHelper;
import org.jellyfin.androidtv.util.PlaybackHelper;
import org.jellyfin.androidtv.util.TextUtilsKt;
@@ -112,10 +112,11 @@ public class LiveTvGuideFragment extends Fragment implements LiveTvGuide, View.O
private Handler mHandler = new Handler();
private Lazy<ApiClient> apiClient = inject(ApiClient.class);
private final Lazy<ApiClient> apiClient = inject(ApiClient.class);
private final Lazy<CustomMessageRepository> customMessageRepository = inject(CustomMessageRepository.class);
private final Lazy<NavigationRepository> navigationRepository = inject(NavigationRepository.class);
private final Lazy<PlaybackHelper> playbackHelper = inject(PlaybackHelper.class);
private final Lazy<ImageHelper> imageHelper = inject(ImageHelper.class);
@Nullable
@Override
@@ -805,7 +806,7 @@ public class LiveTvGuideFragment extends Fragment implements LiveTvGuide, View.O
if (mSelectedProgram.getId() != null) {
mDisplayDate.setText(TimeUtils.getFriendlyDate(requireContext(), TimeUtils.convertToLocalDate(mSelectedProgram.getStartDate())));
String url = ImageUtils.getPrimaryImageUrl(ModelCompat.asSdk(mSelectedProgram));
String url = imageHelper.getValue().getPrimaryImageUrl(ModelCompat.asSdk(mSelectedProgram), null, ImageHelper.MAX_PRIMARY_IMAGE_HEIGHT);
mImage.load(url, null, ContextCompat.getDrawable(requireContext(), R.drawable.blank10x10), 0, 0);
} else {
mImage.setImageResource(R.drawable.blank10x10);

View File

@@ -37,7 +37,7 @@ import org.jellyfin.androidtv.ui.itemhandling.BaseRowItem;
import org.jellyfin.androidtv.ui.navigation.Destinations;
import org.jellyfin.androidtv.ui.navigation.NavigationRepository;
import org.jellyfin.androidtv.ui.presentation.PositionableListRowPresenter;
import org.jellyfin.androidtv.util.ImageUtils;
import org.jellyfin.androidtv.util.ImageHelper;
import org.jellyfin.androidtv.util.KeyProcessor;
import org.jellyfin.androidtv.util.TimeUtils;
import org.jellyfin.androidtv.util.Utils;
@@ -81,10 +81,11 @@ public class AudioNowPlayingFragment extends Fragment {
private boolean queueRowHasFocus = false;
private Lazy<BackgroundService> backgroundService = inject(BackgroundService.class);
private Lazy<MediaManager> mediaManager = inject(MediaManager.class);
private Lazy<NavigationRepository> navigationRepository = inject(NavigationRepository.class);
private final Lazy<BackgroundService> backgroundService = inject(BackgroundService.class);
private final Lazy<MediaManager> mediaManager = inject(MediaManager.class);
private final Lazy<NavigationRepository> navigationRepository = inject(NavigationRepository.class);
private final Lazy<KeyProcessor> keyProcessor = inject(KeyProcessor.class);
private final Lazy<ImageHelper> imageHelper = inject(ImageHelper.class);
private PopupMenu popupMenu;
@@ -295,10 +296,10 @@ public class AudioNowPlayingFragment extends Fragment {
private void updatePoster() {
// Figure image size
Double aspect = ImageUtils.getImageAspectRatio(mBaseItem, false);
Double aspect = imageHelper.getValue().getImageAspectRatio(mBaseItem, false);
int posterHeight = aspect > 1 ? Utils.convertDpToPixel(requireContext(), 150) : Utils.convertDpToPixel(requireActivity(), 250);
String primaryImageUrl = ImageUtils.getPrimaryImageUrl(mBaseItem, false, null, posterHeight);
String primaryImageUrl = imageHelper.getValue().getPrimaryImageUrl(mBaseItem, false, null, posterHeight);
Timber.d("Audio Poster url: %s", primaryImageUrl);
mPoster.load(primaryImageUrl, null, ContextCompat.getDrawable(requireContext(), R.drawable.ic_album), aspect, 0);
}

View File

@@ -70,7 +70,7 @@ import org.jellyfin.androidtv.ui.presentation.MutableObjectAdapter;
import org.jellyfin.androidtv.ui.presentation.PositionableListRowPresenter;
import org.jellyfin.androidtv.ui.shared.PaddedLineBackgroundSpan;
import org.jellyfin.androidtv.util.CoroutineUtils;
import org.jellyfin.androidtv.util.ImageUtils;
import org.jellyfin.androidtv.util.ImageHelper;
import org.jellyfin.androidtv.util.InfoLayoutHelper;
import org.jellyfin.androidtv.util.TextUtilsKt;
import org.jellyfin.androidtv.util.TimeUtils;
@@ -165,6 +165,7 @@ public class CustomPlaybackOverlayFragment extends Fragment implements LiveTvGui
private final Lazy<CustomMessageRepository> customMessageRepository = inject(CustomMessageRepository.class);
private final Lazy<NavigationRepository> navigationRepository = inject(NavigationRepository.class);
private final Lazy<BackgroundService> backgroundService = inject(BackgroundService.class);
private final Lazy<ImageHelper> imageHelper = inject(ImageHelper.class);
private final PlaybackOverlayFragmentHelper helper = new PlaybackOverlayFragmentHelper(this);
@@ -1416,7 +1417,7 @@ public class CustomPlaybackOverlayFragment extends Fragment implements LiveTvGui
binding.itemTitle.setText(current.getName());
}
// Update the logo
String imageUrl = ImageUtils.getLogoImageUrl(current, 440, false);
String imageUrl = imageHelper.getValue().getLogoImageUrl(current, 440, false);
if (imageUrl != null) {
binding.itemLogo.setVisibility(View.VISIBLE);
binding.itemTitle.setVisibility(View.GONE);

View File

@@ -12,8 +12,6 @@ import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.leanback.widget.BaseCardView;
import androidx.leanback.widget.Presenter;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ViewTreeLifecycleOwner;
import org.jellyfin.androidtv.R;
import org.jellyfin.androidtv.constant.ImageType;
@@ -23,7 +21,6 @@ import org.jellyfin.androidtv.preference.constant.WatchedIndicatorBehavior;
import org.jellyfin.androidtv.ui.card.LegacyImageCardView;
import org.jellyfin.androidtv.ui.itemhandling.BaseRowItem;
import org.jellyfin.androidtv.util.ImageHelper;
import org.jellyfin.androidtv.util.ImageUtils;
import org.jellyfin.androidtv.util.Utils;
import org.jellyfin.sdk.model.api.BaseItemDto;
import org.jellyfin.sdk.model.api.BaseItemKind;
@@ -36,8 +33,6 @@ import java.util.Locale;
import java.util.Map;
public class CardPresenter extends Presenter {
public static final double ASPECT_RATIO_BANNER = 1000.0 / 185.0;
private int mStaticHeight = 150;
private ImageType mImageType = ImageType.POSTER;
private double aspect;
@@ -74,14 +69,12 @@ public class CardPresenter extends Presenter {
private BaseRowItem mItem;
private LegacyImageCardView mCardView;
private Drawable mDefaultCardImage;
private final LifecycleOwner lifecycleOwner;
public ViewHolder(View view, LifecycleOwner lifecycleOwner) {
public ViewHolder(View view) {
super(view);
mCardView = (LegacyImageCardView) view;
mDefaultCardImage = ContextCompat.getDrawable(mCardView.getContext(), R.drawable.tile_port_video);
this.lifecycleOwner = lifecycleOwner;
}
public int getCardWidth() {
@@ -106,11 +99,12 @@ public class CardPresenter extends Presenter {
boolean showWatched = true;
boolean showProgress = false;
if (imageType.equals(ImageType.BANNER)) {
aspect = ASPECT_RATIO_BANNER;
aspect = ImageHelper.ASPECT_RATIO_BANNER;
} else if (imageType.equals(ImageType.THUMB)) {
aspect = ImageHelper.ASPECT_RATIO_16_9;
} else {
aspect = Utils.getSafeValue(ImageUtils.getImageAspectRatio(itemDto, m.getPreferParentThumb()), ImageHelper.ASPECT_RATIO_7_9);
ImageHelper imageHelper = KoinJavaComponent.<ImageHelper>get(ImageHelper.class);
aspect = Utils.getSafeValue(imageHelper.getImageAspectRatio(itemDto, m.getPreferParentThumb()), ImageHelper.ASPECT_RATIO_7_9);
}
switch (itemDto.getType()) {
case AUDIO:
@@ -239,7 +233,7 @@ public class CardPresenter extends Presenter {
case LiveTvChannel:
org.jellyfin.sdk.model.api.BaseItemDto channel = mItem.getBaseItem();
// TODO: Is it even possible to have channels with banners or thumbs?
double tvAspect = imageType.equals(ImageType.BANNER) ? ASPECT_RATIO_BANNER :
double tvAspect = imageType.equals(ImageType.BANNER) ? ImageHelper.ASPECT_RATIO_BANNER :
imageType.equals(ImageType.THUMB) ? ImageHelper.ASPECT_RATIO_16_9 :
Utils.getSafeValue(channel.getPrimaryImageAspectRatio(), 1.0);
cardHeight = !m.getStaticHeight() ? tvAspect > 1 ? lHeight : pHeight : sHeight;
@@ -286,7 +280,7 @@ public class CardPresenter extends Presenter {
break;
case LiveTvRecording:
BaseItemDto recording = mItem.getBaseItem();
double recordingAspect = imageType.equals(ImageType.BANNER) ? ASPECT_RATIO_BANNER : (imageType.equals(ImageType.THUMB) ? ImageHelper.ASPECT_RATIO_16_9 : Utils.getSafeValue(recording.getPrimaryImageAspectRatio(), ImageHelper.ASPECT_RATIO_7_9));
double recordingAspect = imageType.equals(ImageType.BANNER) ? ImageHelper.ASPECT_RATIO_BANNER : (imageType.equals(ImageType.THUMB) ? ImageHelper.ASPECT_RATIO_16_9 : Utils.getSafeValue(recording.getPrimaryImageAspectRatio(), ImageHelper.ASPECT_RATIO_7_9));
cardHeight = !m.getStaticHeight() ? recordingAspect > 1 ? lHeight : pHeight : sHeight;
cardWidth = (int) ((recordingAspect) * cardHeight);
if (cardWidth < 5) {
@@ -355,7 +349,7 @@ public class CardPresenter extends Presenter {
@ColorInt int color = typedValue.data;
cardView.setBackgroundColor(color);
return new ViewHolder(cardView, ViewTreeLifecycleOwner.get(parent));
return new ViewHolder(cardView);
}
@Override
@@ -399,7 +393,7 @@ public class CardPresenter extends Presenter {
if (rowItem.getBaseItem() != null && rowItem.getBaseItem().getImageBlurHashes() != null) {
Map<String, String> blurHashMap;
String imageTag;
if (aspect == ASPECT_RATIO_BANNER) {
if (aspect == ImageHelper.ASPECT_RATIO_BANNER) {
blurHashMap = rowItem.getBaseItem().getImageBlurHashes().get(org.jellyfin.sdk.model.api.ImageType.BANNER);
imageTag = rowItem.getBaseItem().getImageTags().get(org.jellyfin.sdk.model.api.ImageType.BANNER);
} else if (aspect == ImageHelper.ASPECT_RATIO_2_3 && rowItem.getBaseItemType() == BaseItemKind.EPISODE && rowItem.getPreferSeriesPoster()) {

View File

@@ -20,6 +20,7 @@ class ImageHelper(
const val ASPECT_RATIO_2_3 = 2.0 / 3.0
const val ASPECT_RATIO_16_9 = 16.0 / 9.0
const val ASPECT_RATIO_7_9 = 7.0 / 9.0
const val ASPECT_RATIO_BANNER = 1000.0 / 185.0
const val MAX_PRIMARY_IMAGE_HEIGHT: Int = 370
}

View File

@@ -1,63 +0,0 @@
package org.jellyfin.androidtv.util;
import android.content.Context;
import androidx.annotation.AnyRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.jellyfin.androidtv.util.sdk.compat.ModelCompat;
import org.jellyfin.apiclient.model.entities.ImageType;
import org.jellyfin.apiclient.model.livetv.ChannelInfoDto;
import org.jellyfin.sdk.model.api.BaseItemDto;
import org.jellyfin.sdk.model.api.BaseItemPerson;
import org.jellyfin.sdk.model.api.UserDto;
import org.koin.java.KoinJavaComponent;
import java.util.UUID;
public class ImageUtils {
public static Double getImageAspectRatio(org.jellyfin.sdk.model.api.BaseItemDto item, boolean preferParentThumb) {
return KoinJavaComponent.<ImageHelper>get(ImageHelper.class).getImageAspectRatio(item, preferParentThumb);
}
public static String getPrimaryImageUrl(@NonNull BaseItemPerson item, @Nullable int maxHeight) {
return KoinJavaComponent.<ImageHelper>get(ImageHelper.class).getPrimaryImageUrl(item, maxHeight);
}
public static String getPrimaryImageUrl(@NonNull UserDto item) {
return KoinJavaComponent.<ImageHelper>get(ImageHelper.class).getPrimaryImageUrl(item);
}
public static String getPrimaryImageUrl(@NonNull org.jellyfin.sdk.model.api.BaseItemDto item) {
return KoinJavaComponent.<ImageHelper>get(ImageHelper.class).getPrimaryImageUrl(item, null, ImageHelper.MAX_PRIMARY_IMAGE_HEIGHT);
}
public static String getPrimaryImageUrl(ChannelInfoDto item) {
return KoinJavaComponent.<ImageHelper>get(ImageHelper.class).getPrimaryImageUrl(ModelCompat.asSdk(item), null, ImageHelper.MAX_PRIMARY_IMAGE_HEIGHT);
}
public static String getImageUrl(@NonNull UUID itemId, @NonNull ImageType imageType, @NonNull String imageTag) {
return KoinJavaComponent.<ImageHelper>get(ImageHelper.class).getImageUrl(itemId, ModelCompat.asSdk(imageType), imageTag);
}
public static String getBannerImageUrl(org.jellyfin.sdk.model.api.BaseItemDto item, int fillWidth, int fillHeight) {
return KoinJavaComponent.<ImageHelper>get(ImageHelper.class).getBannerImageUrl(item, fillWidth, fillHeight);
}
public static String getThumbImageUrl(BaseItemDto item, int fillWidth, int fillHeight) {
return KoinJavaComponent.<ImageHelper>get(ImageHelper.class).getThumbImageUrl(item, fillWidth, fillHeight);
}
public static String getPrimaryImageUrl(@NonNull org.jellyfin.sdk.model.api.BaseItemDto item, boolean preferParentThumb, @Nullable Integer fillWidth, @Nullable Integer fillHeight) {
return KoinJavaComponent.<ImageHelper>get(ImageHelper.class).getPrimaryImageUrl(item, preferParentThumb, fillWidth, fillHeight);
}
public static String getLogoImageUrl(@Nullable org.jellyfin.sdk.model.api.BaseItemDto item, int maxWidth, boolean useSeriesFallback) {
return KoinJavaComponent.<ImageHelper>get(ImageHelper.class).getLogoImageUrl(item, maxWidth, useSeriesFallback);
}
public static String getResourceUrl(Context context, @AnyRes int resourceId) {
return KoinJavaComponent.<ImageHelper>get(ImageHelper.class).getResourceUrl(context, resourceId);
}
}